[SDAG] Fix expansion of BITREVERSE
authorJames Molloy <james.molloy@arm.com>
Fri, 13 Nov 2015 10:02:36 +0000 (10:02 +0000)
committerJames Molloy <james.molloy@arm.com>
Fri, 13 Nov 2015 10:02:36 +0000 (10:02 +0000)
Richard Trieu noted that UBSan detected an overflowing shift, and the obvious fix caused a crash.

What was happening was that the shiftee (1U) was indeed too small for the possible range of shifts it had to handle, but also we were using "VT.getSizeInBits()" to get the maximum type bitwidth, but we wanted "VT.getScalarSizeInBits()" to get the vector lane size instead of the entire vector size.

Use an APInt for the shift and VT.getScalarSizeInBits().

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@253023 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
test/CodeGen/AArch64/bitreverse.ll

index 186697d3d0240091fe90d2d86ab97849aebd56bd..e3a11cd27e1797c52965909efdf0712cb7ac92ae 100644 (file)
@@ -2780,7 +2780,7 @@ SDValue SelectionDAGLegalize::PromoteLegalFP_TO_INT(SDValue LegalOp,
 SDValue SelectionDAGLegalize::ExpandBITREVERSE(SDValue Op, SDLoc dl) {
   EVT VT = Op.getValueType();
   EVT SHVT = TLI.getShiftAmountTy(VT, DAG.getDataLayout());
-  unsigned Sz = VT.getSizeInBits();
+  unsigned Sz = VT.getScalarSizeInBits();
   
   SDValue Tmp, Tmp2;
   Tmp = DAG.getConstant(0, dl, VT);
@@ -2791,8 +2791,10 @@ SDValue SelectionDAGLegalize::ExpandBITREVERSE(SDValue Op, SDLoc dl) {
     else
       Tmp2 =
           DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(I - J, dl, SHVT));
-    Tmp2 =
-        DAG.getNode(ISD::AND, dl, VT, Tmp2, DAG.getConstant(1U << J, dl, VT));
+    
+    APInt Shift(Sz, 1);
+    Shift = Shift.shl(J);
+    Tmp2 = DAG.getNode(ISD::AND, dl, VT, Tmp2, DAG.getConstant(Shift, dl, VT));
     Tmp = DAG.getNode(ISD::OR, dl, VT, Tmp, Tmp2);
   }
 
index b780412f765e0f72bbf352c2adf7222273af76d0..702581789bb7a9c35c87588770b31cee3d2e3be3 100644 (file)
@@ -21,3 +21,48 @@ define i8 @g(i8 %a) {
   %b = call i8 @llvm.bitreverse.i8(i8 %a)
   ret i8 %b
 }
+
+declare <8 x i8> @llvm.bitreverse.v8i8(<8 x i8>) readnone
+
+define <8 x i8> @g_vec(<8 x i8> %a) {
+; Try and match as much of the sequence as precisely as possible.
+
+; CHECK-LABEL: g_vec:
+; CHECK-DAG: movi [[M1:v.*]], #0x80
+; CHECK-DAG: movi [[M2:v.*]], #0x40
+; CHECK-DAG: movi [[M3:v.*]], #0x20
+; CHECK-DAG: movi [[M4:v.*]], #0x10
+; CHECK-DAG: movi [[M5:v.*]], #0x8
+; CHECK-DAG: movi [[M6:v.*]], #0x4{{$}}
+; CHECK-DAG: movi [[M7:v.*]], #0x2{{$}}
+; CHECK-DAG: movi [[M8:v.*]], #0x1{{$}}
+; CHECK-DAG: shl  [[S1:v.*]], v0.8b, #7
+; CHECK-DAG: shl  [[S2:v.*]], v0.8b, #5
+; CHECK-DAG: shl  [[S3:v.*]], v0.8b, #3
+; CHECK-DAG: shl  [[S4:v.*]], v0.8b, #1
+; CHECK-DAG: ushr [[S5:v.*]], v0.8b, #1
+; CHECK-DAG: ushr [[S6:v.*]], v0.8b, #3
+; CHECK-DAG: ushr [[S7:v.*]], v0.8b, #5
+; CHECK-DAG: ushr [[S8:v.*]], v0.8b, #7
+; CHECK-DAG: and  [[A1:v.*]], [[S1]], [[M1]]
+; CHECK-DAG: and  [[A2:v.*]], [[S2]], [[M2]]
+; CHECK-DAG: and  [[A3:v.*]], [[S3]], [[M3]]
+; CHECK-DAG: and  [[A4:v.*]], [[S4]], [[M4]]
+; CHECK-DAG: and  [[A5:v.*]], [[S5]], [[M5]]
+; CHECK-DAG: and  [[A6:v.*]], [[S6]], [[M6]]
+; CHECK-DAG: and  [[A7:v.*]], [[S7]], [[M7]]
+; CHECK-DAG: and  [[A8:v.*]], [[S8]], [[M8]]
+
+; The rest can be ORRed together in any order; it's not worth the test
+; maintenance to match them precisely.
+; CHECK-DAG: orr
+; CHECK-DAG: orr
+; CHECK-DAG: orr
+; CHECK-DAG: orr
+; CHECK-DAG: orr
+; CHECK-DAG: orr
+; CHECK-DAG: orr
+; CHECK: ret
+  %b = call <8 x i8> @llvm.bitreverse.v8i8(<8 x i8> %a)
+  ret <8 x i8> %b
+}