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

Hal Finkel hfinkel at anl.gov
Sun Oct 19 12:39:19 PDT 2014


----- 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.

 -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



More information about the llvm-commits mailing list