Fix instcombine to not introduce undefined shifts when merging two
authorChris Lattner <sabre@nondot.org>
Fri, 20 Mar 2009 22:41:15 +0000 (22:41 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 20 Mar 2009 22:41:15 +0000 (22:41 +0000)
shifts together.  This fixes PR3851.

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

lib/Transforms/Scalar/InstructionCombining.cpp
test/Transforms/InstCombine/2009-03-20-AShrOverShift.ll [new file with mode: 0644]

index 10671cd908b767ca2cd88e4a96ea4c1de4316f11..6af0afd55e18e40de3ab3a5ea0476c1ee41fcd61 100644 (file)
@@ -7307,22 +7307,34 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
     Value *X = ShiftOp->getOperand(0);
     
     uint32_t AmtSum = ShiftAmt1+ShiftAmt2;   // Fold into one big shift.
-    if (AmtSum > TypeBits)
-      AmtSum = TypeBits;
     
     const IntegerType *Ty = cast<IntegerType>(I.getType());
     
     // Check for (X << c1) << c2  and  (X >> c1) >> c2
     if (I.getOpcode() == ShiftOp->getOpcode()) {
+      // If this is oversized composite shift, then unsigned shifts get 0, ashr
+      // saturates.
+      if (AmtSum >= TypeBits) {
+        if (I.getOpcode() != Instruction::AShr)
+          return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
+        AmtSum = TypeBits-1;  // Saturate to 31 for i32 ashr.
+      }
+      
       return BinaryOperator::Create(I.getOpcode(), X,
                                     ConstantInt::get(Ty, AmtSum));
     } else if (ShiftOp->getOpcode() == Instruction::LShr &&
                I.getOpcode() == Instruction::AShr) {
+      if (AmtSum >= TypeBits)
+        return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
+      
       // ((X >>u C1) >>s C2) -> (X >>u (C1+C2))  since C1 != 0.
       return BinaryOperator::CreateLShr(X, ConstantInt::get(Ty, AmtSum));
     } else if (ShiftOp->getOpcode() == Instruction::AShr &&
                I.getOpcode() == Instruction::LShr) {
       // ((X >>s C1) >>u C2) -> ((X >>s (C1+C2)) & mask) since C1 != 0.
+      if (AmtSum >= TypeBits)
+        AmtSum = TypeBits-1;
+      
       Instruction *Shift =
         BinaryOperator::CreateAShr(X, ConstantInt::get(Ty, AmtSum));
       InsertNewInstBefore(Shift, I);
diff --git a/test/Transforms/InstCombine/2009-03-20-AShrOverShift.ll b/test/Transforms/InstCombine/2009-03-20-AShrOverShift.ll
new file mode 100644 (file)
index 0000000..92ace11
--- /dev/null
@@ -0,0 +1,9 @@
+; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep {ashr i32 %val, 31}
+; PR3851
+
+define i32 @foo2(i32 %val) nounwind {
+entry:
+       %shr = ashr i32 %val, 15                ; <i32> [#uses=3]
+       %shr4 = ashr i32 %shr, 17               ; <i32> [#uses=1]
+        ret i32 %shr4
+ }