diff options
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 33 | ||||
| -rw-r--r-- | llvm/test/Transforms/InstCombine/getelementptr.ll | 8 | ||||
| -rw-r--r-- | llvm/test/Transforms/InstCombine/icmp.ll | 28 |
3 files changed, 36 insertions, 33 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index f9a7eb2a512..33d97e10aa8 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1990,20 +1990,14 @@ static Instruction *foldICmpShlOne(ICmpInst &Cmp, Instruction *Shl, /// Fold icmp (shl X, Y), C. Instruction *InstCombiner::foldICmpShlConstant(ICmpInst &Cmp, Instruction *Shl, const APInt *C) { - // FIXME: This should use m_APInt to allow splat vectors. - ConstantInt *ShAmt = dyn_cast<ConstantInt>(Shl->getOperand(1)); - if (!ShAmt) + const APInt *ShiftAmt; + if (!match(Shl->getOperand(1), m_APInt(ShiftAmt))) return foldICmpShlOne(Cmp, Shl, C); - // FIXME: This check restricts all folds under here to scalar types. - ConstantInt *RHS = dyn_cast<ConstantInt>(Cmp.getOperand(1)); - if (!RHS) - return nullptr; - // Check that the shift amount is in range. If not, don't perform undefined // shifts. When the shift is visited it will be simplified. unsigned TypeBits = C->getBitWidth(); - if (ShAmt->uge(TypeBits)) + if (ShiftAmt->uge(TypeBits)) return nullptr; ICmpInst::Predicate Pred = Cmp.getPredicate(); @@ -2011,25 +2005,30 @@ Instruction *InstCombiner::foldICmpShlConstant(ICmpInst &Cmp, Instruction *Shl, if (Cmp.isEquality()) { // If the shift is NUW, then it is just shifting out zeros, no need for an // AND. + Constant *LShrC = ConstantInt::get(Shl->getType(), C->lshr(*ShiftAmt)); if (cast<BinaryOperator>(Shl)->hasNoUnsignedWrap()) - return new ICmpInst(Pred, X, ConstantExpr::getLShr(RHS, ShAmt)); + return new ICmpInst(Pred, X, LShrC); // If the shift is NSW and we compare to 0, then it is just shifting out // sign bits, no need for an AND either. if (cast<BinaryOperator>(Shl)->hasNoSignedWrap() && *C == 0) - return new ICmpInst(Pred, X, ConstantExpr::getLShr(RHS, ShAmt)); + return new ICmpInst(Pred, X, LShrC); if (Shl->hasOneUse()) { // Otherwise strength reduce the shift into an and. - uint32_t ShAmtVal = (uint32_t)ShAmt->getLimitedValue(TypeBits); - Constant *Mask = - Builder->getInt(APInt::getLowBitsSet(TypeBits, TypeBits - ShAmtVal)); + Constant *Mask = ConstantInt::get(Shl->getType(), + APInt::getLowBitsSet(TypeBits, TypeBits - ShiftAmt->getZExtValue())); Value *And = Builder->CreateAnd(X, Mask, Shl->getName() + ".mask"); - return new ICmpInst(Pred, And, ConstantExpr::getLShr(RHS, ShAmt)); + return new ICmpInst(Pred, And, LShrC); } } + // FIXME: This check restricts all folds under here to scalar types. + ConstantInt *RHS = dyn_cast<ConstantInt>(Cmp.getOperand(1)); + if (!RHS) + return nullptr; + // If this is a signed comparison to 0 and the shift is sign preserving, // use the shift LHS operand instead; isSignTest may change 'Pred', so only // do that if we're sure to not continue on in this function. @@ -2042,7 +2041,7 @@ Instruction *InstCombiner::foldICmpShlConstant(ICmpInst &Cmp, Instruction *Shl, // (X << 31) <s 0 --> (X&1) != 0 Constant *Mask = ConstantInt::get( X->getType(), - APInt::getOneBitSet(TypeBits, TypeBits - ShAmt->getZExtValue() - 1)); + APInt::getOneBitSet(TypeBits, TypeBits - ShiftAmt->getZExtValue() - 1)); Value *And = Builder->CreateAnd(X, Mask, Shl->getName() + ".mask"); return new ICmpInst(TrueIfSigned ? ICmpInst::ICMP_NE : ICmpInst::ICMP_EQ, And, Constant::getNullValue(And->getType())); @@ -2054,7 +2053,7 @@ Instruction *InstCombiner::foldICmpShlConstant(ICmpInst &Cmp, Instruction *Shl, // This enables to get rid of the shift in favor of a trunc which can be // free on the target. It has the additional benefit of comparing to a // smaller constant, which will be target friendly. - unsigned Amt = ShAmt->getLimitedValue(TypeBits - 1); + unsigned Amt = ShiftAmt->getLimitedValue(TypeBits - 1); if (Shl->hasOneUse() && Amt != 0 && C->countTrailingZeros() >= Amt) { Type *NTy = IntegerType::get(Cmp.getContext(), TypeBits - Amt); Constant *NCI = ConstantExpr::getTrunc( diff --git a/llvm/test/Transforms/InstCombine/getelementptr.ll b/llvm/test/Transforms/InstCombine/getelementptr.ll index 491fc355cba..7ccbdf11fde 100644 --- a/llvm/test/Transforms/InstCombine/getelementptr.ll +++ b/llvm/test/Transforms/InstCombine/getelementptr.ll @@ -175,10 +175,10 @@ define i1 @test13(i64 %X, %S* %P) { ; CHECK: %C = icmp eq i64 %X, -1 } +; This is a test of icmp + shl nuw in disguise - 4611... is 0x3fff... define <2 x i1> @test13_vector(<2 x i64> %X, <2 x %S*> %P) nounwind { ; CHECK-LABEL: @test13_vector( -; CHECK-NEXT: [[A_IDX:%.*]] = shl nuw <2 x i64> %X, <i64 2, i64 2> -; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i64> [[A_IDX]], <i64 -4, i64 -4> +; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i64> %X, <i64 4611686018427387903, i64 4611686018427387903> ; CHECK-NEXT: ret <2 x i1> [[C]] ; %A = getelementptr inbounds %S, <2 x %S*> %P, <2 x i64> zeroinitializer, <2 x i32> <i32 1, i32 1>, <2 x i64> %X @@ -197,10 +197,10 @@ define i1 @test13_as1(i16 %X, %S addrspace(1)* %P) { ret i1 %C } +; This is a test of icmp + shl nuw in disguise - 16383 is 0x3fff. define <2 x i1> @test13_vector_as1(<2 x i16> %X, <2 x %S addrspace(1)*> %P) { ; CHECK-LABEL: @test13_vector_as1( -; CHECK-NEXT: [[A_IDX:%.*]] = shl nuw <2 x i16> %X, <i16 2, i16 2> -; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i16> [[A_IDX]], <i16 -4, i16 -4> +; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i16> %X, <i16 16383, i16 16383> ; CHECK-NEXT: ret <2 x i1> [[C]] ; %A = getelementptr inbounds %S, <2 x %S addrspace(1)*> %P, <2 x i16> <i16 0, i16 0>, <2 x i32> <i32 1, i32 1>, <2 x i16> %X diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll index b15a960c0db..e1b58393f79 100644 --- a/llvm/test/Transforms/InstCombine/icmp.ll +++ b/llvm/test/Transforms/InstCombine/icmp.ll @@ -1183,11 +1183,9 @@ define i1 @icmp_shl_nsw_eq(i32 %x) { ret i1 %cmp } -; FIXME: Vectors should fold the same way. define <2 x i1> @icmp_shl_nsw_eq_vec(<2 x i32> %x) { ; CHECK-LABEL: @icmp_shl_nsw_eq_vec( -; CHECK-NEXT: [[MUL:%.*]] = shl nsw <2 x i32> %x, <i32 5, i32 5> -; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[MUL]], zeroinitializer +; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> %x, zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %mul = shl nsw <2 x i32> %x, <i32 5, i32 5> @@ -1206,11 +1204,10 @@ define i1 @icmp_shl_eq(i32 %x) { ret i1 %cmp } -; FIXME: Vectors should fold the same way. define <2 x i1> @icmp_shl_eq_vec(<2 x i32> %x) { ; CHECK-LABEL: @icmp_shl_eq_vec( -; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> %x, <i32 5, i32 5> -; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[MUL]], zeroinitializer +; CHECK-NEXT: [[MUL_MASK:%.*]] = and <2 x i32> %x, <i32 134217727, i32 134217727> +; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[MUL_MASK]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %mul = shl <2 x i32> %x, <i32 5, i32 5> @@ -1228,11 +1225,9 @@ define i1 @icmp_shl_nsw_ne(i32 %x) { ret i1 %cmp } -; FIXME: Vectors should fold the same way. define <2 x i1> @icmp_shl_nsw_ne_vec(<2 x i32> %x) { ; CHECK-LABEL: @icmp_shl_nsw_ne_vec( -; CHECK-NEXT: [[MUL:%.*]] = shl nsw <2 x i32> %x, <i32 7, i32 7> -; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[MUL]], zeroinitializer +; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> %x, zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %mul = shl nsw <2 x i32> %x, <i32 7, i32 7> @@ -1251,11 +1246,10 @@ define i1 @icmp_shl_ne(i32 %x) { ret i1 %cmp } -; FIXME: Vectors should fold the same way. define <2 x i1> @icmp_shl_ne_vec(<2 x i32> %x) { ; CHECK-LABEL: @icmp_shl_ne_vec( -; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> %x, <i32 7, i32 7> -; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[MUL]], zeroinitializer +; CHECK-NEXT: [[MUL_MASK:%.*]] = and <2 x i32> %x, <i32 33554431, i32 33554431> +; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[MUL_MASK]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %mul = shl <2 x i32> %x, <i32 7, i32 7> @@ -1263,6 +1257,16 @@ define <2 x i1> @icmp_shl_ne_vec(<2 x i32> %x) { ret <2 x i1> %cmp } +define <2 x i1> @icmp_shl_nuw_ne_vec(<2 x i32> %x) { +; CHECK-LABEL: @icmp_shl_nuw_ne_vec( +; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> %x, <i32 2, i32 2> +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %shl = shl nuw <2 x i32> %x, <i32 7, i32 7> + %cmp = icmp ne <2 x i32> %shl, <i32 256, i32 256> + ret <2 x i1> %cmp +} + ; If the (mul x, C) preserved the sign and this is sign test, ; compare the LHS operand instead define i1 @icmp_mul_nsw(i32 %x) { |

