diff options
author | Chris Lattner <sabre@nondot.org> | 2009-03-20 22:41:15 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-03-20 22:41:15 +0000 |
commit | 344c7c5cc4dd76e3f538dcc3d4f487be0b6ca067 (patch) | |
tree | c11e8bf54bfc283e12675a7217fb9dc97c276038 | |
parent | ab6b226978644c438a3a7768a06dcd48509d000c (diff) | |
download | external_llvm-344c7c5cc4dd76e3f538dcc3d4f487be0b6ca067.zip external_llvm-344c7c5cc4dd76e3f538dcc3d4f487be0b6ca067.tar.gz external_llvm-344c7c5cc4dd76e3f538dcc3d4f487be0b6ca067.tar.bz2 |
Fix instcombine to not introduce undefined shifts when merging two
shifts together. This fixes PR3851.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@67411 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 16 | ||||
-rw-r--r-- | test/Transforms/InstCombine/2009-03-20-AShrOverShift.ll | 9 |
2 files changed, 23 insertions, 2 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 10671cd..6af0afd 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -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 index 0000000..92ace11 --- /dev/null +++ b/test/Transforms/InstCombine/2009-03-20-AShrOverShift.ll @@ -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 + } |