[llvm] [InstSimplify] fold uno/ord comparison if fpclass is always NaN (PR #97763)

Alex MacLean via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 8 09:07:25 PDT 2024


https://github.com/AlexMaclean updated https://github.com/llvm/llvm-project/pull/97763

>From a881a30129d63e464f26fe4e869ce3d5f18a6a4e Mon Sep 17 00:00:00 2001
From: Alex MacLean <amaclean at nvidia.com>
Date: Sat, 6 Jul 2024 16:44:31 +0000
Subject: [PATCH 1/3] pre-commit tests

---
 .../InstSimplify/floating-point-compare.ll    | 34 +++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/llvm/test/Transforms/InstSimplify/floating-point-compare.ll b/llvm/test/Transforms/InstSimplify/floating-point-compare.ll
index 70f0321039ea94..9696905b55779b 100644
--- a/llvm/test/Transforms/InstSimplify/floating-point-compare.ll
+++ b/llvm/test/Transforms/InstSimplify/floating-point-compare.ll
@@ -672,6 +672,40 @@ define i1 @assume_nonnan_x2_ord(float %x, float %y) {
   ret i1 %cmp
 }
 
+define i1 @assume_nan_x2_uno(float %x, float %y) {
+; CHECK-LABEL: @assume_nan_x2_uno(
+; CHECK-NEXT:    [[UNO_X:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT:    call void @llvm.assume(i1 [[UNO_X]])
+; CHECK-NEXT:    [[UNO_Y:%.*]] = fcmp uno float [[Y:%.*]], 0.000000e+00
+; CHECK-NEXT:    call void @llvm.assume(i1 [[UNO_Y]])
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp uno float [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %uno.x = fcmp uno float %x, 0.0
+  call void @llvm.assume(i1 %uno.x)
+  %uno.y = fcmp uno float %y, 0.0
+  call void @llvm.assume(i1 %uno.y)
+  %cmp = fcmp uno float %x, %y
+  ret i1 %cmp
+}
+
+define i1 @assume_nan_x2_ord(float %x, float %y) {
+; CHECK-LABEL: @assume_nan_x2_ord(
+; CHECK-NEXT:    [[UNO_X:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT:    call void @llvm.assume(i1 [[UNO_X]])
+; CHECK-NEXT:    [[UNO_Y:%.*]] = fcmp uno float [[Y:%.*]], 0.000000e+00
+; CHECK-NEXT:    call void @llvm.assume(i1 [[UNO_Y]])
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ord float [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %uno.x = fcmp uno float %x, 0.0
+  call void @llvm.assume(i1 %uno.x)
+  %uno.y = fcmp uno float %y, 0.0
+  call void @llvm.assume(i1 %uno.y)
+  %cmp = fcmp ord float %x, %y
+  ret i1 %cmp
+}
+
 define i1 @assume_nonan_x2_uno(float %x, float %y) {
 ; CHECK-LABEL: @assume_nonan_x2_uno(
 ; CHECK-NEXT:    [[ORD_X:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00

>From b54f92fdf0cc40cf68c86f647ef3ba9987078012 Mon Sep 17 00:00:00 2001
From: Alex MacLean <amaclean at nvidia.com>
Date: Sat, 6 Jul 2024 16:49:35 +0000
Subject: [PATCH 2/3] [InstSimplify] fold uno/ord comparison if fpclass is
 always NaN

---
 llvm/include/llvm/Analysis/ValueTracking.h               | 5 +++++
 llvm/lib/Analysis/InstructionSimplify.cpp                | 9 +++++++--
 .../Transforms/InstSimplify/floating-point-compare.ll    | 6 ++----
 llvm/test/Transforms/InstSimplify/known-never-nan.ll     | 4 +---
 4 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index a67ad501982d22..51db54aa9b61d5 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -276,6 +276,8 @@ struct KnownFPClass {
     return (KnownFPClasses & Mask) == fcNone;
   }
 
+  bool isKnownAlways(FPClassTest Mask) const { return isKnownNever(~Mask); }
+
   bool isUnknown() const {
     return KnownFPClasses == fcAllFlags && !SignBit;
   }
@@ -285,6 +287,9 @@ struct KnownFPClass {
     return isKnownNever(fcNan);
   }
 
+  /// Return true if it's known this must always be a nan.
+  bool isKnownAlwaysNaN() const { return isKnownAlways(fcNan); }
+
   /// Return true if it's known this can never be an infinity.
   bool isKnownNeverInfinity() const {
     return isKnownNever(fcInf);
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 1b72f151e3692a..78da7e02fd8ce9 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4117,9 +4117,14 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
   // 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, /*Depth=*/0, Q) &&
-                         isKnownNeverNaN(LHS, /*Depth=*/0, Q)))
+    KnownFPClass RHSClass = computeKnownFPClass(RHS, fcAllFlags, 0, Q);
+    KnownFPClass LHSClass = computeKnownFPClass(LHS, fcAllFlags, 0, Q);
+    if (FMF.noNaNs() ||
+        (RHSClass.isKnownNeverNaN() && LHSClass.isKnownNeverNaN()))
       return ConstantInt::get(RetTy, Pred == FCmpInst::FCMP_ORD);
+
+    if (RHSClass.isKnownAlwaysNaN() || LHSClass.isKnownAlwaysNaN())
+      return ConstantInt::get(RetTy, Pred == CmpInst::FCMP_UNO);
   }
 
   const APFloat *C = nullptr;
diff --git a/llvm/test/Transforms/InstSimplify/floating-point-compare.ll b/llvm/test/Transforms/InstSimplify/floating-point-compare.ll
index 9696905b55779b..e9d5c353cbccfc 100644
--- a/llvm/test/Transforms/InstSimplify/floating-point-compare.ll
+++ b/llvm/test/Transforms/InstSimplify/floating-point-compare.ll
@@ -678,8 +678,7 @@ define i1 @assume_nan_x2_uno(float %x, float %y) {
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[UNO_X]])
 ; CHECK-NEXT:    [[UNO_Y:%.*]] = fcmp uno float [[Y:%.*]], 0.000000e+00
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[UNO_Y]])
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp uno float [[X]], [[Y]]
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 true
 ;
   %uno.x = fcmp uno float %x, 0.0
   call void @llvm.assume(i1 %uno.x)
@@ -695,8 +694,7 @@ define i1 @assume_nan_x2_ord(float %x, float %y) {
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[UNO_X]])
 ; CHECK-NEXT:    [[UNO_Y:%.*]] = fcmp uno float [[Y:%.*]], 0.000000e+00
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[UNO_Y]])
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ord float [[X]], [[Y]]
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 false
 ;
   %uno.x = fcmp uno float %x, 0.0
   call void @llvm.assume(i1 %uno.x)
diff --git a/llvm/test/Transforms/InstSimplify/known-never-nan.ll b/llvm/test/Transforms/InstSimplify/known-never-nan.ll
index 49a48ae42d0645..907eca0a856a81 100644
--- a/llvm/test/Transforms/InstSimplify/known-never-nan.ll
+++ b/llvm/test/Transforms/InstSimplify/known-never-nan.ll
@@ -512,12 +512,10 @@ define i1 @isKnownNeverNaN_nofpclass_callsite() {
 
 declare nofpclass(sub norm zero inf) double @only_nans()
 
-; TODO: Could simplify to false
 define i1 @isKnownNeverNaN_only_nans() {
 ; CHECK-LABEL: @isKnownNeverNaN_only_nans(
 ; CHECK-NEXT:    [[CALL:%.*]] = call double @only_nans()
-; CHECK-NEXT:    [[TMP:%.*]] = fcmp ord double [[CALL]], [[CALL]]
-; CHECK-NEXT:    ret i1 [[TMP]]
+; CHECK-NEXT:    ret i1 false
 ;
   %call = call double @only_nans()
   %tmp = fcmp ord double %call, %call

>From f9ed2118cc4b8dee83146132162af4408120dcdb Mon Sep 17 00:00:00 2001
From: Alex MacLean <amaclean at nvidia.com>
Date: Mon, 8 Jul 2024 16:06:57 +0000
Subject: [PATCH 3/3] address comments

---
 llvm/lib/Analysis/InstructionSimplify.cpp | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 78da7e02fd8ce9..868a7bf8287006 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4117,8 +4117,11 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
   // 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) {
-    KnownFPClass RHSClass = computeKnownFPClass(RHS, fcAllFlags, 0, Q);
-    KnownFPClass LHSClass = computeKnownFPClass(LHS, fcAllFlags, 0, Q);
+    KnownFPClass RHSClass =
+        computeKnownFPClass(RHS, fcAllFlags, /*Depth=*/0, Q);
+    KnownFPClass LHSClass =
+        computeKnownFPClass(LHS, fcAllFlags, /*Depth=*/0, Q);
+
     if (FMF.noNaNs() ||
         (RHSClass.isKnownNeverNaN() && LHSClass.isKnownNeverNaN()))
       return ConstantInt::get(RetTy, Pred == FCmpInst::FCMP_ORD);



More information about the llvm-commits mailing list