mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
InstCombine: fix fold "fcmp x, undef" to account for NaN
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> llvm-svn: 231626
This commit is contained in:
parent
112fafc026
commit
201b59d62e
@ -1201,11 +1201,15 @@ public:
|
||||
|
||||
/// @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 {
|
||||
|
@ -3054,8 +3054,13 @@ static Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
|
||||
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) {
|
||||
|
@ -1327,7 +1327,7 @@ static FCmpInst::Predicate evaluateFCmpRelation(Constant *V1, Constant *V2) {
|
||||
|
||||
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));
|
||||
@ -1665,15 +1665,22 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred,
|
||||
|
||||
// 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
|
||||
@ -1789,7 +1796,10 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred,
|
||||
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!");
|
||||
|
@ -240,3 +240,38 @@ define i32 @test17(double %a, double (double)* %p) nounwind {
|
||||
%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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user