Skip to content

Commit 8e9d50c

Browse files
authored
[InstSimplify] fold uno/ord comparison if fpclass is always NaN (#97763)
In InstSimplify we already fold `fcmp ord/uno` to a constant when both operands are known to be non-NaN. This change slightly generalizes this to also handle the case where either of the operands is known to always be NaN. Proof: https://alive2.llvm.org/ce/z/AhCmJN
1 parent ce03155 commit 8e9d50c

File tree

4 files changed

+48
-5
lines changed

4 files changed

+48
-5
lines changed

llvm/include/llvm/Analysis/ValueTracking.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,8 @@ struct KnownFPClass {
276276
return (KnownFPClasses & Mask) == fcNone;
277277
}
278278

279+
bool isKnownAlways(FPClassTest Mask) const { return isKnownNever(~Mask); }
280+
279281
bool isUnknown() const {
280282
return KnownFPClasses == fcAllFlags && !SignBit;
281283
}
@@ -285,6 +287,9 @@ struct KnownFPClass {
285287
return isKnownNever(fcNan);
286288
}
287289

290+
/// Return true if it's known this must always be a nan.
291+
bool isKnownAlwaysNaN() const { return isKnownAlways(fcNan); }
292+
288293
/// Return true if it's known this can never be an infinity.
289294
bool isKnownNeverInfinity() const {
290295
return isKnownNever(fcInf);

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4117,9 +4117,17 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
41174117
// This catches the 2 variable input case, constants are handled below as a
41184118
// class-like compare.
41194119
if (Pred == FCmpInst::FCMP_ORD || Pred == FCmpInst::FCMP_UNO) {
4120-
if (FMF.noNaNs() || (isKnownNeverNaN(RHS, /*Depth=*/0, Q) &&
4121-
isKnownNeverNaN(LHS, /*Depth=*/0, Q)))
4120+
KnownFPClass RHSClass =
4121+
computeKnownFPClass(RHS, fcAllFlags, /*Depth=*/0, Q);
4122+
KnownFPClass LHSClass =
4123+
computeKnownFPClass(LHS, fcAllFlags, /*Depth=*/0, Q);
4124+
4125+
if (FMF.noNaNs() ||
4126+
(RHSClass.isKnownNeverNaN() && LHSClass.isKnownNeverNaN()))
41224127
return ConstantInt::get(RetTy, Pred == FCmpInst::FCMP_ORD);
4128+
4129+
if (RHSClass.isKnownAlwaysNaN() || LHSClass.isKnownAlwaysNaN())
4130+
return ConstantInt::get(RetTy, Pred == CmpInst::FCMP_UNO);
41234131
}
41244132

41254133
const APFloat *C = nullptr;

llvm/test/Transforms/InstSimplify/floating-point-compare.ll

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,38 @@ define i1 @assume_nonnan_x2_ord(float %x, float %y) {
672672
ret i1 %cmp
673673
}
674674

675+
define i1 @assume_nan_x2_uno(float %x, float %y) {
676+
; CHECK-LABEL: @assume_nan_x2_uno(
677+
; CHECK-NEXT: [[UNO_X:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
678+
; CHECK-NEXT: call void @llvm.assume(i1 [[UNO_X]])
679+
; CHECK-NEXT: [[UNO_Y:%.*]] = fcmp uno float [[Y:%.*]], 0.000000e+00
680+
; CHECK-NEXT: call void @llvm.assume(i1 [[UNO_Y]])
681+
; CHECK-NEXT: ret i1 true
682+
;
683+
%uno.x = fcmp uno float %x, 0.0
684+
call void @llvm.assume(i1 %uno.x)
685+
%uno.y = fcmp uno float %y, 0.0
686+
call void @llvm.assume(i1 %uno.y)
687+
%cmp = fcmp uno float %x, %y
688+
ret i1 %cmp
689+
}
690+
691+
define i1 @assume_nan_x2_ord(float %x, float %y) {
692+
; CHECK-LABEL: @assume_nan_x2_ord(
693+
; CHECK-NEXT: [[UNO_X:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
694+
; CHECK-NEXT: call void @llvm.assume(i1 [[UNO_X]])
695+
; CHECK-NEXT: [[UNO_Y:%.*]] = fcmp uno float [[Y:%.*]], 0.000000e+00
696+
; CHECK-NEXT: call void @llvm.assume(i1 [[UNO_Y]])
697+
; CHECK-NEXT: ret i1 false
698+
;
699+
%uno.x = fcmp uno float %x, 0.0
700+
call void @llvm.assume(i1 %uno.x)
701+
%uno.y = fcmp uno float %y, 0.0
702+
call void @llvm.assume(i1 %uno.y)
703+
%cmp = fcmp ord float %x, %y
704+
ret i1 %cmp
705+
}
706+
675707
define i1 @assume_nonan_x2_uno(float %x, float %y) {
676708
; CHECK-LABEL: @assume_nonan_x2_uno(
677709
; CHECK-NEXT: [[ORD_X:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00

llvm/test/Transforms/InstSimplify/known-never-nan.ll

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -512,12 +512,10 @@ define i1 @isKnownNeverNaN_nofpclass_callsite() {
512512

513513
declare nofpclass(sub norm zero inf) double @only_nans()
514514

515-
; TODO: Could simplify to false
516515
define i1 @isKnownNeverNaN_only_nans() {
517516
; CHECK-LABEL: @isKnownNeverNaN_only_nans(
518517
; CHECK-NEXT: [[CALL:%.*]] = call double @only_nans()
519-
; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[CALL]], [[CALL]]
520-
; CHECK-NEXT: ret i1 [[TMP]]
518+
; CHECK-NEXT: ret i1 false
521519
;
522520
%call = call double @only_nans()
523521
%tmp = fcmp ord double %call, %call

0 commit comments

Comments
 (0)