[llvm] r213678 - This patch implements optimization as mentioned in PR19753: Optimize comparisons with "ashr/lshr exact" of a constanst.
Sanjay Patel
spatel at rotateright.com
Sun Oct 19 11:46:54 PDT 2014
> Sorry for the necro-post, but did this get verified with an SMT solver?
Apparently not - at least 2 more miscompiles have been blamed on this patch
after PR19958 was marked fixed:
http://llvm.org/bugs/show_bug.cgi?id=20945
http://llvm.org/bugs/show_bug.cgi?id=21222
On Fri, Oct 17, 2014 at 5:26 PM, Sean Silva <chisophugis at gmail.com> wrote:
> Sorry for the necro-post, but did this get verified with an SMT solver?
>
> Sanjay (CC'd) even provided links to example code for using an SMT solver
> to verify it in http://llvm.org/bugs/show_bug.cgi?id=19958#c9
>
> -- Sean Silva
>
> On Tue, Jul 22, 2014 at 12:19 PM, Suyog Sarda <suyog.sarda at samsung.com>
> wrote:
>
>> Author: suyog
>> Date: Tue Jul 22 14:19:36 2014
>> New Revision: 213678
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=213678&view=rev
>> Log:
>> This patch implements optimization as mentioned in PR19753: Optimize
>> comparisons with "ashr/lshr exact" of a constanst.
>> It handles the errors which were seen in PR19958 where wrong code was
>> being emitted due to earlier patch.
>> Added code for lshr as well as non-exact right shifts.
>>
>> It implements :
>> (icmp eq/ne (ashr/lshr const2, A), const1)" ->
>> (icmp eq/ne A, Log2(const2/const1)) ->
>> (icmp eq/ne A, Log2(const2) - Log2(const1))
>>
>> Differential Revision: http://reviews.llvm.org/D4068
>>
>>
>> Added:
>> llvm/trunk/test/Transforms/InstCombine/icmp-shr.ll
>> Modified:
>> llvm/trunk/lib/Transforms/InstCombine/InstCombine.h
>> llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
>>
>> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombine.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombine.h?rev=213678&r1=213677&r2=213678&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Transforms/InstCombine/InstCombine.h (original)
>> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombine.h Tue Jul 22
>> 14:19:36 2014
>> @@ -172,6 +172,8 @@ public:
>> ConstantInt *DivRHS);
>> Instruction *FoldICmpShrCst(ICmpInst &ICI, BinaryOperator *DivI,
>> ConstantInt *DivRHS);
>> + Instruction *FoldICmpCstShrCst(ICmpInst &I, Value *Op, Value *A,
>> + ConstantInt *CI1, ConstantInt *CI2);
>> Instruction *FoldICmpAddOpCst(Instruction &ICI, Value *X, ConstantInt
>> *CI,
>> ICmpInst::Predicate Pred);
>> Instruction *FoldGEPICmp(GEPOperator *GEPLHS, Value *RHS,
>>
>> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp?rev=213678&r1=213677&r2=213678&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
>> (original)
>> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp Tue Jul
>> 22 14:19:36 2014
>> @@ -1044,6 +1044,90 @@ Instruction *InstCombiner::FoldICmpShrCs
>> return nullptr;
>> }
>>
>> +/// FoldICmpCstShrCst - Handle "(icmp eq/ne (ashr/lshr const2, A),
>> const1)" ->
>> +/// (icmp eq/ne A, Log2(const2/const1)) ->
>> +/// (icmp eq/ne A, Log2(const2) - Log2(const1)).
>> +Instruction *InstCombiner::FoldICmpCstShrCst(ICmpInst &I, Value *Op,
>> Value *A,
>> + ConstantInt *CI1,
>> + ConstantInt *CI2) {
>> + assert(I.isEquality() && "Cannot fold icmp gt/lt");
>> +
>> + auto getConstant = [&I, this](bool IsTrue) {
>> + if (I.getPredicate() == I.ICMP_NE)
>> + IsTrue = !IsTrue;
>> + return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), IsTrue));
>> + };
>> +
>> + auto getICmp = [&I](CmpInst::Predicate Pred, Value *LHS, Value *RHS) {
>> + if (I.getPredicate() == I.ICMP_NE)
>> + Pred = CmpInst::getInversePredicate(Pred);
>> + return new ICmpInst(Pred, LHS, RHS);
>> + };
>> +
>> + APInt AP1 = CI1->getValue();
>> + APInt AP2 = CI2->getValue();
>> +
>> + if (!AP1) {
>> + if (!AP2) {
>> + // Both Constants are 0.
>> + return getConstant(true);
>> + }
>> +
>> + if (cast<BinaryOperator>(Op)->isExact())
>> + return getConstant(false);
>> +
>> + if (AP2.isNegative()) {
>> + // MSB is set, so a lshr with a large enough 'A' would be
>> undefined.
>> + return getConstant(false);
>> + }
>> +
>> + // 'A' must be large enough to shift out the highest set bit.
>> + return getICmp(I.ICMP_UGT, A,
>> + ConstantInt::get(A->getType(), AP2.logBase2()));
>> + }
>> +
>> + if (!AP2) {
>> + // Shifting 0 by any value gives 0.
>> + return getConstant(false);
>> + }
>> +
>> + bool IsAShr = isa<AShrOperator>(Op);
>> + if (AP1 == AP2) {
>> + if (AP1.isAllOnesValue() && IsAShr) {
>> + // Arithmatic shift of -1 is always -1.
>> + return getConstant(true);
>> + }
>> + return getICmp(I.ICMP_EQ, A,
>> ConstantInt::getNullValue(A->getType()));
>> + }
>> +
>> + if (IsAShr) {
>> + if (AP1.isNegative() != AP2.isNegative()) {
>> + // Arithmetic shift will never change the sign.
>> + return getConstant(false);
>> + }
>> + // Both the constants are negative, take their positive to calculate
>> + // log.
>> + if (AP1.isNegative()) {
>> + AP1 = -AP1;
>> + AP2 = -AP2;
>> + }
>> + }
>> +
>> + if (AP1.ugt(AP2)) {
>> + // Right-shifting will not increase the value.
>> + return getConstant(false);
>> + }
>> +
>> + // Get the distance between the highest bit that's set.
>> + int Shift = AP2.logBase2() - AP1.logBase2();
>> +
>> + // Use lshr here, since we've canonicalized to +ve numbers.
>> + if (AP1 == AP2.lshr(Shift))
>> + return getICmp(I.ICMP_EQ, A, ConstantInt::get(A->getType(), Shift));
>> +
>> + // Shifting const2 will never be equal to const1.
>> + return getConstant(false);
>> +}
>>
>> /// visitICmpInstWithInstAndIntCst - Handle "icmp (instr, intcst)".
>> ///
>> @@ -2469,6 +2553,15 @@ Instruction *InstCombiner::visitICmpInst
>> Builder->getInt(CI->getValue()-1));
>> }
>>
>> + // (icmp eq/ne (ashr/lshr const2, A), const1)
>> + if (I.isEquality()) {
>> + ConstantInt *CI2;
>> + if (match(Op0, m_AShr(m_ConstantInt(CI2), m_Value(A))) ||
>> + match(Op0, m_LShr(m_ConstantInt(CI2), m_Value(A)))) {
>> + return FoldICmpCstShrCst(I, Op0, A, CI, CI2);
>> + }
>> + }
>> +
>> // If this comparison is a normal comparison, it demands all
>> // bits, if it is a sign bit comparison, it only demands the sign
>> bit.
>> bool UnusedBit;
>>
>> Added: llvm/trunk/test/Transforms/InstCombine/icmp-shr.ll
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/icmp-shr.ll?rev=213678&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/Transforms/InstCombine/icmp-shr.ll (added)
>> +++ llvm/trunk/test/Transforms/InstCombine/icmp-shr.ll Tue Jul 22
>> 14:19:36 2014
>> @@ -0,0 +1,677 @@
>> +; RUN: opt < %s -instcombine -S | FileCheck %s
>> +
>> +target datalayout =
>> "e-p:64:64:64-p1:16:16:16-p2:32:32:32-p3:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
>> +
>> +; CHECK-LABEL: @exact_lshr_eq_both_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_lshr_eq_both_zero(i8 %a) {
>> + %shr = lshr exact i8 0, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_eq_both_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_ashr_eq_both_zero(i8 %a) {
>> + %shr = ashr exact i8 0, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_eq_both_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @nonexact_lshr_eq_both_zero(i8 %a) {
>> + %shr = lshr i8 0, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_eq_both_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @nonexact_ashr_eq_both_zero(i8 %a) {
>> + %shr = ashr i8 0, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_ne_both_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_lshr_ne_both_zero(i8 %a) {
>> + %shr = lshr exact i8 0, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne_both_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_ashr_ne_both_zero(i8 %a) {
>> + %shr = ashr exact i8 0, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_ne_both_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @nonexact_lshr_ne_both_zero(i8 %a) {
>> + %shr = lshr i8 0, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_ne_both_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @nonexact_ashr_ne_both_zero(i8 %a) {
>> + %shr = ashr i8 0, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_eq_last_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_lshr_eq_last_zero(i8 %a) {
>> + %shr = lshr exact i8 128, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_eq_last_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_ashr_eq_last_zero(i8 %a) {
>> + %shr = ashr exact i8 -128, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_ne_last_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_lshr_ne_last_zero(i8 %a) {
>> + %shr = lshr exact i8 128, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne_last_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_ashr_ne_last_zero(i8 %a) {
>> + %shr = ashr exact i8 -128, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_eq_last_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @nonexact_lshr_eq_last_zero(i8 %a) {
>> + %shr = lshr i8 128, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_eq_last_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @nonexact_ashr_eq_last_zero(i8 %a) {
>> + %shr = ashr i8 -128, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_ne_last_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @nonexact_lshr_ne_last_zero(i8 %a) {
>> + %shr = lshr i8 128, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_ne_last_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @nonexact_ashr_ne_last_zero(i8 %a) {
>> + %shr = ashr i8 -128, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @lshr_eq_msb_low_last_zero
>> +; CHECK-NEXT: icmp ugt i8 %a, 6
>> +define i1 @lshr_eq_msb_low_last_zero(i8 %a) {
>> + %shr = lshr i8 127, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_eq_msb_low_second_zero
>> +; CHECK-NEXT: icmp ugt i8 %a, 6
>> +define i1 @ashr_eq_msb_low_second_zero(i8 %a) {
>> + %shr = ashr i8 127, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @lshr_ne_msb_low_last_zero
>> +; CHECK-NEXT: icmp ult i8 %a, 7
>> +define i1 @lshr_ne_msb_low_last_zero(i8 %a) {
>> + %shr = lshr i8 127, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_ne_msb_low_second_zero
>> +; CHECK-NEXT: icmp ult i8 %a, 7
>> +define i1 @ashr_ne_msb_low_second_zero(i8 %a) {
>> + %shr = ashr i8 127, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @lshr_eq_first_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @lshr_eq_first_zero(i8 %a) {
>> + %shr = lshr i8 0, %a
>> + %cmp = icmp eq i8 %shr, 2
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_eq_first_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @ashr_eq_first_zero(i8 %a) {
>> + %shr = ashr i8 0, %a
>> + %cmp = icmp eq i8 %shr, 2
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @lshr_ne_first_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @lshr_ne_first_zero(i8 %a) {
>> + %shr = lshr i8 0, %a
>> + %cmp = icmp ne i8 %shr, 2
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_ne_first_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @ashr_ne_first_zero(i8 %a) {
>> + %shr = ashr i8 0, %a
>> + %cmp = icmp ne i8 %shr, 2
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_eq_both_minus1
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @ashr_eq_both_minus1(i8 %a) {
>> + %shr = ashr i8 -1, %a
>> + %cmp = icmp eq i8 %shr, -1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_ne_both_minus1
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @ashr_ne_both_minus1(i8 %a) {
>> + %shr = ashr i8 -1, %a
>> + %cmp = icmp ne i8 %shr, -1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_eq_both_minus1
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_ashr_eq_both_minus1(i8 %a) {
>> + %shr = ashr exact i8 -1, %a
>> + %cmp = icmp eq i8 %shr, -1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne_both_minus1
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_ashr_ne_both_minus1(i8 %a) {
>> + %shr = ashr exact i8 -1, %a
>> + %cmp = icmp ne i8 %shr, -1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_eq_both_equal
>> +; CHECK-NEXT: icmp eq i8 %a, 0
>> +define i1 @ashr_eq_both_equal(i8 %a) {
>> + %shr = ashr i8 128, %a
>> + %cmp = icmp eq i8 %shr, 128
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_ne_both_equal
>> +; CHECK-NEXT: icmp ne i8 %a, 0
>> +define i1 @ashr_ne_both_equal(i8 %a) {
>> + %shr = ashr i8 128, %a
>> + %cmp = icmp ne i8 %shr, 128
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @lshr_eq_both_equal
>> +; CHECK-NEXT: icmp eq i8 %a, 0
>> +define i1 @lshr_eq_both_equal(i8 %a) {
>> + %shr = lshr i8 127, %a
>> + %cmp = icmp eq i8 %shr, 127
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @lshr_ne_both_equal
>> +; CHECK-NEXT: icmp ne i8 %a, 0
>> +define i1 @lshr_ne_both_equal(i8 %a) {
>> + %shr = lshr i8 127, %a
>> + %cmp = icmp ne i8 %shr, 127
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_eq_both_equal
>> +; CHECK-NEXT: icmp eq i8 %a, 0
>> +define i1 @exact_ashr_eq_both_equal(i8 %a) {
>> + %shr = ashr exact i8 128, %a
>> + %cmp = icmp eq i8 %shr, 128
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne_both_equal
>> +; CHECK-NEXT: icmp ne i8 %a, 0
>> +define i1 @exact_ashr_ne_both_equal(i8 %a) {
>> + %shr = ashr exact i8 128, %a
>> + %cmp = icmp ne i8 %shr, 128
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_eq_both_equal
>> +; CHECK-NEXT: icmp eq i8 %a, 0
>> +define i1 @exact_lshr_eq_both_equal(i8 %a) {
>> + %shr = lshr exact i8 126, %a
>> + %cmp = icmp eq i8 %shr, 126
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_ne_both_equal
>> +; CHECK-NEXT: icmp ne i8 %a, 0
>> +define i1 @exact_lshr_ne_both_equal(i8 %a) {
>> + %shr = lshr exact i8 126, %a
>> + %cmp = icmp ne i8 %shr, 126
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_eq_opposite_msb
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_ashr_eq_opposite_msb(i8 %a) {
>> + %shr = ashr exact i8 -128, %a
>> + %cmp = icmp eq i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_eq_opposite_msb
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @ashr_eq_opposite_msb(i8 %a) {
>> + %shr = ashr i8 -128, %a
>> + %cmp = icmp eq i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_eq_opposite_msb
>> +; CHECK-NEXT: icmp eq i8 %a, 7
>> +define i1 @exact_lshr_eq_opposite_msb(i8 %a) {
>> + %shr = lshr exact i8 -128, %a
>> + %cmp = icmp eq i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @lshr_eq_opposite_msb
>> +; CHECK-NEXT: icmp eq i8 %a, 7
>> +define i1 @lshr_eq_opposite_msb(i8 %a) {
>> + %shr = lshr i8 -128, %a
>> + %cmp = icmp eq i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne_opposite_msb
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_ashr_ne_opposite_msb(i8 %a) {
>> + %shr = ashr exact i8 -128, %a
>> + %cmp = icmp ne i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_ne_opposite_msb
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @ashr_ne_opposite_msb(i8 %a) {
>> + %shr = ashr i8 -128, %a
>> + %cmp = icmp ne i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_ne_opposite_msb
>> +; CHECK-NEXT: icmp ne i8 %a, 7
>> +define i1 @exact_lshr_ne_opposite_msb(i8 %a) {
>> + %shr = lshr exact i8 -128, %a
>> + %cmp = icmp ne i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @lshr_ne_opposite_msb
>> +; CHECK-NEXT: icmp ne i8 %a, 7
>> +define i1 @lshr_ne_opposite_msb(i8 %a) {
>> + %shr = lshr i8 -128, %a
>> + %cmp = icmp ne i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_eq_shift_gt
>> +; CHECK-NEXT : ret i1 false
>> +define i1 @exact_ashr_eq_shift_gt(i8 %a) {
>> + %shr = ashr exact i8 -2, %a
>> + %cmp = icmp eq i8 %shr, -8
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne_shift_gt
>> +; CHECK-NEXT : ret i1 true
>> +define i1 @exact_ashr_ne_shift_gt(i8 %a) {
>> + %shr = ashr exact i8 -2, %a
>> + %cmp = icmp ne i8 %shr, -8
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_eq_shift_gt
>> +; CHECK-NEXT : ret i1 false
>> +define i1 @nonexact_ashr_eq_shift_gt(i8 %a) {
>> + %shr = ashr i8 -2, %a
>> + %cmp = icmp eq i8 %shr, -8
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_ne_shift_gt
>> +; CHECK-NEXT : ret i1 true
>> +define i1 @nonexact_ashr_ne_shift_gt(i8 %a) {
>> + %shr = ashr i8 -2, %a
>> + %cmp = icmp ne i8 %shr, -8
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_eq_shift_gt
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_lshr_eq_shift_gt(i8 %a) {
>> + %shr = lshr exact i8 2, %a
>> + %cmp = icmp eq i8 %shr, 8
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_ne_shift_gt
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_lshr_ne_shift_gt(i8 %a) {
>> + %shr = lshr exact i8 2, %a
>> + %cmp = icmp ne i8 %shr, 8
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_eq_shift_gt
>> +; CHECK-NEXT : ret i1 false
>> +define i1 @nonexact_lshr_eq_shift_gt(i8 %a) {
>> + %shr = lshr i8 2, %a
>> + %cmp = icmp eq i8 %shr, 8
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_ne_shift_gt
>> +; CHECK-NEXT : ret i1 true
>> +define i1 @nonexact_lshr_ne_shift_gt(i8 %a) {
>> + %shr = ashr i8 2, %a
>> + %cmp = icmp ne i8 %shr, 8
>> + ret i1 %cmp
>> +}
>> +
>> +
>> +
>> +; CHECK-LABEL: @exact_ashr_eq
>> +; CHECK-NEXT: icmp eq i8 %a, 7
>> +define i1 @exact_ashr_eq(i8 %a) {
>> + %shr = ashr exact i8 -128, %a
>> + %cmp = icmp eq i8 %shr, -1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne
>> +; CHECK-NEXT: icmp ne i8 %a, 7
>> +define i1 @exact_ashr_ne(i8 %a) {
>> + %shr = ashr exact i8 -128, %a
>> + %cmp = icmp ne i8 %shr, -1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_eq
>> +; CHECK-NEXT: icmp eq i8 %a, 2
>> +define i1 @exact_lshr_eq(i8 %a) {
>> + %shr = lshr exact i8 4, %a
>> + %cmp = icmp eq i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_ne
>> +; CHECK-NEXT: icmp ne i8 %a, 2
>> +define i1 @exact_lshr_ne(i8 %a) {
>> + %shr = lshr exact i8 4, %a
>> + %cmp = icmp ne i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_eq
>> +; CHECK-NEXT: icmp eq i8 %a, 7
>> +define i1 @nonexact_ashr_eq(i8 %a) {
>> + %shr = ashr i8 -128, %a
>> + %cmp = icmp eq i8 %shr, -1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_ne
>> +; CHECK-NEXT: icmp ne i8 %a, 7
>> +define i1 @nonexact_ashr_ne(i8 %a) {
>> + %shr = ashr i8 -128, %a
>> + %cmp = icmp ne i8 %shr, -1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_eq
>> +; CHECK-NEXT: icmp eq i8 %a, 2
>> +define i1 @nonexact_lshr_eq(i8 %a) {
>> + %shr = lshr i8 4, %a
>> + %cmp = icmp eq i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_ne
>> +; CHECK-NEXT: icmp ne i8 %a, 2
>> +define i1 @nonexact_lshr_ne(i8 %a) {
>> + %shr = lshr i8 4, %a
>> + %cmp = icmp ne i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_eq_exactdiv
>> +; CHECK-NEXT: icmp eq i8 %a, 4
>> +define i1 @exact_lshr_eq_exactdiv(i8 %a) {
>> + %shr = lshr exact i8 80, %a
>> + %cmp = icmp eq i8 %shr, 5
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_ne_exactdiv
>> +; CHECK-NEXT: icmp ne i8 %a, 4
>> +define i1 @exact_lshr_ne_exactdiv(i8 %a) {
>> + %shr = lshr exact i8 80, %a
>> + %cmp = icmp ne i8 %shr, 5
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_eq_exactdiv
>> +; CHECK-NEXT: icmp eq i8 %a, 4
>> +define i1 @nonexact_lshr_eq_exactdiv(i8 %a) {
>> + %shr = lshr i8 80, %a
>> + %cmp = icmp eq i8 %shr, 5
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_ne_exactdiv
>> +; CHECK-NEXT: icmp ne i8 %a, 4
>> +define i1 @nonexact_lshr_ne_exactdiv(i8 %a) {
>> + %shr = lshr i8 80, %a
>> + %cmp = icmp ne i8 %shr, 5
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_eq_exactdiv
>> +; CHECK-NEXT: icmp eq i8 %a, 4
>> +define i1 @exact_ashr_eq_exactdiv(i8 %a) {
>> + %shr = ashr exact i8 -80, %a
>> + %cmp = icmp eq i8 %shr, -5
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne_exactdiv
>> +; CHECK-NEXT: icmp ne i8 %a, 4
>> +define i1 @exact_ashr_ne_exactdiv(i8 %a) {
>> + %shr = ashr exact i8 -80, %a
>> + %cmp = icmp ne i8 %shr, -5
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_eq_exactdiv
>> +; CHECK-NEXT: icmp eq i8 %a, 4
>> +define i1 @nonexact_ashr_eq_exactdiv(i8 %a) {
>> + %shr = ashr i8 -80, %a
>> + %cmp = icmp eq i8 %shr, -5
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_ne_exactdiv
>> +; CHECK-NEXT: icmp ne i8 %a, 4
>> +define i1 @nonexact_ashr_ne_exactdiv(i8 %a) {
>> + %shr = ashr i8 -80, %a
>> + %cmp = icmp ne i8 %shr, -5
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_eq_noexactdiv
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_lshr_eq_noexactdiv(i8 %a) {
>> + %shr = lshr exact i8 80, %a
>> + %cmp = icmp eq i8 %shr, 31
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_ne_noexactdiv
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_lshr_ne_noexactdiv(i8 %a) {
>> + %shr = lshr exact i8 80, %a
>> + %cmp = icmp ne i8 %shr, 31
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_eq_noexactdiv
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @nonexact_lshr_eq_noexactdiv(i8 %a) {
>> + %shr = lshr i8 80, %a
>> + %cmp = icmp eq i8 %shr, 31
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_ne_noexactdiv
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @nonexact_lshr_ne_noexactdiv(i8 %a) {
>> + %shr = lshr i8 80, %a
>> + %cmp = icmp ne i8 %shr, 31
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_eq_noexactdiv
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_ashr_eq_noexactdiv(i8 %a) {
>> + %shr = ashr exact i8 -80, %a
>> + %cmp = icmp eq i8 %shr, -31
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne_noexactdiv
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_ashr_ne_noexactdiv(i8 %a) {
>> + %shr = ashr exact i8 -80, %a
>> + %cmp = icmp ne i8 %shr, -31
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_eq_noexactdiv
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @nonexact_ashr_eq_noexactdiv(i8 %a) {
>> + %shr = ashr i8 -80, %a
>> + %cmp = icmp eq i8 %shr, -31
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_ne_noexactdiv
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @nonexact_ashr_ne_noexactdiv(i8 %a) {
>> + %shr = ashr i8 -80, %a
>> + %cmp = icmp ne i8 %shr, -31
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_eq_noexactlog
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_lshr_eq_noexactlog(i8 %a) {
>> + %shr = lshr exact i8 90, %a
>> + %cmp = icmp eq i8 %shr, 30
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_ne_noexactlog
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_lshr_ne_noexactlog(i8 %a) {
>> + %shr = lshr exact i8 90, %a
>> + %cmp = icmp ne i8 %shr, 30
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_eq_noexactlog
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @nonexact_lshr_eq_noexactlog(i8 %a) {
>> + %shr = lshr i8 90, %a
>> + %cmp = icmp eq i8 %shr, 30
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_ne_noexactlog
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @nonexact_lshr_ne_noexactlog(i8 %a) {
>> + %shr = lshr i8 90, %a
>> + %cmp = icmp ne i8 %shr, 30
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_eq_noexactlog
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_ashr_eq_noexactlog(i8 %a) {
>> + %shr = ashr exact i8 -90, %a
>> + %cmp = icmp eq i8 %shr, -30
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne_noexactlog
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_ashr_ne_noexactlog(i8 %a) {
>> + %shr = ashr exact i8 -90, %a
>> + %cmp = icmp ne i8 %shr, -30
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_eq_noexactlog
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @nonexact_ashr_eq_noexactlog(i8 %a) {
>> + %shr = ashr i8 -90, %a
>> + %cmp = icmp eq i8 %shr, -30
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_ne_noexactlog
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @nonexact_ashr_ne_noexactlog(i8 %a) {
>> + %shr = ashr i8 -90, %a
>> + %cmp = icmp ne i8 %shr, -30
>> + ret i1 %cmp
>> +}
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141019/6273d895/attachment.html>
More information about the llvm-commits
mailing list