diff options
author | Craig Topper <craig.topper@intel.com> | 2018-09-22 05:53:27 +0000 |
---|---|---|
committer | Craig Topper <craig.topper@intel.com> | 2018-09-22 05:53:27 +0000 |
commit | 2b3f5df73a7d3413c4f354d57ff377b8982af207 (patch) | |
tree | 9a83db44907e8ef0718cb801b1a928f04ca4326e /llvm/lib/Transforms | |
parent | 082e04c61d2b6c6b6ed3a8e010e9b1b1a3a22ef4 (diff) | |
download | bcm5719-llvm-2b3f5df73a7d3413c4f354d57ff377b8982af207.tar.gz bcm5719-llvm-2b3f5df73a7d3413c4f354d57ff377b8982af207.zip |
[InstCombine] Fold (min/max ~X, Y) -> ~(max/min X, ~Y) when Y is freely invertible
Summary: This restores the combine that was reverted in r341883. The infinite loop from the failing test no longer occurs due to changes from r342163.
Reviewers: spatel, dmgreen
Reviewed By: spatel
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D52070
llvm-svn: 342797
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index b7e237eb6ed..f42deff7409 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -1844,17 +1844,43 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { } // MAX(~a, ~b) -> ~MIN(a, b) + // MAX(~a, C) -> ~MIN(a, ~C) // MIN(~a, ~b) -> ~MAX(a, b) - Value *A, *B; - if (match(LHS, m_Not(m_Value(A))) && match(RHS, m_Not(m_Value(B))) && - !IsFreeToInvert(A, A->hasOneUse()) && - !IsFreeToInvert(B, B->hasOneUse()) && - (!LHS->hasNUsesOrMore(3) || !RHS->hasNUsesOrMore(3))) { - CmpInst::Predicate InvertedPred = getInverseMinMaxPred(SPF); - Value *InvertedCmp = Builder.CreateICmp(InvertedPred, A, B); - Value *NewSel = Builder.CreateSelect(InvertedCmp, A, B); - return BinaryOperator::CreateNot(NewSel); - } + // MIN(~a, C) -> ~MAX(a, ~C) + auto moveNotAfterMinMax = [&](Value *X, Value *Y, + bool Swapped) -> Instruction * { + Value *A; + if (match(X, m_Not(m_Value(A))) && !X->hasNUsesOrMore(3) && + !IsFreeToInvert(A, A->hasOneUse()) && + // Passing false to only consider m_Not and constants. + IsFreeToInvert(Y, false)) { + Value *B = Builder.CreateNot(Y); + Value *NewMinMax = createMinMax(Builder, getInverseMinMaxFlavor(SPF), + A, B); + // Copy the profile metadata. + if (MDNode *MD = SI.getMetadata(LLVMContext::MD_prof)) { + cast<SelectInst>(NewMinMax)->setMetadata(LLVMContext::MD_prof, MD); + // Swap the metadata if the operands are swapped. + if (Swapped) { + assert(X == SI.getFalseValue() && Y == SI.getTrueValue() && + "Unexpected operands."); + cast<SelectInst>(NewMinMax)->swapProfMetadata(); + } else { + assert(X == SI.getTrueValue() && Y == SI.getFalseValue() && + "Unexpected operands."); + } + } + + return BinaryOperator::CreateNot(NewMinMax); + } + + return nullptr; + }; + + if (Instruction *I = moveNotAfterMinMax(LHS, RHS, /*Swapped*/false)) + return I; + if (Instruction *I = moveNotAfterMinMax(RHS, LHS, /*Swapped*/true)) + return I; if (Instruction *I = factorizeMinMaxTree(SPF, LHS, RHS, Builder)) return I; |