From 403006205f8b77668f06123a2330250c743e407e Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Tue, 14 Oct 2008 18:44:08 +0000 Subject: [PATCH] Combine (fcmp cc0 x, y) | (fcmp cc1 x, y) into a single fcmp when possible. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@57515 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Scalar/InstructionCombining.cpp | 42 ++++++++++++++++++- test/Transforms/InstCombine/or-fcmp.ll | 34 +++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 test/Transforms/InstCombine/or-fcmp.ll diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index a687dbde101..f0beacfe101 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -3136,6 +3136,7 @@ static unsigned getFCmpCode(FCmpInst::Predicate CC, bool &isOrdered) { case FCmpInst::FCMP_UNE: return 5; // 101 case FCmpInst::FCMP_OLE: isOrdered = true; return 6; // 110 case FCmpInst::FCMP_ULE: return 6; // 110 + // True -> 7 default: // Not expecting FCMP_FALSE and FCMP_TRUE; assert(0 && "Unexpected FCmp predicate!"); @@ -3219,6 +3220,7 @@ static Value *getFCmpValue(bool isordered, unsigned code, return new FCmpInst(FCmpInst::FCMP_OLE, LHS, RHS); else return new FCmpInst(FCmpInst::FCMP_ULE, LHS, RHS); + case 7: return ConstantInt::getTrue(); } } @@ -4555,7 +4557,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { if (FCmpInst *RHS = dyn_cast(I.getOperand(1))) { if (LHS->getPredicate() == FCmpInst::FCMP_UNO && RHS->getPredicate() == FCmpInst::FCMP_UNO && - LHS->getOperand(0)->getType() == RHS->getOperand(0)->getType()) + LHS->getOperand(0)->getType() == RHS->getOperand(0)->getType()) { if (ConstantFP *LHSC = dyn_cast(LHS->getOperand(1))) if (ConstantFP *RHSC = dyn_cast(RHS->getOperand(1))) { // If either of the constants are nans, then the whole thing returns @@ -4568,6 +4570,44 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { return new FCmpInst(FCmpInst::FCMP_UNO, LHS->getOperand(0), RHS->getOperand(0)); } + } else { + Value *Op0LHS, *Op0RHS, *Op1LHS, *Op1RHS; + FCmpInst::Predicate Op0CC, Op1CC; + if (match(Op0, m_FCmp(Op0CC, m_Value(Op0LHS), m_Value(Op0RHS))) && + match(Op1, m_FCmp(Op1CC, m_Value(Op1LHS), m_Value(Op1RHS)))) { + if (Op0LHS == Op1RHS && Op0RHS == Op1LHS) { + // Swap RHS operands to match LHS. + Op1CC = FCmpInst::getSwappedPredicate(Op1CC); + std::swap(Op1LHS, Op1RHS); + } + if (Op0LHS == Op1LHS && Op0RHS == Op1RHS) { + // Simplify (fcmp cc0 x, y) | (fcmp cc1 x, y). + if (Op0CC == Op1CC) + return new FCmpInst((FCmpInst::Predicate)Op0CC, Op0LHS, Op0RHS); + else if (Op0CC == FCmpInst::FCMP_TRUE || + Op1CC == FCmpInst::FCMP_TRUE) + return ReplaceInstUsesWith(I, ConstantInt::getTrue()); + else if (Op0CC == FCmpInst::FCMP_FALSE) + return ReplaceInstUsesWith(I, Op1); + else if (Op1CC == FCmpInst::FCMP_FALSE) + return ReplaceInstUsesWith(I, Op0); + bool Op0Ordered; + bool Op1Ordered; + unsigned Op0Pred = getFCmpCode(Op0CC, Op0Ordered); + unsigned Op1Pred = getFCmpCode(Op1CC, Op1Ordered); + if (Op0Ordered == Op1Ordered) { + // If both are ordered or unordered, return a new fcmp with + // or'ed predicates. + Value *RV = getFCmpValue(Op0Ordered, Op0Pred|Op1Pred, + Op0LHS, Op0RHS); + if (Instruction *I = dyn_cast(RV)) + return I; + // Otherwise, it's a constant boolean value... + return ReplaceInstUsesWith(I, RV); + } + } + } + } } } diff --git a/test/Transforms/InstCombine/or-fcmp.ll b/test/Transforms/InstCombine/or-fcmp.ll new file mode 100644 index 00000000000..3833c6f706f --- /dev/null +++ b/test/Transforms/InstCombine/or-fcmp.ll @@ -0,0 +1,34 @@ +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep fcmp | count 3 +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep ret | grep 1 + +define zeroext i8 @t1(float %x, float %y) nounwind { + %a = fcmp ueq float %x, %y ; [#uses=1] + %b = fcmp uno float %x, %y ; [#uses=1] + %c = or i1 %a, %b + %retval = zext i1 %c to i8 + ret i8 %retval +} + +define zeroext i8 @t2(float %x, float %y) nounwind { + %a = fcmp olt float %x, %y ; [#uses=1] + %b = fcmp oeq float %x, %y ; [#uses=1] + %c = or i1 %a, %b + %retval = zext i1 %c to i8 + ret i8 %retval +} + +define zeroext i8 @t3(float %x, float %y) nounwind { + %a = fcmp ult float %x, %y ; [#uses=1] + %b = fcmp uge float %x, %y ; [#uses=1] + %c = or i1 %a, %b + %retval = zext i1 %c to i8 + ret i8 %retval +} + +define zeroext i8 @t4(float %x, float %y) nounwind { + %a = fcmp ult float %x, %y ; [#uses=1] + %b = fcmp ugt float %x, %y ; [#uses=1] + %c = or i1 %a, %b + %retval = zext i1 %c to i8 + ret i8 %retval +}