aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-10-24 05:38:08 +0000
committerChris Lattner <sabre@nondot.org>2007-10-24 05:38:08 +0000
commit99c65745a2c5dfc66e3943633fb8ab3d2b94418d (patch)
tree7f060994e7e1438587fc99fddf7e4e5320dacd0c
parent9ac0ca07f9e1a12f224994aa297cfc856e4b1e0d (diff)
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
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp48
-rw-r--r--test/Transforms/InstCombine/and2.ll12
-rw-r--r--test/Transforms/InstCombine/or2.ll12
3 files changed, 68 insertions, 4 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index fb7b8d881d..ef86d2861d 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<FCmpInst>(I.getOperand(0))) {
+ if (FCmpInst *RHS = dyn_cast<FCmpInst>(I.getOperand(1))) {
+ if (LHS->getPredicate() == FCmpInst::FCMP_ORD &&
+ RHS->getPredicate() == FCmpInst::FCMP_ORD)
+ if (ConstantFP *LHSC = dyn_cast<ConstantFP>(LHS->getOperand(1)))
+ if (ConstantFP *RHSC = dyn_cast<ConstantFP>(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<CastInst>(Op0))
+ if (CastInst *Op0C = dyn_cast<CastInst>(Op0)) {
if (CastInst *Op1C = dyn_cast<CastInst>(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<FCmpInst>(I.getOperand(0))) {
+ if (FCmpInst *RHS = dyn_cast<FCmpInst>(I.getOperand(1))) {
+ if (LHS->getPredicate() == FCmpInst::FCMP_UNO &&
+ RHS->getPredicate() == FCmpInst::FCMP_UNO)
+ if (ConstantFP *LHSC = dyn_cast<ConstantFP>(LHS->getOperand(1)))
+ if (ConstantFP *RHSC = dyn_cast<ConstantFP>(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<CastInst>(Op0))
+ if (CastInst *Op0C = dyn_cast<CastInst>(Op0)) {
if (CastInst *Op1C = dyn_cast<CastInst>(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 0000000000..3b80d94e1a
--- /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 0000000000..f14a274391
--- /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 ; <i1> [#uses=1]
+ %tmp13 = fcmp uno double %Y, 0.000000e+00 ; <i1> [#uses=1]
+ %bothcond = or i1 %tmp13, %tmp9 ; <i1> [#uses=1]
+ ret i1 %bothcond
+}
+