Skip to content

Commit 89f0314

Browse files
committed
Revert "InstSimplify: Use correct interested FP classes when simplifying fcmp"
Revert "InstSimplify: Add baseline tests for reported regression" Revert "InstSimplify: Start cleaning up simplifyFCmpInst" This reverts commit 0637b00. This reverts commit 239fb20. This reverts commit ddb3f12. These commits causes crashes when compiling chromium code, attached reduced ir at: https://reviews.llvm.org/D151887#4634914
1 parent 471004c commit 89f0314

File tree

8 files changed

+129
-235
lines changed

8 files changed

+129
-235
lines changed

llvm/include/llvm/Analysis/ValueTracking.h

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#include "llvm/ADT/SmallSet.h"
1919
#include "llvm/IR/Constants.h"
2020
#include "llvm/IR/DataLayout.h"
21-
#include "llvm/IR/FMF.h"
2221
#include "llvm/IR/InstrTypes.h"
2322
#include "llvm/IR/Intrinsics.h"
2423
#include <cassert>
@@ -230,10 +229,6 @@ std::pair<Value *, FPClassTest> fcmpToClassTest(CmpInst::Predicate Pred,
230229
const Function &F, Value *LHS,
231230
Value *RHS,
232231
bool LookThroughSrc = true);
233-
std::pair<Value *, FPClassTest> fcmpToClassTest(CmpInst::Predicate Pred,
234-
const Function &F, Value *LHS,
235-
const APFloat *ConstRHS,
236-
bool LookThroughSrc = true);
237232

238233
struct KnownFPClass {
239234
/// Floating-point classes the value could be one of.
@@ -476,28 +471,6 @@ KnownFPClass computeKnownFPClass(
476471
const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr,
477472
bool UseInstrInfo = true);
478473

479-
/// Wrapper to account for known fast math flags at the use instruction.
480-
inline KnownFPClass computeKnownFPClass(
481-
const Value *V, FastMathFlags FMF, const DataLayout &DL,
482-
FPClassTest InterestedClasses = fcAllFlags, unsigned Depth = 0,
483-
const TargetLibraryInfo *TLI = nullptr, AssumptionCache *AC = nullptr,
484-
const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr,
485-
bool UseInstrInfo = true) {
486-
if (FMF.noNaNs())
487-
InterestedClasses &= ~fcNan;
488-
if (FMF.noInfs())
489-
InterestedClasses &= ~fcInf;
490-
491-
KnownFPClass Result = computeKnownFPClass(V, DL, InterestedClasses, Depth,
492-
TLI, AC, CxtI, DT, UseInstrInfo);
493-
494-
if (FMF.noNaNs())
495-
Result.KnownFPClasses &= ~fcNan;
496-
if (FMF.noInfs())
497-
Result.KnownFPClasses &= ~fcInf;
498-
return Result;
499-
}
500-
501474
/// Return true if we can prove that the specified FP value is never equal to
502475
/// -0.0. Users should use caution when considering PreserveSign
503476
/// denormal-fp-math.

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 69 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -4060,6 +4060,19 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
40604060
if (Pred == FCmpInst::FCMP_TRUE)
40614061
return getTrue(RetTy);
40624062

4063+
// Fold (un)ordered comparison if we can determine there are no NaNs.
4064+
if (Pred == FCmpInst::FCMP_UNO || Pred == FCmpInst::FCMP_ORD)
4065+
if (FMF.noNaNs() ||
4066+
(isKnownNeverNaN(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT) &&
4067+
isKnownNeverNaN(RHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT)))
4068+
return ConstantInt::get(RetTy, Pred == FCmpInst::FCMP_ORD);
4069+
4070+
// NaN is unordered; NaN is not ordered.
4071+
assert((FCmpInst::isOrdered(Pred) || FCmpInst::isUnordered(Pred)) &&
4072+
"Comparison must be either ordered or unordered");
4073+
if (match(RHS, m_NaN()))
4074+
return ConstantInt::get(RetTy, CmpInst::isUnordered(Pred));
4075+
40634076
// fcmp pred x, poison and fcmp pred poison, x
40644077
// fold to poison
40654078
if (isa<PoisonValue>(LHS) || isa<PoisonValue>(RHS))
@@ -4081,86 +4094,80 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
40814094
return getFalse(RetTy);
40824095
}
40834096

4084-
// Fold (un)ordered comparison if we can determine there are no NaNs.
4085-
//
4086-
// This catches the 2 variable input case, constants are handled below as a
4087-
// class-like compare.
4088-
if (Pred == FCmpInst::FCMP_ORD || Pred == FCmpInst::FCMP_UNO) {
4089-
if (FMF.noNaNs() ||
4090-
(isKnownNeverNaN(RHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT) &&
4091-
isKnownNeverNaN(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT)))
4092-
return ConstantInt::get(RetTy, Pred == FCmpInst::FCMP_ORD);
4093-
}
4094-
4095-
const APFloat *C = nullptr;
4096-
match(RHS, m_APFloatAllowUndef(C));
4097-
std::optional<KnownFPClass> FullKnownClassLHS;
4098-
4099-
// Lazily compute the possible classes for LHS. Avoid computing it twice if
4100-
// RHS is a 0.
4101-
auto computeLHSClass = [=, &FullKnownClassLHS](FPClassTest InterestedFlags =
4102-
fcAllFlags) {
4103-
if (FullKnownClassLHS)
4104-
return *FullKnownClassLHS;
4105-
return computeKnownFPClass(LHS, FMF, Q.DL, InterestedFlags, 0, Q.TLI, Q.AC,
4106-
Q.CxtI, Q.DT, Q.IIQ.UseInstrInfo);
4107-
};
4097+
// Handle fcmp with constant RHS.
4098+
// TODO: Use match with a specific FP value, so these work with vectors with
4099+
// undef lanes.
4100+
const APFloat *C;
4101+
if (match(RHS, m_APFloat(C))) {
4102+
// Check whether the constant is an infinity.
4103+
if (C->isInfinity()) {
4104+
if (C->isNegative()) {
4105+
switch (Pred) {
4106+
case FCmpInst::FCMP_OLT:
4107+
// No value is ordered and less than negative infinity.
4108+
return getFalse(RetTy);
4109+
case FCmpInst::FCMP_UGE:
4110+
// All values are unordered with or at least negative infinity.
4111+
return getTrue(RetTy);
4112+
default:
4113+
break;
4114+
}
4115+
} else {
4116+
switch (Pred) {
4117+
case FCmpInst::FCMP_OGT:
4118+
// No value is ordered and greater than infinity.
4119+
return getFalse(RetTy);
4120+
case FCmpInst::FCMP_ULE:
4121+
// All values are unordered with and at most infinity.
4122+
return getTrue(RetTy);
4123+
default:
4124+
break;
4125+
}
4126+
}
41084127

4109-
if (C && Q.CxtI) {
4110-
// Fold out compares that express a class test.
4111-
//
4112-
// FIXME: Should be able to perform folds without context
4113-
// instruction. Always pass in the context function?
4114-
4115-
const Function *ParentF = Q.CxtI->getFunction();
4116-
auto [ClassVal, ClassTest] = fcmpToClassTest(Pred, *ParentF, LHS, C);
4117-
if (ClassVal) {
4118-
FullKnownClassLHS = computeLHSClass();
4119-
if ((FullKnownClassLHS->KnownFPClasses & ClassTest) == fcNone)
4128+
// LHS == Inf
4129+
if (Pred == FCmpInst::FCMP_OEQ &&
4130+
isKnownNeverInfinity(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT))
4131+
return getFalse(RetTy);
4132+
// LHS != Inf
4133+
if (Pred == FCmpInst::FCMP_UNE &&
4134+
isKnownNeverInfinity(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT))
4135+
return getTrue(RetTy);
4136+
// LHS == Inf || LHS == NaN
4137+
if (Pred == FCmpInst::FCMP_UEQ &&
4138+
isKnownNeverInfOrNaN(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT))
41204139
return getFalse(RetTy);
4121-
if ((FullKnownClassLHS->KnownFPClasses & ~ClassTest) == fcNone)
4140+
// LHS != Inf && LHS != NaN
4141+
if (Pred == FCmpInst::FCMP_ONE &&
4142+
isKnownNeverInfOrNaN(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT))
41224143
return getTrue(RetTy);
41234144
}
4124-
}
4125-
4126-
// Handle fcmp with constant RHS.
4127-
if (C) {
4128-
// TODO: Need version fcmpToClassTest which returns implied class when the
4129-
// compare isn't a complete class test. e.g. > 1.0 implies fcPositive, but
4130-
// isn't implementable as a class call.
41314145
if (C->isNegative() && !C->isNegZero()) {
4132-
FPClassTest Interested = KnownFPClass::OrderedLessThanZeroMask;
4133-
4134-
// FIXME: This assert won't always hold if we depend on the context
4135-
// instruction above
41364146
assert(!C->isNaN() && "Unexpected NaN constant!");
41374147
// TODO: We can catch more cases by using a range check rather than
41384148
// relying on CannotBeOrderedLessThanZero.
41394149
switch (Pred) {
41404150
case FCmpInst::FCMP_UGE:
41414151
case FCmpInst::FCMP_UGT:
4142-
case FCmpInst::FCMP_UNE: {
4143-
KnownFPClass KnownClass = computeLHSClass(Interested);
4144-
4152+
case FCmpInst::FCMP_UNE:
41454153
// (X >= 0) implies (X > C) when (C < 0)
4146-
if (KnownClass.cannotBeOrderedLessThanZero())
4154+
if (cannotBeOrderedLessThanZero(LHS, Q.DL, Q.TLI, 0,
4155+
Q.AC, Q.CxtI, Q.DT))
41474156
return getTrue(RetTy);
41484157
break;
4149-
}
41504158
case FCmpInst::FCMP_OEQ:
41514159
case FCmpInst::FCMP_OLE:
4152-
case FCmpInst::FCMP_OLT: {
4153-
KnownFPClass KnownClass = computeLHSClass(Interested);
4154-
4160+
case FCmpInst::FCMP_OLT:
41554161
// (X >= 0) implies !(X < C) when (C < 0)
4156-
if (KnownClass.cannotBeOrderedLessThanZero())
4162+
if (cannotBeOrderedLessThanZero(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI,
4163+
Q.DT))
41574164
return getFalse(RetTy);
41584165
break;
4159-
}
41604166
default:
41614167
break;
41624168
}
41634169
}
4170+
41644171
// Check comparison of [minnum/maxnum with constant] with other constant.
41654172
const APFloat *C2;
41664173
if ((match(LHS, m_Intrinsic<Intrinsic::minnum>(m_Value(), m_APFloat(C2))) &&
@@ -4207,17 +4214,13 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
42074214
}
42084215
}
42094216

4210-
// TODO: Could fold this with above if there were a matcher which returned all
4211-
// classes in a non-splat vector.
42124217
if (match(RHS, m_AnyZeroFP())) {
42134218
switch (Pred) {
42144219
case FCmpInst::FCMP_OGE:
42154220
case FCmpInst::FCMP_ULT: {
4216-
FPClassTest Interested = KnownFPClass::OrderedLessThanZeroMask;
4217-
if (!FMF.noNaNs())
4218-
Interested |= fcNan;
4219-
4220-
KnownFPClass Known = computeLHSClass(Interested);
4221+
FPClassTest Interested = FMF.noNaNs() ? fcNegative : fcNegative | fcNan;
4222+
KnownFPClass Known = computeKnownFPClass(LHS, Q.DL, Interested, 0,
4223+
Q.TLI, Q.AC, Q.CxtI, Q.DT);
42214224

42224225
// Positive or zero X >= 0.0 --> true
42234226
// Positive or zero X < 0.0 --> false
@@ -4227,16 +4230,12 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
42274230
break;
42284231
}
42294232
case FCmpInst::FCMP_UGE:
4230-
case FCmpInst::FCMP_OLT: {
4231-
FPClassTest Interested = KnownFPClass::OrderedLessThanZeroMask;
4232-
KnownFPClass Known = computeLHSClass(Interested);
4233-
4233+
case FCmpInst::FCMP_OLT:
42344234
// Positive or zero or nan X >= 0.0 --> true
42354235
// Positive or zero or nan X < 0.0 --> false
4236-
if (Known.cannotBeOrderedLessThanZero())
4236+
if (cannotBeOrderedLessThanZero(LHS, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT))
42374237
return Pred == FCmpInst::FCMP_UGE ? getTrue(RetTy) : getFalse(RetTy);
42384238
break;
4239-
}
42404239
default:
42414240
break;
42424241
}
@@ -6817,9 +6816,6 @@ static Value *simplifyInstructionWithOperands(Instruction *I,
68176816
const SimplifyQuery &SQ,
68186817
unsigned MaxRecurse) {
68196818
assert(I->getFunction() && "instruction should be inserted in a function");
6820-
assert((!SQ.CxtI || SQ.CxtI->getFunction() == I->getFunction()) &&
6821-
"context instruction should be in the same function");
6822-
68236819
const SimplifyQuery Q = SQ.CxtI ? SQ : SQ.getWithInstruction(I);
68246820

68256821
switch (I->getOpcode()) {

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4007,15 +4007,9 @@ std::pair<Value *, FPClassTest> llvm::fcmpToClassTest(FCmpInst::Predicate Pred,
40074007
Value *LHS, Value *RHS,
40084008
bool LookThroughSrc) {
40094009
const APFloat *ConstRHS;
4010-
if (!match(RHS, m_APFloatAllowUndef(ConstRHS)))
4010+
if (!match(RHS, m_APFloat(ConstRHS)))
40114011
return {nullptr, fcNone};
40124012

4013-
return fcmpToClassTest(Pred, F, LHS, ConstRHS, LookThroughSrc);
4014-
}
4015-
4016-
std::pair<Value *, FPClassTest>
4017-
llvm::fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS,
4018-
const APFloat *ConstRHS, bool LookThroughSrc) {
40194013
// fcmp ord x, zero|normal|subnormal|inf -> ~fcNan
40204014
if (Pred == FCmpInst::FCMP_ORD && !ConstRHS->isNaN())
40214015
return {LHS, ~fcNan};

llvm/test/Transforms/Attributor/nofpclass.ll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,8 @@ define half @assume_fcmp_fabs_with_other_fabs_assume_fallback(half %arg) {
600600
; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR16]]
601601
; CHECK-NEXT: [[UNRELATED_FABS:%.*]] = fcmp oeq half [[FABS]], 0xH0000
602602
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[UNRELATED_FABS]]) #[[ATTR16]]
603-
; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR16]]
603+
; CHECK-NEXT: [[IS_SUBNORMAL:%.*]] = fcmp olt half [[FABS]], 0xH0400
604+
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_SUBNORMAL]]) #[[ATTR16]]
604605
; CHECK-NEXT: call void @extern.use.f16(half nofpclass(nan inf norm) [[ARG]])
605606
; CHECK-NEXT: call void @extern.use.f16(half nofpclass(nan inf nzero sub norm) [[FABS]])
606607
; CHECK-NEXT: ret half [[ARG]]

llvm/test/Transforms/InstCombine/fcmp.ll

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,9 @@ define i1 @is_signbit_clear_nonzero(double %x) {
718718

719719
define i1 @is_signbit_set_simplify_zero(double %x) {
720720
; CHECK-LABEL: @is_signbit_set_simplify_zero(
721-
; CHECK-NEXT: ret i1 false
721+
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 0.000000e+00, double [[X:%.*]])
722+
; CHECK-NEXT: [[R:%.*]] = fcmp ogt double [[S]], 0.000000e+00
723+
; CHECK-NEXT: ret i1 [[R]]
722724
;
723725
%s = call double @llvm.copysign.f64(double 0.0, double %x)
724726
%r = fcmp ogt double %s, 0.0
@@ -729,7 +731,9 @@ define i1 @is_signbit_set_simplify_zero(double %x) {
729731

730732
define i1 @is_signbit_set_simplify_nan(double %x) {
731733
; CHECK-LABEL: @is_signbit_set_simplify_nan(
732-
; CHECK-NEXT: ret i1 false
734+
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 0xFFFFFFFFFFFFFFFF, double [[X:%.*]])
735+
; CHECK-NEXT: [[R:%.*]] = fcmp ogt double [[S]], 0.000000e+00
736+
; CHECK-NEXT: ret i1 [[R]]
733737
;
734738
%s = call double @llvm.copysign.f64(double 0xffffffffffffffff, double %x)
735739
%r = fcmp ogt double %s, 0.0

llvm/test/Transforms/InstCombine/is_fpclass.ll

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2444,7 +2444,8 @@ define <2 x i1> @test_class_fneg_fabs_posinf_negnormal_possubnormal_negzero_nan_
24442444

24452445
define i1 @test_class_is_zero_nozero_src(float nofpclass(zero) %arg) {
24462446
; CHECK-LABEL: @test_class_is_zero_nozero_src(
2447-
; CHECK-NEXT: ret i1 false
2447+
; CHECK-NEXT: [[CLASS:%.*]] = fcmp oeq float [[ARG:%.*]], 0.000000e+00
2448+
; CHECK-NEXT: ret i1 [[CLASS]]
24482449
;
24492450
%class = call i1 @llvm.is.fpclass.f32(float %arg, i32 96)
24502451
ret i1 %class
@@ -2577,7 +2578,8 @@ define i1 @test_class_is_neginf_or_nopinf_src(float nofpclass(pinf) %arg) {
25772578

25782579
define i1 @test_class_is_neginf_noninf_src(float nofpclass(ninf) %arg) {
25792580
; CHECK-LABEL: @test_class_is_neginf_noninf_src(
2580-
; CHECK-NEXT: ret i1 false
2581+
; CHECK-NEXT: [[CLASS:%.*]] = fcmp oeq float [[ARG:%.*]], 0xFFF0000000000000
2582+
; CHECK-NEXT: ret i1 [[CLASS]]
25812583
;
25822584
%class = call i1 @llvm.is.fpclass.f32(float %arg, i32 4)
25832585
ret i1 %class
@@ -2602,7 +2604,8 @@ define i1 @test_class_is_posinf_noninf_src(float nofpclass(ninf) %arg) {
26022604

26032605
define i1 @test_class_is_posinf_nopinf_src(float nofpclass(pinf) %arg) {
26042606
; CHECK-LABEL: @test_class_is_posinf_nopinf_src(
2605-
; CHECK-NEXT: ret i1 false
2607+
; CHECK-NEXT: [[CLASS:%.*]] = fcmp oeq float [[ARG:%.*]], 0x7FF0000000000000
2608+
; CHECK-NEXT: ret i1 [[CLASS]]
26062609
;
26072610
%class = call i1 @llvm.is.fpclass.f32(float %arg, i32 512)
26082611
ret i1 %class
@@ -2730,7 +2733,8 @@ define i1 @test_class_is_nan_assume_uno(float %x) {
27302733
; CHECK-LABEL: @test_class_is_nan_assume_uno(
27312734
; CHECK-NEXT: [[ORD:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
27322735
; CHECK-NEXT: call void @llvm.assume(i1 [[ORD]])
2733-
; CHECK-NEXT: ret i1 true
2736+
; CHECK-NEXT: [[CLASS:%.*]] = fcmp uno float [[X]], 0.000000e+00
2737+
; CHECK-NEXT: ret i1 [[CLASS]]
27342738
;
27352739
%ord = fcmp uno float %x, 0.0
27362740
call void @llvm.assume(i1 %ord)

0 commit comments

Comments
 (0)