[InstCombine] fix rotate narrowing bug for non-pow-2 types
authorSanjay Patel <spatel@rotateright.com>
Thu, 15 Nov 2018 17:19:14 +0000 (17:19 +0000)
committerSanjay Patel <spatel@rotateright.com>
Thu, 15 Nov 2018 17:19:14 +0000 (17:19 +0000)
llvm-svn: 346968

llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
llvm/test/Transforms/InstCombine/rotate.ll

index a934e0a..582f69f 100644 (file)
@@ -498,6 +498,13 @@ Instruction *InstCombiner::narrowRotate(TruncInst &Trunc) {
           shouldChangeType(Trunc.getSrcTy(), Trunc.getType())) &&
          "Don't narrow to an illegal scalar type");
 
+  // Bail out on strange types. It is possible to handle some of these patterns
+  // even with non-power-of-2 sizes, but it is not a likely scenario.
+  Type *DestTy = Trunc.getType();
+  unsigned NarrowWidth = DestTy->getScalarSizeInBits();
+  if (!isPowerOf2_32(NarrowWidth))
+    return nullptr;
+
   // First, find an or'd pair of opposite shifts with the same shifted operand:
   // trunc (or (lshr ShVal, ShAmt0), (shl ShVal, ShAmt1))
   Value *Or0, *Or1;
@@ -538,8 +545,6 @@ Instruction *InstCombiner::narrowRotate(TruncInst &Trunc) {
     return nullptr;
   };
 
-  Type *DestTy = Trunc.getType();
-  unsigned NarrowWidth = DestTy->getScalarSizeInBits();
   Value *ShAmt = matchShiftAmount(ShAmt0, ShAmt1, NarrowWidth);
   bool SubIsOnLHS = false;
   if (!ShAmt) {
index 00b0d80..c5b03fc 100644 (file)
@@ -123,17 +123,16 @@ define i8 @rotate8_not_safe(i8 %v, i32 %shamt) {
   ret i8 %ret
 }
 
-; FIXME: A non-power-of-2 destination type can't be masked as above.
+; A non-power-of-2 destination type can't be masked as above.
 
 define i9 @rotate9_not_safe(i9 %v, i32 %shamt) {
 ; CHECK-LABEL: @rotate9_not_safe(
-; CHECK-NEXT:    [[TMP1:%.*]] = trunc i32 [[SHAMT:%.*]] to i9
-; CHECK-NEXT:    [[TMP2:%.*]] = sub i9 0, [[TMP1]]
-; CHECK-NEXT:    [[TMP3:%.*]] = and i9 [[TMP1]], 8
-; CHECK-NEXT:    [[TMP4:%.*]] = and i9 [[TMP2]], 8
-; CHECK-NEXT:    [[TMP5:%.*]] = lshr i9 [[V:%.*]], [[TMP4]]
-; CHECK-NEXT:    [[TMP6:%.*]] = shl i9 [[V]], [[TMP3]]
-; CHECK-NEXT:    [[RET:%.*]] = or i9 [[TMP5]], [[TMP6]]
+; CHECK-NEXT:    [[CONV:%.*]] = zext i9 [[V:%.*]] to i32
+; CHECK-NEXT:    [[SUB:%.*]] = sub i32 9, [[SHAMT:%.*]]
+; CHECK-NEXT:    [[SHR:%.*]] = lshr i32 [[CONV]], [[SUB]]
+; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[CONV]], [[SHAMT]]
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[SHR]], [[SHL]]
+; CHECK-NEXT:    [[RET:%.*]] = trunc i32 [[OR]] to i9
 ; CHECK-NEXT:    ret i9 [[RET]]
 ;
   %conv = zext i9 %v to i32
@@ -331,17 +330,18 @@ define i8 @rotateleft_8_neg_mask_wide_amount_commute(i8 %v, i32 %shamt) {
   ret i8 %ret
 }
 
-; Non-power-of-2 types. This is transformed correctly, but it's not a typical rotate pattern. 
+; Non-power-of-2 types. This could be transformed, but it's not a typical rotate pattern.
 
 define i9 @rotateleft_9_neg_mask_wide_amount_commute(i9 %v, i33 %shamt) {
 ; CHECK-LABEL: @rotateleft_9_neg_mask_wide_amount_commute(
-; CHECK-NEXT:    [[TMP1:%.*]] = trunc i33 [[SHAMT:%.*]] to i9
-; CHECK-NEXT:    [[TMP2:%.*]] = sub i9 0, [[TMP1]]
-; CHECK-NEXT:    [[TMP3:%.*]] = and i9 [[TMP1]], 8
-; CHECK-NEXT:    [[TMP4:%.*]] = and i9 [[TMP2]], 8
-; CHECK-NEXT:    [[TMP5:%.*]] = shl i9 [[V:%.*]], [[TMP3]]
-; CHECK-NEXT:    [[TMP6:%.*]] = lshr i9 [[V]], [[TMP4]]
-; CHECK-NEXT:    [[RET:%.*]] = or i9 [[TMP5]], [[TMP6]]
+; CHECK-NEXT:    [[NEG:%.*]] = sub i33 0, [[SHAMT:%.*]]
+; CHECK-NEXT:    [[LSHAMT:%.*]] = and i33 [[SHAMT]], 8
+; CHECK-NEXT:    [[RSHAMT:%.*]] = and i33 [[NEG]], 8
+; CHECK-NEXT:    [[CONV:%.*]] = zext i9 [[V:%.*]] to i33
+; CHECK-NEXT:    [[SHL:%.*]] = shl i33 [[CONV]], [[LSHAMT]]
+; CHECK-NEXT:    [[SHR:%.*]] = lshr i33 [[CONV]], [[RSHAMT]]
+; CHECK-NEXT:    [[OR:%.*]] = or i33 [[SHL]], [[SHR]]
+; CHECK-NEXT:    [[RET:%.*]] = trunc i33 [[OR]] to i9
 ; CHECK-NEXT:    ret i9 [[RET]]
 ;
   %neg = sub i33 0, %shamt