@@ -4060,6 +4060,19 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
4060
4060
if (Pred == FCmpInst::FCMP_TRUE)
4061
4061
return getTrue (RetTy);
4062
4062
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
+
4063
4076
// fcmp pred x, poison and fcmp pred poison, x
4064
4077
// fold to poison
4065
4078
if (isa<PoisonValue>(LHS) || isa<PoisonValue>(RHS))
@@ -4081,86 +4094,80 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
4081
4094
return getFalse (RetTy);
4082
4095
}
4083
4096
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
+ }
4108
4127
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 ) )
4120
4139
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 ))
4122
4143
return getTrue (RetTy);
4123
4144
}
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.
4131
4145
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
4136
4146
assert (!C->isNaN () && " Unexpected NaN constant!" );
4137
4147
// TODO: We can catch more cases by using a range check rather than
4138
4148
// relying on CannotBeOrderedLessThanZero.
4139
4149
switch (Pred) {
4140
4150
case FCmpInst::FCMP_UGE:
4141
4151
case FCmpInst::FCMP_UGT:
4142
- case FCmpInst::FCMP_UNE: {
4143
- KnownFPClass KnownClass = computeLHSClass (Interested);
4144
-
4152
+ case FCmpInst::FCMP_UNE:
4145
4153
// (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 ))
4147
4156
return getTrue (RetTy);
4148
4157
break ;
4149
- }
4150
4158
case FCmpInst::FCMP_OEQ:
4151
4159
case FCmpInst::FCMP_OLE:
4152
- case FCmpInst::FCMP_OLT: {
4153
- KnownFPClass KnownClass = computeLHSClass (Interested);
4154
-
4160
+ case FCmpInst::FCMP_OLT:
4155
4161
// (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 ))
4157
4164
return getFalse (RetTy);
4158
4165
break ;
4159
- }
4160
4166
default :
4161
4167
break ;
4162
4168
}
4163
4169
}
4170
+
4164
4171
// Check comparison of [minnum/maxnum with constant] with other constant.
4165
4172
const APFloat *C2;
4166
4173
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,
4207
4214
}
4208
4215
}
4209
4216
4210
- // TODO: Could fold this with above if there were a matcher which returned all
4211
- // classes in a non-splat vector.
4212
4217
if (match (RHS, m_AnyZeroFP ())) {
4213
4218
switch (Pred) {
4214
4219
case FCmpInst::FCMP_OGE:
4215
4220
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 );
4221
4224
4222
4225
// Positive or zero X >= 0.0 --> true
4223
4226
// Positive or zero X < 0.0 --> false
@@ -4227,16 +4230,12 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
4227
4230
break ;
4228
4231
}
4229
4232
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:
4234
4234
// Positive or zero or nan X >= 0.0 --> true
4235
4235
// 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 ))
4237
4237
return Pred == FCmpInst::FCMP_UGE ? getTrue (RetTy) : getFalse (RetTy);
4238
4238
break ;
4239
- }
4240
4239
default :
4241
4240
break ;
4242
4241
}
@@ -6817,9 +6816,6 @@ static Value *simplifyInstructionWithOperands(Instruction *I,
6817
6816
const SimplifyQuery &SQ,
6818
6817
unsigned MaxRecurse) {
6819
6818
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
-
6823
6819
const SimplifyQuery Q = SQ.CxtI ? SQ : SQ.getWithInstruction (I);
6824
6820
6825
6821
switch (I->getOpcode ()) {
0 commit comments