<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sun, Oct 19, 2014 at 12:39 PM, Hal Finkel <span dir="ltr"><<a href="mailto:hfinkel@anl.gov" target="_blank">hfinkel@anl.gov</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span>----- Original Message -----<br>
> From: "Sanjay Patel" <<a href="mailto:spatel@rotateright.com" target="_blank">spatel@rotateright.com</a>><br>
> To: "Sean Silva" <<a href="mailto:chisophugis@gmail.com" target="_blank">chisophugis@gmail.com</a>><br>
> Cc: "Suyog Sarda" <<a href="mailto:suyog.sarda@samsung.com" target="_blank">suyog.sarda@samsung.com</a>>, <a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
> Sent: Sunday, October 19, 2014 1:46:54 PM<br>
> Subject: Re: [llvm] r213678 - This patch implements optimization as mentioned in PR19753: Optimize comparisons with<br>
> "ashr/lshr exact" of a        constanst.<br>
><br>
><br>
><br>
</span><span>> > Sorry for the necro-post, but did this get verified with an SMT<br>
> > solver?<br>
><br>
> Apparently not - at least 2 more miscompiles have been blamed on this<br>
<br>
</span>To be fair, this is not a conclusion you can draw. Even a transformation verified by an SMT solver can be implemented incorrectly ;)<br>
<br>
In any case, if the commit is buggy, and we have PRs with reduced test cases, feel free to revert it pending fixes.<br></blockquote><div><br></div><div>I believe the code in it's current form is correct, I've simplified it considerably in r220314.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
 -Hal<br>
<div><div><br>
> patch after PR19958 was marked fixed:<br>
> <a href="http://llvm.org/bugs/show_bug.cgi?id=20945" target="_blank">http://llvm.org/bugs/show_bug.cgi?id=20945</a><br>
> <a href="http://llvm.org/bugs/show_bug.cgi?id=21222" target="_blank">http://llvm.org/bugs/show_bug.cgi?id=21222</a><br>
><br>
><br>
><br>
> On Fri, Oct 17, 2014 at 5:26 PM, Sean Silva < <a href="mailto:chisophugis@gmail.com" target="_blank">chisophugis@gmail.com</a> ><br>
> wrote:<br>
><br>
><br>
><br>
> Sorry for the necro-post, but did this get verified with an SMT<br>
> solver?<br>
><br>
><br>
> Sanjay (CC'd) even provided links to example code for using an SMT<br>
> solver to verify it in <a href="http://llvm.org/bugs/show_bug.cgi?id=19958#c9" target="_blank">http://llvm.org/bugs/show_bug.cgi?id=19958#c9</a><br>
><br>
><br>
><br>
> -- Sean Silva<br>
><br>
><br>
><br>
><br>
> On Tue, Jul 22, 2014 at 12:19 PM, Suyog Sarda <<br>
> <a href="mailto:suyog.sarda@samsung.com" target="_blank">suyog.sarda@samsung.com</a> > wrote:<br>
><br>
><br>
> Author: suyog<br>
> Date: Tue Jul 22 14:19:36 2014<br>
> New Revision: 213678<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=213678&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=213678&view=rev</a><br>
> Log:<br>
> This patch implements optimization as mentioned in PR19753: Optimize<br>
> comparisons with "ashr/lshr exact" of a constanst.<br>
> It handles the errors which were seen in PR19958 where wrong code was<br>
> being emitted due to earlier patch.<br>
> Added code for lshr as well as non-exact right shifts.<br>
><br>
> It implements :<br>
> (icmp eq/ne (ashr/lshr const2, A), const1)" -><br>
> (icmp eq/ne A, Log2(const2/const1)) -><br>
> (icmp eq/ne A, Log2(const2) - Log2(const1))<br>
><br>
> Differential Revision: <a href="http://reviews.llvm.org/D4068" target="_blank">http://reviews.llvm.org/D4068</a><br>
><br>
><br>
> Added:<br>
> llvm/trunk/test/Transforms/InstCombine/icmp-shr.ll<br>
> Modified:<br>
> llvm/trunk/lib/Transforms/InstCombine/InstCombine.h<br>
> llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp<br>
><br>
> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombine.h<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombine.h?rev=213678&r1=213677&r2=213678&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombine.h?rev=213678&r1=213677&r2=213678&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Transforms/InstCombine/InstCombine.h (original)<br>
> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombine.h Tue Jul 22<br>
> 14:19:36 2014<br>
> @@ -172,6 +172,8 @@ public:<br>
> ConstantInt *DivRHS);<br>
> Instruction *FoldICmpShrCst(ICmpInst &ICI, BinaryOperator *DivI,<br>
> ConstantInt *DivRHS);<br>
> + Instruction *FoldICmpCstShrCst(ICmpInst &I, Value *Op, Value *A,<br>
> + ConstantInt *CI1, ConstantInt *CI2);<br>
> Instruction *FoldICmpAddOpCst(Instruction &ICI, Value *X, ConstantInt<br>
> *CI,<br>
> ICmpInst::Predicate Pred);<br>
> Instruction *FoldGEPICmp(GEPOperator *GEPLHS, Value *RHS,<br>
><br>
> Modified:<br>
> llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp?rev=213678&r1=213677&r2=213678&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp?rev=213678&r1=213677&r2=213678&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp<br>
> (original)<br>
> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp Tue<br>
> Jul 22 14:19:36 2014<br>
> @@ -1044,6 +1044,90 @@ Instruction *InstCombiner::FoldICmpShrCs<br>
> return nullptr;<br>
> }<br>
><br>
> +/// FoldICmpCstShrCst - Handle "(icmp eq/ne (ashr/lshr const2, A),<br>
> const1)" -><br>
> +/// (icmp eq/ne A, Log2(const2/const1)) -><br>
> +/// (icmp eq/ne A, Log2(const2) - Log2(const1)).<br>
> +Instruction *InstCombiner::FoldICmpCstShrCst(ICmpInst &I, Value *Op,<br>
> Value *A,<br>
> + ConstantInt *CI1,<br>
> + ConstantInt *CI2) {<br>
> + assert(I.isEquality() && "Cannot fold icmp gt/lt");<br>
> +<br>
> + auto getConstant = [&I, this](bool IsTrue) {<br>
> + if (I.getPredicate() == I.ICMP_NE)<br>
> + IsTrue = !IsTrue;<br>
> + return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(),<br>
> IsTrue));<br>
> + };<br>
> +<br>
> + auto getICmp = [&I](CmpInst::Predicate Pred, Value *LHS, Value<br>
> *RHS) {<br>
> + if (I.getPredicate() == I.ICMP_NE)<br>
> + Pred = CmpInst::getInversePredicate(Pred);<br>
> + return new ICmpInst(Pred, LHS, RHS);<br>
> + };<br>
> +<br>
> + APInt AP1 = CI1->getValue();<br>
> + APInt AP2 = CI2->getValue();<br>
> +<br>
> + if (!AP1) {<br>
> + if (!AP2) {<br>
> + // Both Constants are 0.<br>
> + return getConstant(true);<br>
> + }<br>
> +<br>
> + if (cast<BinaryOperator>(Op)->isExact())<br>
> + return getConstant(false);<br>
> +<br>
> + if (AP2.isNegative()) {<br>
> + // MSB is set, so a lshr with a large enough 'A' would be<br>
> undefined.<br>
> + return getConstant(false);<br>
> + }<br>
> +<br>
> + // 'A' must be large enough to shift out the highest set bit.<br>
> + return getICmp(I.ICMP_UGT, A,<br>
> + ConstantInt::get(A->getType(), AP2.logBase2()));<br>
> + }<br>
> +<br>
> + if (!AP2) {<br>
> + // Shifting 0 by any value gives 0.<br>
> + return getConstant(false);<br>
> + }<br>
> +<br>
> + bool IsAShr = isa<AShrOperator>(Op);<br>
> + if (AP1 == AP2) {<br>
> + if (AP1.isAllOnesValue() && IsAShr) {<br>
> + // Arithmatic shift of -1 is always -1.<br>
> + return getConstant(true);<br>
> + }<br>
> + return getICmp(I.ICMP_EQ, A,<br>
> ConstantInt::getNullValue(A->getType()));<br>
> + }<br>
> +<br>
> + if (IsAShr) {<br>
> + if (AP1.isNegative() != AP2.isNegative()) {<br>
> + // Arithmetic shift will never change the sign.<br>
> + return getConstant(false);<br>
> + }<br>
> + // Both the constants are negative, take their positive to<br>
> calculate<br>
> + // log.<br>
> + if (AP1.isNegative()) {<br>
> + AP1 = -AP1;<br>
> + AP2 = -AP2;<br>
> + }<br>
> + }<br>
> +<br>
> + if (AP1.ugt(AP2)) {<br>
> + // Right-shifting will not increase the value.<br>
> + return getConstant(false);<br>
> + }<br>
> +<br>
> + // Get the distance between the highest bit that's set.<br>
> + int Shift = AP2.logBase2() - AP1.logBase2();<br>
> +<br>
> + // Use lshr here, since we've canonicalized to +ve numbers.<br>
> + if (AP1 == AP2.lshr(Shift))<br>
> + return getICmp(I.ICMP_EQ, A, ConstantInt::get(A->getType(),<br>
> Shift));<br>
> +<br>
> + // Shifting const2 will never be equal to const1.<br>
> + return getConstant(false);<br>
> +}<br>
><br>
> /// visitICmpInstWithInstAndIntCst - Handle "icmp (instr, intcst)".<br>
> ///<br>
> @@ -2469,6 +2553,15 @@ Instruction *InstCombiner::visitICmpInst<br>
> Builder->getInt(CI->getValue()-1));<br>
> }<br>
><br>
> + // (icmp eq/ne (ashr/lshr const2, A), const1)<br>
> + if (I.isEquality()) {<br>
> + ConstantInt *CI2;<br>
> + if (match(Op0, m_AShr(m_ConstantInt(CI2), m_Value(A))) ||<br>
> + match(Op0, m_LShr(m_ConstantInt(CI2), m_Value(A)))) {<br>
> + return FoldICmpCstShrCst(I, Op0, A, CI, CI2);<br>
> + }<br>
> + }<br>
> +<br>
> // If this comparison is a normal comparison, it demands all<br>
> // bits, if it is a sign bit comparison, it only demands the sign<br>
> bit.<br>
> bool UnusedBit;<br>
><br>
> Added: llvm/trunk/test/Transforms/InstCombine/icmp-shr.ll<br>
> URL:<br>
> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/icmp-shr.ll?rev=213678&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/icmp-shr.ll?rev=213678&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/test/Transforms/InstCombine/icmp-shr.ll (added)<br>
> +++ llvm/trunk/test/Transforms/InstCombine/icmp-shr.ll Tue Jul 22<br>
> 14:19:36 2014<br>
> @@ -0,0 +1,677 @@<br>
> +; RUN: opt < %s -instcombine -S | FileCheck %s<br>
> +<br>
> +target datalayout =<br>
> "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"<br>
> +<br>
> +; CHECK-LABEL: @exact_lshr_eq_both_zero<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @exact_lshr_eq_both_zero(i8 %a) {<br>
> + %shr = lshr exact i8 0, %a<br>
> + %cmp = icmp eq i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_eq_both_zero<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @exact_ashr_eq_both_zero(i8 %a) {<br>
> + %shr = ashr exact i8 0, %a<br>
> + %cmp = icmp eq i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_lshr_eq_both_zero<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @nonexact_lshr_eq_both_zero(i8 %a) {<br>
> + %shr = lshr i8 0, %a<br>
> + %cmp = icmp eq i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_ashr_eq_both_zero<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @nonexact_ashr_eq_both_zero(i8 %a) {<br>
> + %shr = ashr i8 0, %a<br>
> + %cmp = icmp eq i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_lshr_ne_both_zero<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @exact_lshr_ne_both_zero(i8 %a) {<br>
> + %shr = lshr exact i8 0, %a<br>
> + %cmp = icmp ne i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_ne_both_zero<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @exact_ashr_ne_both_zero(i8 %a) {<br>
> + %shr = ashr exact i8 0, %a<br>
> + %cmp = icmp ne i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_lshr_ne_both_zero<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @nonexact_lshr_ne_both_zero(i8 %a) {<br>
> + %shr = lshr i8 0, %a<br>
> + %cmp = icmp ne i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_ashr_ne_both_zero<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @nonexact_ashr_ne_both_zero(i8 %a) {<br>
> + %shr = ashr i8 0, %a<br>
> + %cmp = icmp ne i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_lshr_eq_last_zero<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @exact_lshr_eq_last_zero(i8 %a) {<br>
> + %shr = lshr exact i8 128, %a<br>
> + %cmp = icmp eq i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_eq_last_zero<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @exact_ashr_eq_last_zero(i8 %a) {<br>
> + %shr = ashr exact i8 -128, %a<br>
> + %cmp = icmp eq i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_lshr_ne_last_zero<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @exact_lshr_ne_last_zero(i8 %a) {<br>
> + %shr = lshr exact i8 128, %a<br>
> + %cmp = icmp ne i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_ne_last_zero<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @exact_ashr_ne_last_zero(i8 %a) {<br>
> + %shr = ashr exact i8 -128, %a<br>
> + %cmp = icmp ne i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_lshr_eq_last_zero<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @nonexact_lshr_eq_last_zero(i8 %a) {<br>
> + %shr = lshr i8 128, %a<br>
> + %cmp = icmp eq i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_ashr_eq_last_zero<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @nonexact_ashr_eq_last_zero(i8 %a) {<br>
> + %shr = ashr i8 -128, %a<br>
> + %cmp = icmp eq i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_lshr_ne_last_zero<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @nonexact_lshr_ne_last_zero(i8 %a) {<br>
> + %shr = lshr i8 128, %a<br>
> + %cmp = icmp ne i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_ashr_ne_last_zero<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @nonexact_ashr_ne_last_zero(i8 %a) {<br>
> + %shr = ashr i8 -128, %a<br>
> + %cmp = icmp ne i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @lshr_eq_msb_low_last_zero<br>
> +; CHECK-NEXT: icmp ugt i8 %a, 6<br>
> +define i1 @lshr_eq_msb_low_last_zero(i8 %a) {<br>
> + %shr = lshr i8 127, %a<br>
> + %cmp = icmp eq i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @ashr_eq_msb_low_second_zero<br>
> +; CHECK-NEXT: icmp ugt i8 %a, 6<br>
> +define i1 @ashr_eq_msb_low_second_zero(i8 %a) {<br>
> + %shr = ashr i8 127, %a<br>
> + %cmp = icmp eq i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @lshr_ne_msb_low_last_zero<br>
> +; CHECK-NEXT: icmp ult i8 %a, 7<br>
> +define i1 @lshr_ne_msb_low_last_zero(i8 %a) {<br>
> + %shr = lshr i8 127, %a<br>
> + %cmp = icmp ne i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @ashr_ne_msb_low_second_zero<br>
> +; CHECK-NEXT: icmp ult i8 %a, 7<br>
> +define i1 @ashr_ne_msb_low_second_zero(i8 %a) {<br>
> + %shr = ashr i8 127, %a<br>
> + %cmp = icmp ne i8 %shr, 0<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @lshr_eq_first_zero<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @lshr_eq_first_zero(i8 %a) {<br>
> + %shr = lshr i8 0, %a<br>
> + %cmp = icmp eq i8 %shr, 2<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @ashr_eq_first_zero<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @ashr_eq_first_zero(i8 %a) {<br>
> + %shr = ashr i8 0, %a<br>
> + %cmp = icmp eq i8 %shr, 2<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @lshr_ne_first_zero<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @lshr_ne_first_zero(i8 %a) {<br>
> + %shr = lshr i8 0, %a<br>
> + %cmp = icmp ne i8 %shr, 2<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @ashr_ne_first_zero<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @ashr_ne_first_zero(i8 %a) {<br>
> + %shr = ashr i8 0, %a<br>
> + %cmp = icmp ne i8 %shr, 2<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @ashr_eq_both_minus1<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @ashr_eq_both_minus1(i8 %a) {<br>
> + %shr = ashr i8 -1, %a<br>
> + %cmp = icmp eq i8 %shr, -1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @ashr_ne_both_minus1<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @ashr_ne_both_minus1(i8 %a) {<br>
> + %shr = ashr i8 -1, %a<br>
> + %cmp = icmp ne i8 %shr, -1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_eq_both_minus1<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @exact_ashr_eq_both_minus1(i8 %a) {<br>
> + %shr = ashr exact i8 -1, %a<br>
> + %cmp = icmp eq i8 %shr, -1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_ne_both_minus1<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @exact_ashr_ne_both_minus1(i8 %a) {<br>
> + %shr = ashr exact i8 -1, %a<br>
> + %cmp = icmp ne i8 %shr, -1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @ashr_eq_both_equal<br>
> +; CHECK-NEXT: icmp eq i8 %a, 0<br>
> +define i1 @ashr_eq_both_equal(i8 %a) {<br>
> + %shr = ashr i8 128, %a<br>
> + %cmp = icmp eq i8 %shr, 128<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @ashr_ne_both_equal<br>
> +; CHECK-NEXT: icmp ne i8 %a, 0<br>
> +define i1 @ashr_ne_both_equal(i8 %a) {<br>
> + %shr = ashr i8 128, %a<br>
> + %cmp = icmp ne i8 %shr, 128<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @lshr_eq_both_equal<br>
> +; CHECK-NEXT: icmp eq i8 %a, 0<br>
> +define i1 @lshr_eq_both_equal(i8 %a) {<br>
> + %shr = lshr i8 127, %a<br>
> + %cmp = icmp eq i8 %shr, 127<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @lshr_ne_both_equal<br>
> +; CHECK-NEXT: icmp ne i8 %a, 0<br>
> +define i1 @lshr_ne_both_equal(i8 %a) {<br>
> + %shr = lshr i8 127, %a<br>
> + %cmp = icmp ne i8 %shr, 127<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_eq_both_equal<br>
> +; CHECK-NEXT: icmp eq i8 %a, 0<br>
> +define i1 @exact_ashr_eq_both_equal(i8 %a) {<br>
> + %shr = ashr exact i8 128, %a<br>
> + %cmp = icmp eq i8 %shr, 128<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_ne_both_equal<br>
> +; CHECK-NEXT: icmp ne i8 %a, 0<br>
> +define i1 @exact_ashr_ne_both_equal(i8 %a) {<br>
> + %shr = ashr exact i8 128, %a<br>
> + %cmp = icmp ne i8 %shr, 128<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_lshr_eq_both_equal<br>
> +; CHECK-NEXT: icmp eq i8 %a, 0<br>
> +define i1 @exact_lshr_eq_both_equal(i8 %a) {<br>
> + %shr = lshr exact i8 126, %a<br>
> + %cmp = icmp eq i8 %shr, 126<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_lshr_ne_both_equal<br>
> +; CHECK-NEXT: icmp ne i8 %a, 0<br>
> +define i1 @exact_lshr_ne_both_equal(i8 %a) {<br>
> + %shr = lshr exact i8 126, %a<br>
> + %cmp = icmp ne i8 %shr, 126<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_eq_opposite_msb<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @exact_ashr_eq_opposite_msb(i8 %a) {<br>
> + %shr = ashr exact i8 -128, %a<br>
> + %cmp = icmp eq i8 %shr, 1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @ashr_eq_opposite_msb<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @ashr_eq_opposite_msb(i8 %a) {<br>
> + %shr = ashr i8 -128, %a<br>
> + %cmp = icmp eq i8 %shr, 1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_lshr_eq_opposite_msb<br>
> +; CHECK-NEXT: icmp eq i8 %a, 7<br>
> +define i1 @exact_lshr_eq_opposite_msb(i8 %a) {<br>
> + %shr = lshr exact i8 -128, %a<br>
> + %cmp = icmp eq i8 %shr, 1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @lshr_eq_opposite_msb<br>
> +; CHECK-NEXT: icmp eq i8 %a, 7<br>
> +define i1 @lshr_eq_opposite_msb(i8 %a) {<br>
> + %shr = lshr i8 -128, %a<br>
> + %cmp = icmp eq i8 %shr, 1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_ne_opposite_msb<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @exact_ashr_ne_opposite_msb(i8 %a) {<br>
> + %shr = ashr exact i8 -128, %a<br>
> + %cmp = icmp ne i8 %shr, 1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @ashr_ne_opposite_msb<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @ashr_ne_opposite_msb(i8 %a) {<br>
> + %shr = ashr i8 -128, %a<br>
> + %cmp = icmp ne i8 %shr, 1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_lshr_ne_opposite_msb<br>
> +; CHECK-NEXT: icmp ne i8 %a, 7<br>
> +define i1 @exact_lshr_ne_opposite_msb(i8 %a) {<br>
> + %shr = lshr exact i8 -128, %a<br>
> + %cmp = icmp ne i8 %shr, 1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @lshr_ne_opposite_msb<br>
> +; CHECK-NEXT: icmp ne i8 %a, 7<br>
> +define i1 @lshr_ne_opposite_msb(i8 %a) {<br>
> + %shr = lshr i8 -128, %a<br>
> + %cmp = icmp ne i8 %shr, 1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_eq_shift_gt<br>
> +; CHECK-NEXT : ret i1 false<br>
> +define i1 @exact_ashr_eq_shift_gt(i8 %a) {<br>
> + %shr = ashr exact i8 -2, %a<br>
> + %cmp = icmp eq i8 %shr, -8<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_ne_shift_gt<br>
> +; CHECK-NEXT : ret i1 true<br>
> +define i1 @exact_ashr_ne_shift_gt(i8 %a) {<br>
> + %shr = ashr exact i8 -2, %a<br>
> + %cmp = icmp ne i8 %shr, -8<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_ashr_eq_shift_gt<br>
> +; CHECK-NEXT : ret i1 false<br>
> +define i1 @nonexact_ashr_eq_shift_gt(i8 %a) {<br>
> + %shr = ashr i8 -2, %a<br>
> + %cmp = icmp eq i8 %shr, -8<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_ashr_ne_shift_gt<br>
> +; CHECK-NEXT : ret i1 true<br>
> +define i1 @nonexact_ashr_ne_shift_gt(i8 %a) {<br>
> + %shr = ashr i8 -2, %a<br>
> + %cmp = icmp ne i8 %shr, -8<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_lshr_eq_shift_gt<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @exact_lshr_eq_shift_gt(i8 %a) {<br>
> + %shr = lshr exact i8 2, %a<br>
> + %cmp = icmp eq i8 %shr, 8<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_lshr_ne_shift_gt<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @exact_lshr_ne_shift_gt(i8 %a) {<br>
> + %shr = lshr exact i8 2, %a<br>
> + %cmp = icmp ne i8 %shr, 8<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_lshr_eq_shift_gt<br>
> +; CHECK-NEXT : ret i1 false<br>
> +define i1 @nonexact_lshr_eq_shift_gt(i8 %a) {<br>
> + %shr = lshr i8 2, %a<br>
> + %cmp = icmp eq i8 %shr, 8<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_lshr_ne_shift_gt<br>
> +; CHECK-NEXT : ret i1 true<br>
> +define i1 @nonexact_lshr_ne_shift_gt(i8 %a) {<br>
> + %shr = ashr i8 2, %a<br>
> + %cmp = icmp ne i8 %shr, 8<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_eq<br>
> +; CHECK-NEXT: icmp eq i8 %a, 7<br>
> +define i1 @exact_ashr_eq(i8 %a) {<br>
> + %shr = ashr exact i8 -128, %a<br>
> + %cmp = icmp eq i8 %shr, -1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_ne<br>
> +; CHECK-NEXT: icmp ne i8 %a, 7<br>
> +define i1 @exact_ashr_ne(i8 %a) {<br>
> + %shr = ashr exact i8 -128, %a<br>
> + %cmp = icmp ne i8 %shr, -1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_lshr_eq<br>
> +; CHECK-NEXT: icmp eq i8 %a, 2<br>
> +define i1 @exact_lshr_eq(i8 %a) {<br>
> + %shr = lshr exact i8 4, %a<br>
> + %cmp = icmp eq i8 %shr, 1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_lshr_ne<br>
> +; CHECK-NEXT: icmp ne i8 %a, 2<br>
> +define i1 @exact_lshr_ne(i8 %a) {<br>
> + %shr = lshr exact i8 4, %a<br>
> + %cmp = icmp ne i8 %shr, 1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_ashr_eq<br>
> +; CHECK-NEXT: icmp eq i8 %a, 7<br>
> +define i1 @nonexact_ashr_eq(i8 %a) {<br>
> + %shr = ashr i8 -128, %a<br>
> + %cmp = icmp eq i8 %shr, -1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_ashr_ne<br>
> +; CHECK-NEXT: icmp ne i8 %a, 7<br>
> +define i1 @nonexact_ashr_ne(i8 %a) {<br>
> + %shr = ashr i8 -128, %a<br>
> + %cmp = icmp ne i8 %shr, -1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_lshr_eq<br>
> +; CHECK-NEXT: icmp eq i8 %a, 2<br>
> +define i1 @nonexact_lshr_eq(i8 %a) {<br>
> + %shr = lshr i8 4, %a<br>
> + %cmp = icmp eq i8 %shr, 1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_lshr_ne<br>
> +; CHECK-NEXT: icmp ne i8 %a, 2<br>
> +define i1 @nonexact_lshr_ne(i8 %a) {<br>
> + %shr = lshr i8 4, %a<br>
> + %cmp = icmp ne i8 %shr, 1<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_lshr_eq_exactdiv<br>
> +; CHECK-NEXT: icmp eq i8 %a, 4<br>
> +define i1 @exact_lshr_eq_exactdiv(i8 %a) {<br>
> + %shr = lshr exact i8 80, %a<br>
> + %cmp = icmp eq i8 %shr, 5<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_lshr_ne_exactdiv<br>
> +; CHECK-NEXT: icmp ne i8 %a, 4<br>
> +define i1 @exact_lshr_ne_exactdiv(i8 %a) {<br>
> + %shr = lshr exact i8 80, %a<br>
> + %cmp = icmp ne i8 %shr, 5<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_lshr_eq_exactdiv<br>
> +; CHECK-NEXT: icmp eq i8 %a, 4<br>
> +define i1 @nonexact_lshr_eq_exactdiv(i8 %a) {<br>
> + %shr = lshr i8 80, %a<br>
> + %cmp = icmp eq i8 %shr, 5<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_lshr_ne_exactdiv<br>
> +; CHECK-NEXT: icmp ne i8 %a, 4<br>
> +define i1 @nonexact_lshr_ne_exactdiv(i8 %a) {<br>
> + %shr = lshr i8 80, %a<br>
> + %cmp = icmp ne i8 %shr, 5<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_eq_exactdiv<br>
> +; CHECK-NEXT: icmp eq i8 %a, 4<br>
> +define i1 @exact_ashr_eq_exactdiv(i8 %a) {<br>
> + %shr = ashr exact i8 -80, %a<br>
> + %cmp = icmp eq i8 %shr, -5<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_ne_exactdiv<br>
> +; CHECK-NEXT: icmp ne i8 %a, 4<br>
> +define i1 @exact_ashr_ne_exactdiv(i8 %a) {<br>
> + %shr = ashr exact i8 -80, %a<br>
> + %cmp = icmp ne i8 %shr, -5<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_ashr_eq_exactdiv<br>
> +; CHECK-NEXT: icmp eq i8 %a, 4<br>
> +define i1 @nonexact_ashr_eq_exactdiv(i8 %a) {<br>
> + %shr = ashr i8 -80, %a<br>
> + %cmp = icmp eq i8 %shr, -5<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_ashr_ne_exactdiv<br>
> +; CHECK-NEXT: icmp ne i8 %a, 4<br>
> +define i1 @nonexact_ashr_ne_exactdiv(i8 %a) {<br>
> + %shr = ashr i8 -80, %a<br>
> + %cmp = icmp ne i8 %shr, -5<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_lshr_eq_noexactdiv<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @exact_lshr_eq_noexactdiv(i8 %a) {<br>
> + %shr = lshr exact i8 80, %a<br>
> + %cmp = icmp eq i8 %shr, 31<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_lshr_ne_noexactdiv<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @exact_lshr_ne_noexactdiv(i8 %a) {<br>
> + %shr = lshr exact i8 80, %a<br>
> + %cmp = icmp ne i8 %shr, 31<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_lshr_eq_noexactdiv<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @nonexact_lshr_eq_noexactdiv(i8 %a) {<br>
> + %shr = lshr i8 80, %a<br>
> + %cmp = icmp eq i8 %shr, 31<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_lshr_ne_noexactdiv<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @nonexact_lshr_ne_noexactdiv(i8 %a) {<br>
> + %shr = lshr i8 80, %a<br>
> + %cmp = icmp ne i8 %shr, 31<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_eq_noexactdiv<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @exact_ashr_eq_noexactdiv(i8 %a) {<br>
> + %shr = ashr exact i8 -80, %a<br>
> + %cmp = icmp eq i8 %shr, -31<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_ne_noexactdiv<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @exact_ashr_ne_noexactdiv(i8 %a) {<br>
> + %shr = ashr exact i8 -80, %a<br>
> + %cmp = icmp ne i8 %shr, -31<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_ashr_eq_noexactdiv<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @nonexact_ashr_eq_noexactdiv(i8 %a) {<br>
> + %shr = ashr i8 -80, %a<br>
> + %cmp = icmp eq i8 %shr, -31<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_ashr_ne_noexactdiv<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @nonexact_ashr_ne_noexactdiv(i8 %a) {<br>
> + %shr = ashr i8 -80, %a<br>
> + %cmp = icmp ne i8 %shr, -31<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_lshr_eq_noexactlog<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @exact_lshr_eq_noexactlog(i8 %a) {<br>
> + %shr = lshr exact i8 90, %a<br>
> + %cmp = icmp eq i8 %shr, 30<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_lshr_ne_noexactlog<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @exact_lshr_ne_noexactlog(i8 %a) {<br>
> + %shr = lshr exact i8 90, %a<br>
> + %cmp = icmp ne i8 %shr, 30<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_lshr_eq_noexactlog<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @nonexact_lshr_eq_noexactlog(i8 %a) {<br>
> + %shr = lshr i8 90, %a<br>
> + %cmp = icmp eq i8 %shr, 30<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_lshr_ne_noexactlog<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @nonexact_lshr_ne_noexactlog(i8 %a) {<br>
> + %shr = lshr i8 90, %a<br>
> + %cmp = icmp ne i8 %shr, 30<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_eq_noexactlog<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @exact_ashr_eq_noexactlog(i8 %a) {<br>
> + %shr = ashr exact i8 -90, %a<br>
> + %cmp = icmp eq i8 %shr, -30<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @exact_ashr_ne_noexactlog<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @exact_ashr_ne_noexactlog(i8 %a) {<br>
> + %shr = ashr exact i8 -90, %a<br>
> + %cmp = icmp ne i8 %shr, -30<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_ashr_eq_noexactlog<br>
> +; CHECK-NEXT: ret i1 false<br>
> +define i1 @nonexact_ashr_eq_noexactlog(i8 %a) {<br>
> + %shr = ashr i8 -90, %a<br>
> + %cmp = icmp eq i8 %shr, -30<br>
> + ret i1 %cmp<br>
> +}<br>
> +<br>
> +; CHECK-LABEL: @nonexact_ashr_ne_noexactlog<br>
> +; CHECK-NEXT: ret i1 true<br>
> +define i1 @nonexact_ashr_ne_noexactlog(i8 %a) {<br>
> + %shr = ashr i8 -90, %a<br>
> + %cmp = icmp ne i8 %shr, -30<br>
> + ret i1 %cmp<br>
> +}<br>
><br>
><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
><br>
><br>
><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
><br>
<br>
</div></div><span><font color="#888888">--<br>
Hal Finkel<br>
Assistant Computational Scientist<br>
Leadership Computing Facility<br>
Argonne National Laboratory<br>
</font></span><div><div>_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</div></div></blockquote></div><br></div></div>