[llvm] 294ad08 - Revert "Revert "InstSimplify: Use correct interested FP classes when simplifying fcmp""
Philip Reames via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 1 12:17:54 PDT 2023
Author: Philip Reames
Date: 2023-09-01T12:17:36-07:00
New Revision: 294ad08ecc0085e3ae93bbd16d488f284fe0d8fb
URL: https://github.com/llvm/llvm-project/commit/294ad08ecc0085e3ae93bbd16d488f284fe0d8fb
DIFF: https://github.com/llvm/llvm-project/commit/294ad08ecc0085e3ae93bbd16d488f284fe0d8fb.diff
LOG: Revert "Revert "InstSimplify: Use correct interested FP classes when simplifying fcmp""
This reverts commit 89f0314ee14a4d7f5a92fd63574ba545863df016. Change does not build.
Added:
Modified:
llvm/include/llvm/Analysis/ValueTracking.h
llvm/lib/Analysis/InstructionSimplify.cpp
llvm/lib/Analysis/ValueTracking.cpp
llvm/test/Transforms/Attributor/nofpclass.ll
llvm/test/Transforms/InstCombine/fcmp.ll
llvm/test/Transforms/InstCombine/is_fpclass.ll
llvm/test/Transforms/InstSimplify/floating-point-compare.ll
llvm/test/Transforms/InstSimplify/known-never-infinity.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 3521fa8be3b691d..695f2fecae885b7 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/SmallSet.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/FMF.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Intrinsics.h"
#include <cassert>
@@ -229,6 +230,10 @@ std::pair<Value *, FPClassTest> fcmpToClassTest(CmpInst::Predicate Pred,
const Function &F, Value *LHS,
Value *RHS,
bool LookThroughSrc = true);
+std::pair<Value *, FPClassTest> fcmpToClassTest(CmpInst::Predicate Pred,
+ const Function &F, Value *LHS,
+ const APFloat *ConstRHS,
+ bool LookThroughSrc = true);
struct KnownFPClass {
/// Floating-point classes the value could be one of.
@@ -471,6 +476,28 @@ KnownFPClass computeKnownFPClass(
const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr,
bool UseInstrInfo = true);
+/// Wrapper to account for known fast math flags at the use instruction.
+inline KnownFPClass computeKnownFPClass(
+ const Value *V, FastMathFlags FMF, const DataLayout &DL,
+ FPClassTest InterestedClasses = fcAllFlags, unsigned Depth = 0,
+ const TargetLibraryInfo *TLI = nullptr, AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr,
+ bool UseInstrInfo = true) {
+ if (FMF.noNaNs())
+ InterestedClasses &= ~fcNan;
+ if (FMF.noInfs())
+ InterestedClasses &= ~fcInf;
+
+ KnownFPClass Result = computeKnownFPClass(V, DL, InterestedClasses, Depth,
+ TLI, AC, CxtI, DT, UseInstrInfo);
+
+ if (FMF.noNaNs())
+ Result.KnownFPClasses &= ~fcNan;
+ if (FMF.noInfs())
+ Result.KnownFPClasses &= ~fcInf;
+ return Result;
+}
+
/// Return true if we can prove that the specified FP value is never equal to
/// -0.0. Users should use caution when considering PreserveSign
/// denormal-fp-math.
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 600418a5b7debf8..040c2e55d87ceda 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4060,19 +4060,6 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
if (Pred == FCmpInst::FCMP_TRUE)
return getTrue(RetTy);
- // Fold (un)ordered comparison if we can determine there are no NaNs.
- if (Pred == FCmpInst::FCMP_UNO || Pred == FCmpInst::FCMP_ORD)
- if (FMF.noNaNs() ||
- (isKnownNeverNaN(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT) &&
- isKnownNeverNaN(RHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT)))
- return ConstantInt::get(RetTy, Pred == FCmpInst::FCMP_ORD);
-
- // NaN is unordered; NaN is not ordered.
- assert((FCmpInst::isOrdered(Pred) || FCmpInst::isUnordered(Pred)) &&
- "Comparison must be either ordered or unordered");
- if (match(RHS, m_NaN()))
- return ConstantInt::get(RetTy, CmpInst::isUnordered(Pred));
-
// fcmp pred x, poison and fcmp pred poison, x
// fold to poison
if (isa<PoisonValue>(LHS) || isa<PoisonValue>(RHS))
@@ -4094,80 +4081,86 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
return getFalse(RetTy);
}
- // Handle fcmp with constant RHS.
- // TODO: Use match with a specific FP value, so these work with vectors with
- // undef lanes.
- const APFloat *C;
- if (match(RHS, m_APFloat(C))) {
- // Check whether the constant is an infinity.
- if (C->isInfinity()) {
- if (C->isNegative()) {
- switch (Pred) {
- case FCmpInst::FCMP_OLT:
- // No value is ordered and less than negative infinity.
- return getFalse(RetTy);
- case FCmpInst::FCMP_UGE:
- // All values are unordered with or at least negative infinity.
- return getTrue(RetTy);
- default:
- break;
- }
- } else {
- switch (Pred) {
- case FCmpInst::FCMP_OGT:
- // No value is ordered and greater than infinity.
- return getFalse(RetTy);
- case FCmpInst::FCMP_ULE:
- // All values are unordered with and at most infinity.
- return getTrue(RetTy);
- default:
- break;
- }
- }
+ // Fold (un)ordered comparison if we can determine there are no NaNs.
+ //
+ // This catches the 2 variable input case, constants are handled below as a
+ // class-like compare.
+ if (Pred == FCmpInst::FCMP_ORD || Pred == FCmpInst::FCMP_UNO) {
+ if (FMF.noNaNs() ||
+ (isKnownNeverNaN(RHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT) &&
+ isKnownNeverNaN(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT)))
+ return ConstantInt::get(RetTy, Pred == FCmpInst::FCMP_ORD);
+ }
- // LHS == Inf
- if (Pred == FCmpInst::FCMP_OEQ &&
- isKnownNeverInfinity(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT))
- return getFalse(RetTy);
- // LHS != Inf
- if (Pred == FCmpInst::FCMP_UNE &&
- isKnownNeverInfinity(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT))
- return getTrue(RetTy);
- // LHS == Inf || LHS == NaN
- if (Pred == FCmpInst::FCMP_UEQ &&
- isKnownNeverInfOrNaN(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT))
+ const APFloat *C = nullptr;
+ match(RHS, m_APFloatAllowUndef(C));
+ std::optional<KnownFPClass> FullKnownClassLHS;
+
+ // Lazily compute the possible classes for LHS. Avoid computing it twice if
+ // RHS is a 0.
+ auto computeLHSClass = [=, &FullKnownClassLHS](FPClassTest InterestedFlags =
+ fcAllFlags) {
+ if (FullKnownClassLHS)
+ return *FullKnownClassLHS;
+ return computeKnownFPClass(LHS, FMF, Q.DL, InterestedFlags, 0, Q.TLI, Q.AC,
+ Q.CxtI, Q.DT, Q.IIQ.UseInstrInfo);
+ };
+
+ if (C && Q.CxtI) {
+ // Fold out compares that express a class test.
+ //
+ // FIXME: Should be able to perform folds without context
+ // instruction. Always pass in the context function?
+
+ const Function *ParentF = Q.CxtI->getFunction();
+ auto [ClassVal, ClassTest] = fcmpToClassTest(Pred, *ParentF, LHS, C);
+ if (ClassVal) {
+ FullKnownClassLHS = computeLHSClass();
+ if ((FullKnownClassLHS->KnownFPClasses & ClassTest) == fcNone)
return getFalse(RetTy);
- // LHS != Inf && LHS != NaN
- if (Pred == FCmpInst::FCMP_ONE &&
- isKnownNeverInfOrNaN(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT))
+ if ((FullKnownClassLHS->KnownFPClasses & ~ClassTest) == fcNone)
return getTrue(RetTy);
}
+ }
+
+ // Handle fcmp with constant RHS.
+ if (C) {
+ // TODO: Need version fcmpToClassTest which returns implied class when the
+ // compare isn't a complete class test. e.g. > 1.0 implies fcPositive, but
+ // isn't implementable as a class call.
if (C->isNegative() && !C->isNegZero()) {
+ FPClassTest Interested = KnownFPClass::OrderedLessThanZeroMask;
+
+ // FIXME: This assert won't always hold if we depend on the context
+ // instruction above
assert(!C->isNaN() && "Unexpected NaN constant!");
// TODO: We can catch more cases by using a range check rather than
// relying on CannotBeOrderedLessThanZero.
switch (Pred) {
case FCmpInst::FCMP_UGE:
case FCmpInst::FCMP_UGT:
- case FCmpInst::FCMP_UNE:
+ case FCmpInst::FCMP_UNE: {
+ KnownFPClass KnownClass = computeLHSClass(Interested);
+
// (X >= 0) implies (X > C) when (C < 0)
- if (cannotBeOrderedLessThanZero(LHS, Q.DL, Q.TLI, 0,
- Q.AC, Q.CxtI, Q.DT))
+ if (KnownClass.cannotBeOrderedLessThanZero())
return getTrue(RetTy);
break;
+ }
case FCmpInst::FCMP_OEQ:
case FCmpInst::FCMP_OLE:
- case FCmpInst::FCMP_OLT:
+ case FCmpInst::FCMP_OLT: {
+ KnownFPClass KnownClass = computeLHSClass(Interested);
+
// (X >= 0) implies !(X < C) when (C < 0)
- if (cannotBeOrderedLessThanZero(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI,
- Q.DT))
+ if (KnownClass.cannotBeOrderedLessThanZero())
return getFalse(RetTy);
break;
+ }
default:
break;
}
}
-
// Check comparison of [minnum/maxnum with constant] with other constant.
const APFloat *C2;
if ((match(LHS, m_Intrinsic<Intrinsic::minnum>(m_Value(), m_APFloat(C2))) &&
@@ -4214,13 +4207,17 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
}
}
+ // TODO: Could fold this with above if there were a matcher which returned all
+ // classes in a non-splat vector.
if (match(RHS, m_AnyZeroFP())) {
switch (Pred) {
case FCmpInst::FCMP_OGE:
case FCmpInst::FCMP_ULT: {
- FPClassTest Interested = FMF.noNaNs() ? fcNegative : fcNegative | fcNan;
- KnownFPClass Known = computeKnownFPClass(LHS, Q.DL, Interested, 0,
- Q.TLI, Q.AC, Q.CxtI, Q.DT);
+ FPClassTest Interested = KnownFPClass::OrderedLessThanZeroMask;
+ if (!FMF.noNaNs())
+ Interested |= fcNan;
+
+ KnownFPClass Known = computeLHSClass(Interested);
// Positive or zero X >= 0.0 --> true
// Positive or zero X < 0.0 --> false
@@ -4230,12 +4227,16 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
break;
}
case FCmpInst::FCMP_UGE:
- case FCmpInst::FCMP_OLT:
+ case FCmpInst::FCMP_OLT: {
+ FPClassTest Interested = KnownFPClass::OrderedLessThanZeroMask;
+ KnownFPClass Known = computeLHSClass(Interested);
+
// Positive or zero or nan X >= 0.0 --> true
// Positive or zero or nan X < 0.0 --> false
- if (cannotBeOrderedLessThanZero(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT))
+ if (Known.cannotBeOrderedLessThanZero())
return Pred == FCmpInst::FCMP_UGE ? getTrue(RetTy) : getFalse(RetTy);
break;
+ }
default:
break;
}
@@ -6816,6 +6817,9 @@ static Value *simplifyInstructionWithOperands(Instruction *I,
const SimplifyQuery &SQ,
unsigned MaxRecurse) {
assert(I->getFunction() && "instruction should be inserted in a function");
+ assert((!SQ.CxtI || SQ.CxtI->getFunction() == I->getFunction()) &&
+ "context instruction should be in the same function");
+
const SimplifyQuery Q = SQ.CxtI ? SQ : SQ.getWithInstruction(I);
switch (I->getOpcode()) {
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 0c31dc22b871ef2..801814e0c18a837 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4007,9 +4007,15 @@ std::pair<Value *, FPClassTest> llvm::fcmpToClassTest(FCmpInst::Predicate Pred,
Value *LHS, Value *RHS,
bool LookThroughSrc) {
const APFloat *ConstRHS;
- if (!match(RHS, m_APFloat(ConstRHS)))
+ if (!match(RHS, m_APFloatAllowUndef(ConstRHS)))
return {nullptr, fcNone};
+ return fcmpToClassTest(Pred, F, LHS, ConstRHS, LookThroughSrc);
+}
+
+std::pair<Value *, FPClassTest>
+llvm::fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS,
+ const APFloat *ConstRHS, bool LookThroughSrc) {
// fcmp ord x, zero|normal|subnormal|inf -> ~fcNan
if (Pred == FCmpInst::FCMP_ORD && !ConstRHS->isNaN())
return {LHS, ~fcNan};
diff --git a/llvm/test/Transforms/Attributor/nofpclass.ll b/llvm/test/Transforms/Attributor/nofpclass.ll
index 2690bba123a3454..051ae8b8fe3d5ac 100644
--- a/llvm/test/Transforms/Attributor/nofpclass.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass.ll
@@ -600,8 +600,7 @@ define half @assume_fcmp_fabs_with_other_fabs_assume_fallback(half %arg) {
; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR16]]
; CHECK-NEXT: [[UNRELATED_FABS:%.*]] = fcmp oeq half [[FABS]], 0xH0000
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[UNRELATED_FABS]]) #[[ATTR16]]
-; CHECK-NEXT: [[IS_SUBNORMAL:%.*]] = fcmp olt half [[FABS]], 0xH0400
-; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_SUBNORMAL]]) #[[ATTR16]]
+; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR16]]
; CHECK-NEXT: call void @extern.use.f16(half nofpclass(nan inf norm) [[ARG]])
; CHECK-NEXT: call void @extern.use.f16(half nofpclass(nan inf nzero sub norm) [[FABS]])
; CHECK-NEXT: ret half [[ARG]]
diff --git a/llvm/test/Transforms/InstCombine/fcmp.ll b/llvm/test/Transforms/InstCombine/fcmp.ll
index 5c4380b14397dcb..159c84d0dd8aa91 100644
--- a/llvm/test/Transforms/InstCombine/fcmp.ll
+++ b/llvm/test/Transforms/InstCombine/fcmp.ll
@@ -718,9 +718,7 @@ define i1 @is_signbit_clear_nonzero(double %x) {
define i1 @is_signbit_set_simplify_zero(double %x) {
; CHECK-LABEL: @is_signbit_set_simplify_zero(
-; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 0.000000e+00, double [[X:%.*]])
-; CHECK-NEXT: [[R:%.*]] = fcmp ogt double [[S]], 0.000000e+00
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 false
;
%s = call double @llvm.copysign.f64(double 0.0, double %x)
%r = fcmp ogt double %s, 0.0
@@ -731,9 +729,7 @@ define i1 @is_signbit_set_simplify_zero(double %x) {
define i1 @is_signbit_set_simplify_nan(double %x) {
; CHECK-LABEL: @is_signbit_set_simplify_nan(
-; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 0xFFFFFFFFFFFFFFFF, double [[X:%.*]])
-; CHECK-NEXT: [[R:%.*]] = fcmp ogt double [[S]], 0.000000e+00
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 false
;
%s = call double @llvm.copysign.f64(double 0xffffffffffffffff, double %x)
%r = fcmp ogt double %s, 0.0
diff --git a/llvm/test/Transforms/InstCombine/is_fpclass.ll b/llvm/test/Transforms/InstCombine/is_fpclass.ll
index 2f399e7e23a6376..ad0bcd1b0c437cb 100644
--- a/llvm/test/Transforms/InstCombine/is_fpclass.ll
+++ b/llvm/test/Transforms/InstCombine/is_fpclass.ll
@@ -2444,8 +2444,7 @@ define <2 x i1> @test_class_fneg_fabs_posinf_negnormal_possubnormal_negzero_nan_
define i1 @test_class_is_zero_nozero_src(float nofpclass(zero) %arg) {
; CHECK-LABEL: @test_class_is_zero_nozero_src(
-; CHECK-NEXT: [[CLASS:%.*]] = fcmp oeq float [[ARG:%.*]], 0.000000e+00
-; CHECK-NEXT: ret i1 [[CLASS]]
+; CHECK-NEXT: ret i1 false
;
%class = call i1 @llvm.is.fpclass.f32(float %arg, i32 96)
ret i1 %class
@@ -2578,8 +2577,7 @@ define i1 @test_class_is_neginf_or_nopinf_src(float nofpclass(pinf) %arg) {
define i1 @test_class_is_neginf_noninf_src(float nofpclass(ninf) %arg) {
; CHECK-LABEL: @test_class_is_neginf_noninf_src(
-; CHECK-NEXT: [[CLASS:%.*]] = fcmp oeq float [[ARG:%.*]], 0xFFF0000000000000
-; CHECK-NEXT: ret i1 [[CLASS]]
+; CHECK-NEXT: ret i1 false
;
%class = call i1 @llvm.is.fpclass.f32(float %arg, i32 4)
ret i1 %class
@@ -2604,8 +2602,7 @@ define i1 @test_class_is_posinf_noninf_src(float nofpclass(ninf) %arg) {
define i1 @test_class_is_posinf_nopinf_src(float nofpclass(pinf) %arg) {
; CHECK-LABEL: @test_class_is_posinf_nopinf_src(
-; CHECK-NEXT: [[CLASS:%.*]] = fcmp oeq float [[ARG:%.*]], 0x7FF0000000000000
-; CHECK-NEXT: ret i1 [[CLASS]]
+; CHECK-NEXT: ret i1 false
;
%class = call i1 @llvm.is.fpclass.f32(float %arg, i32 512)
ret i1 %class
@@ -2733,8 +2730,7 @@ define i1 @test_class_is_nan_assume_uno(float %x) {
; CHECK-LABEL: @test_class_is_nan_assume_uno(
; CHECK-NEXT: [[ORD:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: call void @llvm.assume(i1 [[ORD]])
-; CHECK-NEXT: [[CLASS:%.*]] = fcmp uno float [[X]], 0.000000e+00
-; CHECK-NEXT: ret i1 [[CLASS]]
+; CHECK-NEXT: ret i1 true
;
%ord = fcmp uno float %x, 0.0
call void @llvm.assume(i1 %ord)
diff --git a/llvm/test/Transforms/InstSimplify/floating-point-compare.ll b/llvm/test/Transforms/InstSimplify/floating-point-compare.ll
index a88057e4d4d93ed..62dd37d9b74e62c 100644
--- a/llvm/test/Transforms/InstSimplify/floating-point-compare.ll
+++ b/llvm/test/Transforms/InstSimplify/floating-point-compare.ll
@@ -656,8 +656,7 @@ define i1 @assume_nan_ord(float %x) {
; CHECK-LABEL: @assume_nan_ord(
; CHECK-NEXT: [[UNO:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: call void @llvm.assume(i1 [[UNO]])
-; CHECK-NEXT: [[CMP:%.*]] = fcmp ord float [[X]], 1.000000e+00
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 false
;
%uno = fcmp uno float %x, 0.0
call void @llvm.assume(i1 %uno)
@@ -681,8 +680,7 @@ define i1 @assume_nan_uno(float %x) {
; CHECK-LABEL: @assume_nan_uno(
; CHECK-NEXT: [[UNO:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: call void @llvm.assume(i1 [[UNO]])
-; CHECK-NEXT: [[CMP:%.*]] = fcmp uno float [[X]], 1.000000e+00
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 true
;
%uno = fcmp uno float %x, 0.0
call void @llvm.assume(i1 %uno)
@@ -1525,10 +1523,7 @@ define i1 @fcmp_olt_0_assumed_oge_zero(float %x) {
define i1 @ogt_zero_fabs_select_negone_or_pinf(i1 %cond) {
; CHECK-LABEL: @ogt_zero_fabs_select_negone_or_pinf(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND:%.*]], float -1.000000e+00, float 0x7FF0000000000000
-; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
-; CHECK-NEXT: [[ONE:%.*]] = fcmp ogt float [[FABS]], 0.000000e+00
-; CHECK-NEXT: ret i1 [[ONE]]
+; CHECK-NEXT: ret i1 true
;
entry:
%select = select i1 %cond, float -1.0, float 0x7FF0000000000000
@@ -1540,10 +1535,7 @@ entry:
define i1 @ogt_zero_fabs_select_one_or_ninf(i1 %cond) {
; CHECK-LABEL: @ogt_zero_fabs_select_one_or_ninf(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND:%.*]], float 1.000000e+00, float 0xFFF0000000000000
-; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
-; CHECK-NEXT: [[ONE:%.*]] = fcmp ogt float [[FABS]], 0.000000e+00
-; CHECK-NEXT: ret i1 [[ONE]]
+; CHECK-NEXT: ret i1 true
;
entry:
%select = select i1 %cond, float 1.0, float 0xFFF0000000000000
@@ -1552,6 +1544,114 @@ entry:
ret i1 %one
}
+; Make sure we recognize fcmp < 0 is recognized as impossible here when simplifying the fcmp
+define float @fast_square_must_be_positive_ieee(float %arg, float %arg1) {
+; CHECK-LABEL: @fast_square_must_be_positive_ieee(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: [[I:%.*]] = fmul float [[ARG:%.*]], [[ARG]]
+; CHECK-NEXT: [[I2:%.*]] = fmul float [[ARG1:%.*]], [[ARG1]]
+; CHECK-NEXT: [[I3:%.*]] = fadd float [[I2]], [[I]]
+; CHECK-NEXT: ret float [[I3]]
+;
+bb:
+ %i = fmul float %arg, %arg
+ %i2 = fmul float %arg1, %arg1
+ %i3 = fadd float %i2, %i
+ %i4 = fcmp olt float %i3, 0.000000e+00
+ %i5 = select i1 %i4, float 0.000000e+00, float %i3
+ ret float %i5
+}
+
+; Make sure we recognize fcmp < 0 is recognized as impossible here when simplifying the fcmp
+define float @fast_square_must_be_positive_ieee_nnan(float %arg, float %arg1) {
+; CHECK-LABEL: @fast_square_must_be_positive_ieee_nnan(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: [[I:%.*]] = fmul float [[ARG:%.*]], [[ARG]]
+; CHECK-NEXT: [[I2:%.*]] = fmul float [[ARG1:%.*]], [[ARG1]]
+; CHECK-NEXT: [[I3:%.*]] = fadd float [[I2]], [[I]]
+; CHECK-NEXT: ret float [[I3]]
+;
+bb:
+ %i = fmul float %arg, %arg
+ %i2 = fmul float %arg1, %arg1
+ %i3 = fadd float %i2, %i
+ %i4 = fcmp nnan olt float %i3, 0.000000e+00
+ %i5 = select i1 %i4, float 0.000000e+00, float %i3
+ ret float %i5
+}
+
+; Make sure we recognize fcmp < 0 is recognized as impossible here when simplifying the fcmp
+define float @fast_square_must_be_positive_daz(float %arg, float %arg1) #0 {
+; CHECK-LABEL: @fast_square_must_be_positive_daz(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: [[I:%.*]] = fmul float [[ARG:%.*]], [[ARG]]
+; CHECK-NEXT: [[I2:%.*]] = fmul float [[ARG1:%.*]], [[ARG1]]
+; CHECK-NEXT: [[I3:%.*]] = fadd float [[I2]], [[I]]
+; CHECK-NEXT: ret float [[I3]]
+;
+bb:
+ %i = fmul float %arg, %arg
+ %i2 = fmul float %arg1, %arg1
+ %i3 = fadd float %i2, %i
+ %i4 = fcmp olt float %i3, 0.000000e+00
+ %i5 = select i1 %i4, float 0.000000e+00, float %i3
+ ret float %i5
+}
+
+; Make sure we recognize fcmp < 0 is recognized as impossible here when simplifying the fcmp
+define float @fast_square_must_be_positive_daz_nnan(float %arg, float %arg1) #0 {
+; CHECK-LABEL: @fast_square_must_be_positive_daz_nnan(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: [[I:%.*]] = fmul float [[ARG:%.*]], [[ARG]]
+; CHECK-NEXT: [[I2:%.*]] = fmul float [[ARG1:%.*]], [[ARG1]]
+; CHECK-NEXT: [[I3:%.*]] = fadd float [[I2]], [[I]]
+; CHECK-NEXT: ret float [[I3]]
+;
+bb:
+ %i = fmul float %arg, %arg
+ %i2 = fmul float %arg1, %arg1
+ %i3 = fadd float %i2, %i
+ %i4 = fcmp nnan olt float %i3, 0.000000e+00
+ %i5 = select i1 %i4, float 0.000000e+00, float %i3
+ ret float %i5
+}
+
+; Make the compare to negative constant is folded out
+define float @must_be_olt_negative_constant_daz(float %arg, float %arg1) #0 {
+; CHECK-LABEL: @must_be_olt_negative_constant_daz(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: [[I:%.*]] = fmul float [[ARG:%.*]], [[ARG]]
+; CHECK-NEXT: [[I2:%.*]] = fmul float [[ARG1:%.*]], [[ARG1]]
+; CHECK-NEXT: [[I3:%.*]] = fadd float [[I2]], [[I]]
+; CHECK-NEXT: ret float [[I3]]
+;
+bb:
+ %i = fmul float %arg, %arg
+ %i2 = fmul float %arg1, %arg1
+ %i3 = fadd float %i2, %i
+ %i4 = fcmp olt float %i3, -1.0
+ %i5 = select i1 %i4, float 0.000000e+00, float %i3
+ ret float %i5
+}
+
+; Make the compare to negative constant is folded out
+define float @must_be_olt_negative_constant_daz_nnan(float %arg, float %arg1) #0 {
+; CHECK-LABEL: @must_be_olt_negative_constant_daz_nnan(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: [[I:%.*]] = fmul float [[ARG:%.*]], [[ARG]]
+; CHECK-NEXT: [[I2:%.*]] = fmul float [[ARG1:%.*]], [[ARG1]]
+; CHECK-NEXT: [[I3:%.*]] = fadd float [[I2]], [[I]]
+; CHECK-NEXT: ret float [[I3]]
+;
+bb:
+ %i = fmul float %arg, %arg
+ %i2 = fmul float %arg1, %arg1
+ %i3 = fadd float %i2, %i
+ %i4 = fcmp nnan olt float %i3, -1.0
+ %i5 = select i1 %i4, float 0.000000e+00, float %i3
+ ret float %i5
+}
+
declare <2 x double> @llvm.fabs.v2f64(<2 x double>)
declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
declare <2 x float> @llvm.maxnum.v2f32(<2 x float>, <2 x float>)
@@ -1571,3 +1671,5 @@ declare double @llvm.sqrt.f64(double)
declare double @llvm.copysign.f64(double, double)
declare half @llvm.fabs.f16(half)
declare void @llvm.assume(i1 noundef)
+
+attributes #0 = { "denormal-fp-math"="preserve-sign,preserve-sign" }
diff --git a/llvm/test/Transforms/InstSimplify/known-never-infinity.ll b/llvm/test/Transforms/InstSimplify/known-never-infinity.ll
index a7b7e0b4b1fa6c9..efa19aa0999a7a3 100644
--- a/llvm/test/Transforms/InstSimplify/known-never-infinity.ll
+++ b/llvm/test/Transforms/InstSimplify/known-never-infinity.ll
@@ -753,11 +753,7 @@ define i1 @isKnownNeverInfinity_cos(double %x) {
define i1 @isKnownNeverInfinity_log(double %x) {
; CHECK-LABEL: define i1 @isKnownNeverInfinity_log
; CHECK-SAME: (double [[X:%.*]]) {
-; CHECK-NEXT: [[X_CLAMP_ZERO:%.*]] = call double @llvm.maxnum.f64(double [[X]], double 0.000000e+00)
-; CHECK-NEXT: [[A:%.*]] = fadd ninf double [[X_CLAMP_ZERO]], 1.000000e+00
-; CHECK-NEXT: [[E:%.*]] = call double @llvm.log.f64(double [[A]])
-; CHECK-NEXT: [[R:%.*]] = fcmp une double [[E]], 0x7FF0000000000000
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 true
;
%x.clamp.zero = call double @llvm.maxnum.f64(double %x, double 0.0)
%a = fadd ninf double %x.clamp.zero, 1.0
@@ -769,10 +765,7 @@ define i1 @isKnownNeverInfinity_log(double %x) {
define i1 @isNotKnownNeverInfinity_log_maybe_negative(double %x) {
; CHECK-LABEL: define i1 @isNotKnownNeverInfinity_log_maybe_negative
; CHECK-SAME: (double [[X:%.*]]) {
-; CHECK-NEXT: [[X_NOT_INF:%.*]] = fadd ninf double [[X]], 1.000000e+00
-; CHECK-NEXT: [[E:%.*]] = call double @llvm.log.f64(double [[X_NOT_INF]])
-; CHECK-NEXT: [[R:%.*]] = fcmp une double [[E]], 0x7FF0000000000000
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 true
;
%x.not.inf = fadd ninf double %x, 1.0
@@ -812,11 +805,7 @@ define i1 @isKnownNeverNegInfinity_log_maybe_0(double %x) {
define i1 @isKnownNeverInfinity_log10(double %x) {
; CHECK-LABEL: define i1 @isKnownNeverInfinity_log10
; CHECK-SAME: (double [[X:%.*]]) {
-; CHECK-NEXT: [[X_CLAMP_ZERO:%.*]] = call double @llvm.maxnum.f64(double [[X]], double 0.000000e+00)
-; CHECK-NEXT: [[A:%.*]] = fadd ninf double [[X_CLAMP_ZERO]], 1.000000e+00
-; CHECK-NEXT: [[E:%.*]] = call double @llvm.log10.f64(double [[A]])
-; CHECK-NEXT: [[R:%.*]] = fcmp une double [[E]], 0x7FF0000000000000
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 true
;
%x.clamp.zero = call double @llvm.maxnum.f64(double %x, double 0.0)
%a = fadd ninf double %x.clamp.zero, 1.0
@@ -828,10 +817,7 @@ define i1 @isKnownNeverInfinity_log10(double %x) {
define i1 @isNotKnownNeverInfinity_log10_maybe_negative(double %x) {
; CHECK-LABEL: define i1 @isNotKnownNeverInfinity_log10_maybe_negative
; CHECK-SAME: (double [[X:%.*]]) {
-; CHECK-NEXT: [[X_NOT_INF:%.*]] = fadd ninf double [[X]], 1.000000e+00
-; CHECK-NEXT: [[E:%.*]] = call double @llvm.log10.f64(double [[X_NOT_INF]])
-; CHECK-NEXT: [[R:%.*]] = fcmp une double [[E]], 0x7FF0000000000000
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 true
;
%x.not.inf = fadd ninf double %x, 1.0
@@ -871,11 +857,7 @@ define i1 @isKnownNeverNegInfinity_log10_maybe_0(double %x) {
define i1 @isKnownNeverInfinity_log2(double %x) {
; CHECK-LABEL: define i1 @isKnownNeverInfinity_log2
; CHECK-SAME: (double [[X:%.*]]) {
-; CHECK-NEXT: [[X_CLAMP_ZERO:%.*]] = call double @llvm.maxnum.f64(double [[X]], double 0.000000e+00)
-; CHECK-NEXT: [[A:%.*]] = fadd ninf double [[X_CLAMP_ZERO]], 1.000000e+00
-; CHECK-NEXT: [[E:%.*]] = call double @llvm.log2.f64(double [[A]])
-; CHECK-NEXT: [[R:%.*]] = fcmp une double [[E]], 0x7FF0000000000000
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 true
;
%x.clamp.zero = call double @llvm.maxnum.f64(double %x, double 0.0)
%a = fadd ninf double %x.clamp.zero, 1.0
@@ -887,10 +869,7 @@ define i1 @isKnownNeverInfinity_log2(double %x) {
define i1 @isNotKnownNeverInfinity_log2_maybe_negative(double %x) {
; CHECK-LABEL: define i1 @isNotKnownNeverInfinity_log2_maybe_negative
; CHECK-SAME: (double [[X:%.*]]) {
-; CHECK-NEXT: [[X_NOT_INF:%.*]] = fadd ninf double [[X]], 1.000000e+00
-; CHECK-NEXT: [[E:%.*]] = call double @llvm.log2.f64(double [[X_NOT_INF]])
-; CHECK-NEXT: [[R:%.*]] = fcmp une double [[E]], 0x7FF0000000000000
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 true
;
%x.not.inf = fadd ninf double %x, 1.0
@@ -1057,10 +1036,7 @@ define i1 @not_ninf_fabs_select_nzero_or_pinf(i1 %cond) {
; CHECK-LABEL: define i1 @not_ninf_fabs_select_nzero_or_pinf
; CHECK-SAME: (i1 [[COND:%.*]]) {
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float -0.000000e+00, float 0x7FF0000000000000
-; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
-; CHECK-NEXT: [[ONE:%.*]] = fcmp one float [[FABS]], 0xFFF0000000000000
-; CHECK-NEXT: ret i1 [[ONE]]
+; CHECK-NEXT: ret i1 true
;
entry:
%select = select i1 %cond, float -0.000000e+00, float 0x7FF0000000000000
More information about the llvm-commits
mailing list