Index: include/llvm/IR/Instructions.h =================================================================== --- include/llvm/IR/Instructions.h +++ include/llvm/IR/Instructions.h @@ -1201,11 +1201,15 @@ /// @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 { Index: lib/Analysis/InstructionSimplify.cpp =================================================================== --- lib/Analysis/InstructionSimplify.cpp +++ lib/Analysis/InstructionSimplify.cpp @@ -3054,8 +3054,13 @@ if (Pred == FCmpInst::FCMP_TRUE) return ConstantInt::get(GetCompareTy(LHS), 1); - if (isa(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(LHS) || isa(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) { Index: lib/IR/ConstantFold.cpp =================================================================== --- lib/IR/ConstantFold.cpp +++ lib/IR/ConstantFold.cpp @@ -1327,7 +1327,7 @@ if (!isa(V1)) { if (!isa(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( ConstantExpr::getFCmp(FCmpInst::FCMP_OEQ, V1, V2)); @@ -1665,15 +1665,22 @@ // Handle some degenerate cases first if (isa(C1) || isa(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(C1) && isa(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 @@ -1789,7 +1796,10 @@ 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(C1) || isa(C2))) { int Result = -1; // -1 = unknown, 0 = known false, 1 = known true. switch (evaluateFCmpRelation(C1, C2)) { default: llvm_unreachable("Unknown relation!"); Index: test/Transforms/InstCombine/fcmp.ll =================================================================== --- test/Transforms/InstCombine/fcmp.ll +++ test/Transforms/InstCombine/fcmp.ll @@ -240,3 +240,38 @@ %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 +}