From 99c65745a2c5dfc66e3943633fb8ab3d2b94418d Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 24 Oct 2007 05:38:08 +0000 Subject: [PATCH] Implement a couple of foldings for ordered and unordered comparisons, implementing cases related to PR1738. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43289 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Scalar/InstructionCombining.cpp | 48 +++++++++++++++++-- test/Transforms/InstCombine/and2.ll | 12 +++++ test/Transforms/InstCombine/or2.ll | 12 +++++ 3 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 test/Transforms/InstCombine/and2.ll create mode 100644 test/Transforms/InstCombine/or2.ll diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index fb7b8d881d7..ef86d2861da 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -3628,6 +3628,24 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) { } } + // (fcmp ord x, c) & (fcmp ord y, c) -> (fcmp ord x, y) + if (FCmpInst *LHS = dyn_cast(I.getOperand(0))) { + if (FCmpInst *RHS = dyn_cast(I.getOperand(1))) { + if (LHS->getPredicate() == FCmpInst::FCMP_ORD && + RHS->getPredicate() == FCmpInst::FCMP_ORD) + 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 + // false. + if (LHSC->getValueAPF().getCategory() == APFloat::fcNaN || + RHSC->getValueAPF().getCategory() == APFloat::fcNaN) + return ReplaceInstUsesWith(I, ConstantInt::getFalse()); + return new FCmpInst(FCmpInst::FCMP_ORD, LHS->getOperand(0), + RHS->getOperand(0)); + } + } + } + return Changed ? &I : 0; } @@ -4074,7 +4092,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { } // fold (or (cast A), (cast B)) -> (cast (or A, B)) - if (CastInst *Op0C = dyn_cast(Op0)) + if (CastInst *Op0C = dyn_cast(Op0)) { if (CastInst *Op1C = dyn_cast(Op1)) if (Op0C->getOpcode() == Op1C->getOpcode()) {// same cast kind ? const Type *SrcTy = Op0C->getOperand(0)->getType(); @@ -4091,7 +4109,29 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { return CastInst::create(Op0C->getOpcode(), NewOp, I.getType()); } } - + } + + + // (fcmp uno x, c) | (fcmp uno y, c) -> (fcmp uno x, y) + if (FCmpInst *LHS = dyn_cast(I.getOperand(0))) { + if (FCmpInst *RHS = dyn_cast(I.getOperand(1))) { + if (LHS->getPredicate() == FCmpInst::FCMP_UNO && + RHS->getPredicate() == FCmpInst::FCMP_UNO) + 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 + // true. + if (LHSC->getValueAPF().getCategory() == APFloat::fcNaN || + RHSC->getValueAPF().getCategory() == APFloat::fcNaN) + return ReplaceInstUsesWith(I, ConstantInt::getTrue()); + + // Otherwise, no need to compare the two constants, compare the + // rest. + return new FCmpInst(FCmpInst::FCMP_UNO, LHS->getOperand(0), + RHS->getOperand(0)); + } + } + } return Changed ? &I : 0; } @@ -4341,7 +4381,7 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) { return R; // fold (xor (cast A), (cast B)) -> (cast (xor A, B)) - if (CastInst *Op0C = dyn_cast(Op0)) + if (CastInst *Op0C = dyn_cast(Op0)) { if (CastInst *Op1C = dyn_cast(Op1)) if (Op0C->getOpcode() == Op1C->getOpcode()) { // same cast kind? const Type *SrcTy = Op0C->getOperand(0)->getType(); @@ -4358,7 +4398,7 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) { return CastInst::create(Op0C->getOpcode(), NewOp, I.getType()); } } - + } return Changed ? &I : 0; } diff --git a/test/Transforms/InstCombine/and2.ll b/test/Transforms/InstCombine/and2.ll new file mode 100644 index 00000000000..3b80d94e1a6 --- /dev/null +++ b/test/Transforms/InstCombine/and2.ll @@ -0,0 +1,12 @@ +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep and + + +; PR1738 +define i1 @test1(double %X, double %Y) { + %tmp9 = fcmp ord double %X, 0.000000e+00 + %tmp13 = fcmp ord double %Y, 0.000000e+00 + %bothcond = and i1 %tmp13, %tmp9 + ret i1 %bothcond +} + + diff --git a/test/Transforms/InstCombine/or2.ll b/test/Transforms/InstCombine/or2.ll new file mode 100644 index 00000000000..f14a2743916 --- /dev/null +++ b/test/Transforms/InstCombine/or2.ll @@ -0,0 +1,12 @@ +; This test makes sure that these instructions are properly eliminated. +; +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep -v xor | not grep {or } + +; PR1738 +define i1 @test1(double %X, double %Y) { + %tmp9 = fcmp uno double %X, 0.000000e+00 ; [#uses=1] + %tmp13 = fcmp uno double %Y, 0.000000e+00 ; [#uses=1] + %bothcond = or i1 %tmp13, %tmp9 ; [#uses=1] + ret i1 %bothcond +} + -- 2.34.1