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!");
return new FCmpInst(FCmpInst::FCMP_OLE, LHS, RHS);
else
return new FCmpInst(FCmpInst::FCMP_ULE, LHS, RHS);
+ case 7: return ConstantInt::getTrue();
}
}
if (FCmpInst *RHS = dyn_cast<FCmpInst>(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<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
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<Instruction>(RV))
+ return I;
+ // Otherwise, it's a constant boolean value...
+ return ReplaceInstUsesWith(I, RV);
+ }
+ }
+ }
+ }
}
}
--- /dev/null
+; 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 ; <i1> [#uses=1]
+ %b = fcmp uno float %x, %y ; <i1> [#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 ; <i1> [#uses=1]
+ %b = fcmp oeq float %x, %y ; <i1> [#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 ; <i1> [#uses=1]
+ %b = fcmp uge float %x, %y ; <i1> [#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 ; <i1> [#uses=1]
+ %b = fcmp ugt float %x, %y ; <i1> [#uses=1]
+ %c = or i1 %a, %b
+ %retval = zext i1 %c to i8
+ ret i8 %retval
+}