From 43b0e2584706c5c0efc86ea099ba8b54bb64743f Mon Sep 17 00:00:00 2001 From: David Bolvansky Date: Thu, 23 Aug 2018 15:22:15 +0000 Subject: [InstCombine] Fold Select with binary op - FP opcodes Summary: Follow up for https://reviews.llvm.org/rL339520 and https://reviews.llvm.org/rL338300 Alive: ``` %A = fcmp oeq float %x, 0.0 %B = fadd nsz float %x, %z %C = select i1 %A, float %B, float %y => %C = select i1 %A, float %z, float %y ---------- %A = fcmp oeq float %x, 0.0 %B = fadd nsz float %x, %z %C = select %A, float %B, float %y => %C = select %A, float %z, float %y Done: 1 Optimization is correct %A = fcmp une float %x, -0.0 %B = fadd nsz float %x, %z %C = select i1 %A, float %y, float %B => %C = select i1 %A, float %y, float %z ---------- %A = fcmp une float %x, -0.0 %B = fadd nsz float %x, %z %C = select %A, float %y, float %B => %C = select %A, float %y, float %z Done: 1 Optimization is correct ``` Reviewers: spatel, lebedev.ri Reviewed By: spatel Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D50714 llvm-svn: 340538 --- .../Transforms/InstCombine/InstCombineSelect.cpp | 25 ++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'llvm/lib') diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index f09a67d96f3..07a25c45118 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -56,19 +56,26 @@ static Value *createMinMax(InstCombiner::BuilderTy &Builder, /// Replace a select operand based on an equality comparison with the identity /// constant of a binop. -static Instruction *foldSelectBinOpIdentity(SelectInst &Sel) { +static Instruction *foldSelectBinOpIdentity(SelectInst &Sel, const TargetLibraryInfo &TLI) { // The select condition must be an equality compare with a constant operand. - // TODO: Support FP compares. Value *X; Constant *C; CmpInst::Predicate Pred; - if (!match(Sel.getCondition(), m_ICmp(Pred, m_Value(X), m_Constant(C))) || - !ICmpInst::isEquality(Pred)) + if (!match(Sel.getCondition(), m_Cmp(Pred, m_Value(X), m_Constant(C)))) + return nullptr; + + bool IsEq; + if (ICmpInst::isEquality(Pred)) + IsEq = Pred == ICmpInst::ICMP_EQ; + else if (Pred == FCmpInst::FCMP_OEQ) + IsEq = true; + else if (Pred == FCmpInst::FCMP_UNE) + IsEq = false; + else return nullptr; // A select operand must be a binop, and the compare constant must be the // identity constant for that binop. - bool IsEq = Pred == ICmpInst::ICMP_EQ; BinaryOperator *BO; if (!match(Sel.getOperand(IsEq ? 1 : 2), m_BinOp(BO)) || ConstantExpr::getBinOpIdentity(BO->getOpcode(), BO->getType(), true) != C) @@ -81,6 +88,12 @@ static Instruction *foldSelectBinOpIdentity(SelectInst &Sel) { if (!match(BO, m_c_BinOp(m_Value(Y), m_Specific(X)))) return nullptr; + // +0.0 compares equal to -0.0, and so it does not behave as required for this + // transform. Bail out if we can not exclude that possibility. + if (isa(BO)) + if (!BO->hasNoSignedZeros() && !CannotBeNegativeZero(Y, &TLI)) + return nullptr; + // BO = binop Y, X // S = { select (cmp eq X, C), BO, ? } or { select (cmp ne X, C), ?, BO } // => @@ -2000,7 +2013,7 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { if (Instruction *Select = foldSelectCmpXchg(SI)) return Select; - if (Instruction *Select = foldSelectBinOpIdentity(SI)) + if (Instruction *Select = foldSelectBinOpIdentity(SI, TLI)) return Select; return nullptr; -- cgit v1.2.3