From: John Brawn Date: Mon, 4 Jun 2018 16:53:57 +0000 (+0000) Subject: [ValueTracking] Match select abs pattern when there's an sext involved X-Git-Tag: android-x86-7.1-r4~262 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=9495e9e09deaf5ac1e2b0098b3ed0e3436fd115e;p=android-x86%2Fexternal-llvm.git [ValueTracking] Match select abs pattern when there's an sext involved When checking a select to see if it matches an abs, allow the true/false values to be a sign-extension of the comparison value instead of requiring that they're directly the comparison value, as all the comparison cares about is the sign of the value. This fixes a regression due to r333702, where we were no longer generating ctlz due to isKnownNonNegative failing to match such a pattern. Differential Revision: https://reviews.llvm.org/D47631 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@333927 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index 8cff7a696b2..12002de7928 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -4604,23 +4604,35 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred, const APInt *C1; if (match(CmpRHS, m_APInt(C1))) { - if ((CmpLHS == TrueVal && match(FalseVal, m_Neg(m_Specific(CmpLHS)))) || - (CmpLHS == FalseVal && match(TrueVal, m_Neg(m_Specific(CmpLHS))))) { - // Set RHS to the negate operand. LHS was assigned to CmpLHS earlier. - RHS = (CmpLHS == TrueVal) ? FalseVal : TrueVal; + // Sign-extending LHS does not change its sign, so TrueVal/FalseVal can + // match against either LHS or sext(LHS). + auto MaybeSExtLHS = m_CombineOr(m_Specific(CmpLHS), + m_SExt(m_Specific(CmpLHS))); + if ((match(TrueVal, MaybeSExtLHS) && + match(FalseVal, m_Neg(m_Specific(TrueVal)))) || + (match(FalseVal, MaybeSExtLHS) && + match(TrueVal, m_Neg(m_Specific(FalseVal))))) { + // Set LHS and RHS so that RHS is the negated operand of the select + if (match(TrueVal, MaybeSExtLHS)) { + LHS = TrueVal; + RHS = FalseVal; + } else { + LHS = FalseVal; + RHS = TrueVal; + } // ABS(X) ==> (X >s 0) ? X : -X and (X >s -1) ? X : -X // NABS(X) ==> (X >s 0) ? -X : X and (X >s -1) ? -X : X if (Pred == ICmpInst::ICMP_SGT && (C1->isNullValue() || C1->isAllOnesValue())) { - return {(CmpLHS == TrueVal) ? SPF_ABS : SPF_NABS, SPNB_NA, false}; + return {(LHS == TrueVal) ? SPF_ABS : SPF_NABS, SPNB_NA, false}; } // ABS(X) ==> (X (X isNullValue() || C1->isOneValue())) { - return {(CmpLHS == FalseVal) ? SPF_ABS : SPF_NABS, SPNB_NA, false}; + return {(LHS == FalseVal) ? SPF_ABS : SPF_NABS, SPNB_NA, false}; } } } diff --git a/test/Transforms/LoopIdiom/ARM/ctlz.ll b/test/Transforms/LoopIdiom/ARM/ctlz.ll index 1f4a879b27e..2a95edfcf38 100644 --- a/test/Transforms/LoopIdiom/ARM/ctlz.ll +++ b/test/Transforms/LoopIdiom/ARM/ctlz.ll @@ -199,3 +199,48 @@ while.cond: ; preds = %while.cond, %entry while.end: ; preds = %while.cond ret i32 %i.0 } + +; Recognize CTLZ builtin pattern. +; Here it will replace the loop - +; assume builtin is always profitable. +; +; int ctlz_sext(short in) +; { +; int n = in; +; if (in < 0) +; n = -n; +; int i = 0; +; while(n >>= 1) { +; i++; +; } +; return i; +; } +; +; ALL: entry +; ALL: %0 = ashr i32 %abs_n, 1 +; ALL-NEXT: %1 = call i32 @llvm.ctlz.i32(i32 %0, i1 false) +; ALL-NEXT: %2 = sub i32 32, %1 +; ALL-NEXT: %3 = add i32 %2, 1 +; ALL: %i.0.lcssa = phi i32 [ %2, %while.cond ] +; ALL: ret i32 %i.0.lcssa + +; Function Attrs: norecurse nounwind readnone uwtable +define i32 @ctlz_sext(i16 %in) { +entry: + %n = sext i16 %in to i32 + %c = icmp sgt i16 %in, 0 + %negn = sub nsw i32 0, %n + %abs_n = select i1 %c, i32 %n, i32 %negn + br label %while.cond + +while.cond: ; preds = %while.cond, %entry + %n.addr.0 = phi i32 [ %abs_n, %entry ], [ %shr, %while.cond ] + %i.0 = phi i32 [ 0, %entry ], [ %inc, %while.cond ] + %shr = ashr i32 %n.addr.0, 1 + %tobool = icmp eq i32 %shr, 0 + %inc = add nsw i32 %i.0, 1 + br i1 %tobool, label %while.end, label %while.cond + +while.end: ; preds = %while.cond + ret i32 %i.0 +} diff --git a/test/Transforms/LoopIdiom/X86/ctlz.ll b/test/Transforms/LoopIdiom/X86/ctlz.ll index 2044f43bc22..1ce13e25fe5 100644 --- a/test/Transforms/LoopIdiom/X86/ctlz.ll +++ b/test/Transforms/LoopIdiom/X86/ctlz.ll @@ -200,6 +200,51 @@ while.end: ; preds = %while.cond ret i32 %i.0 } +; Recognize CTLZ builtin pattern. +; Here it will replace the loop - +; assume builtin is always profitable. +; +; int ctlz_sext(short in) +; { +; int n = in; +; if (in < 0) +; n = -n; +; int i = 0; +; while(n >>= 1) { +; i++; +; } +; return i; +; } +; +; ALL: entry +; ALL: %0 = ashr i32 %abs_n, 1 +; ALL-NEXT: %1 = call i32 @llvm.ctlz.i32(i32 %0, i1 false) +; ALL-NEXT: %2 = sub i32 32, %1 +; ALL-NEXT: %3 = add i32 %2, 1 +; ALL: %i.0.lcssa = phi i32 [ %2, %while.cond ] +; ALL: ret i32 %i.0.lcssa + +; Function Attrs: norecurse nounwind readnone uwtable +define i32 @ctlz_sext(i16 %in) { +entry: + %n = sext i16 %in to i32 + %c = icmp sgt i16 %in, 0 + %negn = sub nsw i32 0, %n + %abs_n = select i1 %c, i32 %n, i32 %negn + br label %while.cond + +while.cond: ; preds = %while.cond, %entry + %n.addr.0 = phi i32 [ %abs_n, %entry ], [ %shr, %while.cond ] + %i.0 = phi i32 [ 0, %entry ], [ %inc, %while.cond ] + %shr = ashr i32 %n.addr.0, 1 + %tobool = icmp eq i32 %shr, 0 + %inc = add nsw i32 %i.0, 1 + br i1 %tobool, label %while.end, label %while.cond + +while.end: ; preds = %while.cond + ret i32 %i.0 +} + ; This loop contains a volatile store. If x is initially negative, ; the code will be an infinite loop because the ashr will eventually produce ; all ones and continue doing so. This prevents the loop from terminating. If