Summary:
See the two test cases.
; Can fold fcmp with undef on one side by choosing NaN for the undef
; Can fold fcmp with undef on both side
; fcmp u_pred undef, undef -> true
; fcmp o_pred undef, undef -> false
; because whatever you choose for the first undef
; you can choose NaN for the other undef
Reviewers: hfinkel, chandlerc, majnemer
Reviewed By: majnemer
Subscribers: majnemer, llvm-commits
Differential Revision: http://reviews.llvm.org/D7617
From: Mehdi Amini <mehdi.amini@apple.com>
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@231626
91177308-0d34-0410-b5e6-
96231b3b80d8
/// @returns true if the predicate of this instruction is EQ or NE.
/// \brief Determine if this is an equality predicate.
- bool isEquality() const {
- return getPredicate() == FCMP_OEQ || getPredicate() == FCMP_ONE ||
- getPredicate() == FCMP_UEQ || getPredicate() == FCMP_UNE;
+ static bool isEquality(Predicate Pred) {
+ return Pred == FCMP_OEQ || Pred == FCMP_ONE || Pred == FCMP_UEQ ||
+ Pred == FCMP_UNE;
}
+ /// @returns true if the predicate of this instruction is EQ or NE.
+ /// \brief Determine if this is an equality predicate.
+ bool isEquality() const { return isEquality(getPredicate()); }
+
/// @returns true if the predicate of this instruction is commutative.
/// \brief Determine if this is a commutative predicate.
bool isCommutative() const {
if (Pred == FCmpInst::FCMP_TRUE)
return ConstantInt::get(GetCompareTy(LHS), 1);
- if (isa<UndefValue>(RHS)) // fcmp pred X, undef -> undef
- return UndefValue::get(GetCompareTy(LHS));
+ // fcmp pred x, undef and fcmp pred undef, x
+ // fold to true if unordered, false if ordered
+ if (isa<UndefValue>(LHS) || isa<UndefValue>(RHS)) {
+ // Choosing NaN for the undef will always make unordered comparison succeed
+ // and ordered comparison fail.
+ return ConstantInt::get(GetCompareTy(LHS), CmpInst::isUnordered(Pred));
+ }
// fcmp x,x -> true/false. Not all compares are foldable.
if (LHS == RHS) {
if (!isa<ConstantExpr>(V1)) {
if (!isa<ConstantExpr>(V2)) {
- // We distilled thisUse the standard constant folder for a few cases
+ // Simple case, use the standard constant folder.
ConstantInt *R = nullptr;
R = dyn_cast<ConstantInt>(
ConstantExpr::getFCmp(FCmpInst::FCMP_OEQ, V1, V2));
// Handle some degenerate cases first
if (isa<UndefValue>(C1) || isa<UndefValue>(C2)) {
+ CmpInst::Predicate Predicate = CmpInst::Predicate(pred);
+ bool isIntegerPredicate = ICmpInst::isIntPredicate(Predicate);
// For EQ and NE, we can always pick a value for the undef to make the
// predicate pass or fail, so we can return undef.
- // Also, if both operands are undef, we can return undef.
- if (ICmpInst::isEquality(ICmpInst::Predicate(pred)) ||
- (isa<UndefValue>(C1) && isa<UndefValue>(C2)))
+ // Also, if both operands are undef, we can return undef for int comparison.
+ if (ICmpInst::isEquality(Predicate) || (isIntegerPredicate && C1 == C2))
return UndefValue::get(ResultTy);
- // Otherwise, pick the same value as the non-undef operand, and fold
- // it to true or false.
- return ConstantInt::get(ResultTy, CmpInst::isTrueWhenEqual(pred));
+
+ // Otherwise, for integer compare, pick the same value as the non-undef
+ // operand, and fold it to true or false.
+ if (isIntegerPredicate)
+ return ConstantInt::get(ResultTy, CmpInst::isTrueWhenEqual(pred));
+
+ // Choosing NaN for the undef will always make unordered comparison succeed
+ // and ordered comparison fails.
+ return ConstantInt::get(ResultTy, CmpInst::isUnordered(Predicate));
}
// icmp eq/ne(null,GV) -> false/true
return ConstantVector::get(ResElts);
}
- if (C1->getType()->isFloatingPointTy()) {
+ if (C1->getType()->isFloatingPointTy() &&
+ // Only call evaluateFCmpRelation if we have a constant expr to avoid
+ // infinite recursive loop
+ (isa<ConstantExpr>(C1) || isa<ConstantExpr>(C2))) {
int Result = -1; // -1 = unknown, 0 = known false, 1 = known true.
switch (evaluateFCmpRelation(C1, C2)) {
default: llvm_unreachable("Unknown relation!");
%conv = zext i1 %cmp to i32
ret i32 %conv
}
+
+; Can fold fcmp with undef on one side by choosing NaN for the undef
+define i32 @test18_undef_unordered(float %a) nounwind {
+; CHECK-LABEL: @test18_undef_unordered
+; CHECK: ret i32 1
+ %cmp = fcmp ueq float %a, undef
+ %conv = zext i1 %cmp to i32
+ ret i32 %conv
+}
+; Can fold fcmp with undef on one side by choosing NaN for the undef
+define i32 @test18_undef_ordered(float %a) nounwind {
+; CHECK-LABEL: @test18_undef_ordered
+; CHECK: ret i32 0
+ %cmp = fcmp oeq float %a, undef
+ %conv = zext i1 %cmp to i32
+ ret i32 %conv
+}
+
+; Can fold fcmp with undef on both side
+; fcmp u_pred undef, undef -> true
+; fcmp o_pred undef, undef -> false
+; because whatever you choose for the first undef
+; you can choose NaN for the other undef
+define i1 @test19_undef_unordered() nounwind {
+; CHECK-LABEL: @test19_undef
+; CHECK: ret i1 true
+ %cmp = fcmp ueq float undef, undef
+ ret i1 %cmp
+}
+define i1 @test19_undef_ordered() nounwind {
+; CHECK-LABEL: @test19_undef
+; CHECK: ret i1 false
+ %cmp = fcmp oeq float undef, undef
+ ret i1 %cmp
+}