[llvm] r213678 - This patch implements optimization as mentioned in PR19753: Optimize comparisons with "ashr/lshr exact" of a constanst.
Suyog Kamal Sarda
suyog.sarda at samsung.com
Sun Oct 26 23:30:37 PDT 2014
Hi all,
Sorry for replying late. Just back from long vacation.
The patch in question was related to PR19753 (filed by David).
The patch was extensively reviewed by Duncan in implementation (cc'ed).
Over the time, this was corrected for few miscompiles (Thanks to Andrea!)
The patch had extra code to handle cases which were already handled by Simplify (mostly corner cases,
the first version of the patch didn't include the extra code).
To simplify understanding the whole logic flow, some extra code was pushed in (as per suggestions from Duncan).
I didn't prove this using SMT solver, as the related bug was filed in PR19753.
Should I prove it using SMT/Z3 ?
Regards,
Suyog Sarda
------- Original Message -------
Sender : David Majnemer<david.majnemer at gmail.com>
Date : Oct 22, 2014 08:49 (GMT+09:00)
Title : Re: [llvm] r213678 - This patch implements optimization as mentioned in PR19753: Optimize comparisons with "ashr/lshr exact" of a constanst.
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
More information about the llvm-commits
mailing list