[llvm] r213678 - This patch implements optimization as mentioned in PR19753: Optimize comparisons with "ashr/lshr exact" of a constanst.

David Majnemer david.majnemer at gmail.com
Tue Oct 21 16:49:29 PDT 2014


On Sun, Oct 19, 2014 at 12:39 PM, Hal Finkel <hfinkel at anl.gov> wrote:

> ----- Original Message -----
> > From: "Sanjay Patel" <spatel at rotateright.com>
> > To: "Sean Silva" <chisophugis at gmail.com>
> > Cc: "Suyog Sarda" <suyog.sarda at samsung.com>, llvm-commits at cs.uiuc.edu
> > Sent: Sunday, October 19, 2014 1:46:54 PM
> > Subject: Re: [llvm] r213678 - This patch implements optimization as
> mentioned in PR19753: Optimize comparisons with
> > "ashr/lshr exact" of a        constanst.
> >
> >
> >
> > > 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
>
> To be fair, this is not a conclusion you can draw. Even a transformation
> verified by an SMT solver can be implemented incorrectly ;)
>
> In any case, if the commit is buggy, and we have PRs with reduced test
> cases, feel free to revert it pending fixes.
>

I believe the code in it's current form is correct, I've simplified it
considerably in r220314.


>  -Hal
>
> > 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
> >
> >
> >
> > _______________________________________________
> > llvm-commits mailing list
> > llvm-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
> >
>
> --
> Hal Finkel
> Assistant Computational Scientist
> Leadership Computing Facility
> Argonne National Laboratory
> _______________________________________________
> 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/20141021/70b3c205/attachment.html>


More information about the llvm-commits mailing list