[llvm] a632ca4 - ValueTracking: Fix nan result handling for fmul

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 15 06:35:19 PDT 2023


Author: Matt Arsenault
Date: 2023-06-15T09:35:12-04:00
New Revision: a632ca4b00279baf18e72a171ec0ce526e9d80aa

URL: https://github.com/llvm/llvm-project/commit/a632ca4b00279baf18e72a171ec0ce526e9d80aa
DIFF: https://github.com/llvm/llvm-project/commit/a632ca4b00279baf18e72a171ec0ce526e9d80aa.diff

LOG: ValueTracking: Fix nan result handling for fmul

This was mishandling maybe 0 * inf.

Fixes issue #63316

Added: 
    

Modified: 
    llvm/lib/Analysis/ValueTracking.cpp
    llvm/test/Transforms/Attributor/nofpclass-nan-fmul.ll
    llvm/test/Transforms/Inline/simplify-instruction-computeKnownFPClass-context.ll
    llvm/test/Transforms/InstSimplify/known-never-nan.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 5393be0e247b4..e4e1a2b4707dc 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4760,29 +4760,36 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
     if ((InterestedClasses & fcNan) != fcNan)
       break;
 
+    // fcSubnormal is only needed in case of DAZ.
+    const FPClassTest NeedForNan = fcNan | fcInf | fcZero | fcSubnormal;
+
     KnownFPClass KnownLHS, KnownRHS;
-    computeKnownFPClass(Op->getOperand(1), DemandedElts,
-                        fcNan | fcInf | fcZero | fcSubnormal, KnownRHS,
+    computeKnownFPClass(Op->getOperand(1), DemandedElts, NeedForNan, KnownRHS,
                         Depth + 1, Q);
-    if (KnownRHS.isKnownNeverNaN() &&
-        (KnownRHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverZero())) {
-      computeKnownFPClass(Op->getOperand(0), DemandedElts,
-                          fcNan | fcInf | fcZero, KnownLHS, Depth + 1, Q);
-      if (!KnownLHS.isKnownNeverNaN())
-        break;
+    if (!KnownRHS.isKnownNeverNaN())
+      break;
 
-      const Function *F = cast<Instruction>(Op)->getFunction();
+    computeKnownFPClass(Op->getOperand(0), DemandedElts, NeedForNan, KnownLHS,
+                        Depth + 1, Q);
+    if (!KnownLHS.isKnownNeverNaN())
+      break;
 
-      // If neither side can be zero (or nan) fmul never produces NaN.
-      // TODO: Check operand combinations.
-      // e.g. fmul nofpclass(inf nan zero), nofpclass(nan) -> nofpclass(nan)
-      if ((KnownLHS.isKnownNeverInfinity() ||
-           (F && KnownLHS.isKnownNeverLogicalZero(*F, Op->getType()))) &&
-          (KnownRHS.isKnownNeverInfinity() ||
-           (F && KnownRHS.isKnownNeverLogicalZero(*F, Op->getType()))))
-        Known.knownNot(fcNan);
+    // If 0 * +/-inf produces NaN.
+    if (KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity()) {
+      Known.knownNot(fcNan);
+      break;
     }
 
+    const Function *F = cast<Instruction>(Op)->getFunction();
+    if (!F)
+      break;
+
+    if ((KnownRHS.isKnownNeverInfinity() ||
+         KnownLHS.isKnownNeverLogicalZero(*F, Op->getType())) &&
+        (KnownLHS.isKnownNeverInfinity() ||
+         KnownRHS.isKnownNeverLogicalZero(*F, Op->getType())))
+      Known.knownNot(fcNan);
+
     break;
   }
   case Instruction::FDiv:

diff  --git a/llvm/test/Transforms/Attributor/nofpclass-nan-fmul.ll b/llvm/test/Transforms/Attributor/nofpclass-nan-fmul.ll
index bb0179daefbda..fbf6c2e0981fb 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-nan-fmul.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-nan-fmul.ll
@@ -62,7 +62,7 @@ define float @ret_fmul_ieee_nonan_noinf__nonan_noinf(float nofpclass(nan inf) %a
 }
 
 define float @ret_fmul_ieee_nonan_nozero__nonan_noinf(float nofpclass(nan zero) %arg0, float nofpclass(nan inf) %arg1) #0 {
-; CHECK-LABEL: define nofpclass(nan) float @ret_fmul_ieee_nonan_nozero__nonan_noinf
+; CHECK-LABEL: define float @ret_fmul_ieee_nonan_nozero__nonan_noinf
 ; CHECK-SAME: (float nofpclass(nan zero) [[ARG0:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
@@ -72,7 +72,7 @@ define float @ret_fmul_ieee_nonan_nozero__nonan_noinf(float nofpclass(nan zero)
 }
 
 define float @ret_fmul_ieee_nonan_noinf__nonan_nozero(float nofpclass(nan inf) %arg0, float nofpclass(nan zero) %arg1) #0 {
-; CHECK-LABEL: define nofpclass(nan) float @ret_fmul_ieee_nonan_noinf__nonan_nozero
+; CHECK-LABEL: define float @ret_fmul_ieee_nonan_noinf__nonan_nozero
 ; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan zero) [[ARG1:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
@@ -285,7 +285,7 @@ define float @ret_fmul_ieee_noinf_nonan__nozero(float nofpclass(inf nan) %arg0,
 }
 
 define float @ret_fmul_ieee_nozero_nonan__noinf_nonan(float nofpclass(zero nan) %arg0, float nofpclass(inf nan) %arg1) {
-; CHECK-LABEL: define nofpclass(nan) float @ret_fmul_ieee_nozero_nonan__noinf_nonan
+; CHECK-LABEL: define float @ret_fmul_ieee_nozero_nonan__noinf_nonan
 ; CHECK-SAME: (float nofpclass(nan zero) [[ARG0:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR4]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
@@ -295,7 +295,7 @@ define float @ret_fmul_ieee_nozero_nonan__noinf_nonan(float nofpclass(zero nan)
 }
 
 define float @ret_fmul_ieee_noinf_nonan__nozero_nonan(float nofpclass(inf nan) %arg0, float nofpclass(zero nan) %arg1) {
-; CHECK-LABEL: define nofpclass(nan) float @ret_fmul_ieee_noinf_nonan__nozero_nonan
+; CHECK-LABEL: define float @ret_fmul_ieee_noinf_nonan__nozero_nonan
 ; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan zero) [[ARG1:%.*]]) #[[ATTR4]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
@@ -345,7 +345,7 @@ define float @ret_fmul_ieee_nozero_nonan__nozero_nonan_noinf(float nofpclass(zer
 }
 
 define float @ret_fmul_ieee_nozero_nonan_noinf__nonan(float nofpclass(zero nan inf) %arg0, float nofpclass(nan) %arg1) {
-; CHECK-LABEL: define float @ret_fmul_ieee_nozero_nonan_noinf__nonan
+; CHECK-LABEL: define nofpclass(nan) float @ret_fmul_ieee_nozero_nonan_noinf__nonan
 ; CHECK-SAME: (float nofpclass(nan inf zero) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR4]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
@@ -355,7 +355,7 @@ define float @ret_fmul_ieee_nozero_nonan_noinf__nonan(float nofpclass(zero nan i
 }
 
 define float @ret_fmul_ieee_nonan__nozero_nonan_noinf(float nofpclass(nan) %arg0, float nofpclass(zero nan inf) %arg1) {
-; CHECK-LABEL: define float @ret_fmul_ieee_nonan__nozero_nonan_noinf
+; CHECK-LABEL: define nofpclass(nan) float @ret_fmul_ieee_nonan__nozero_nonan_noinf
 ; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]], float nofpclass(nan inf zero) [[ARG1:%.*]]) #[[ATTR4]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]

diff  --git a/llvm/test/Transforms/Inline/simplify-instruction-computeKnownFPClass-context.ll b/llvm/test/Transforms/Inline/simplify-instruction-computeKnownFPClass-context.ll
index f0eb263bf0470..7e9f62158c2de 100644
--- a/llvm/test/Transforms/Inline/simplify-instruction-computeKnownFPClass-context.ll
+++ b/llvm/test/Transforms/Inline/simplify-instruction-computeKnownFPClass-context.ll
@@ -60,9 +60,9 @@ define internal i1 @simplify_fcmp_ord_frem_callee(double %a, double %b) {
   ret i1 %cmp
 }
 
-define i1 @simplify_fcmp_ord_fmul_caller(double nofpclass(zero nan) %i0, double nofpclass(zero nan) %i1) {
+define i1 @simplify_fcmp_ord_fmul_caller(double nofpclass(zero nan inf) %i0, double nofpclass(zero nan inf) %i1) {
 ; CHECK-LABEL: define i1 @simplify_fcmp_ord_fmul_caller
-; CHECK-SAME: (double nofpclass(nan zero) [[I0:%.*]], double nofpclass(nan zero) [[I1:%.*]]) {
+; CHECK-SAME: (double nofpclass(nan inf zero) [[I0:%.*]], double nofpclass(nan inf zero) [[I1:%.*]]) {
 ; CHECK-NEXT:    [[SUB_DOUBLE_SUB_I:%.*]] = fmul double [[I0]], [[I1]]
 ; CHECK-NEXT:    ret i1 true
 ;

diff  --git a/llvm/test/Transforms/InstSimplify/known-never-nan.ll b/llvm/test/Transforms/InstSimplify/known-never-nan.ll
index 8583d9733d72d..49a48ae42d064 100644
--- a/llvm/test/Transforms/InstSimplify/known-never-nan.ll
+++ b/llvm/test/Transforms/InstSimplify/known-never-nan.ll
@@ -559,7 +559,10 @@ unwind:
 ; This should not fold to false because fmul 0 * inf = nan
 define i1 @issue63316(i64 %arg) {
 ; CHECK-LABEL: @issue63316(
-; CHECK-NEXT:    ret i1 false
+; CHECK-NEXT:    [[SITOFP:%.*]] = sitofp i64 [[ARG:%.*]] to float
+; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[SITOFP]], 0x7FF0000000000000
+; CHECK-NEXT:    [[FCMP:%.*]] = fcmp uno float [[FMUL]], 0.000000e+00
+; CHECK-NEXT:    ret i1 [[FCMP]]
 ;
   %sitofp = sitofp i64 %arg to float
   %fmul = fmul float %sitofp, 0x7FF0000000000000
@@ -569,7 +572,10 @@ define i1 @issue63316(i64 %arg) {
 
 define i1 @issue63316_commute(i64 %arg) {
 ; CHECK-LABEL: @issue63316_commute(
-; CHECK-NEXT:    ret i1 false
+; CHECK-NEXT:    [[SITOFP:%.*]] = sitofp i64 [[ARG:%.*]] to float
+; CHECK-NEXT:    [[FMUL:%.*]] = fmul float 0x7FF0000000000000, [[SITOFP]]
+; CHECK-NEXT:    [[FCMP:%.*]] = fcmp uno float [[FMUL]], 0.000000e+00
+; CHECK-NEXT:    ret i1 [[FCMP]]
 ;
   %sitofp = sitofp i64 %arg to float
   %fmul = fmul float 0x7FF0000000000000, %sitofp


        


More information about the llvm-commits mailing list