[llvm] 77e3fea - ValueTracking: Improve trunc handling in computeKnownFPClass

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 26 02:21:11 PDT 2023


Author: Matt Arsenault
Date: 2023-04-26T05:20:56-04:00
New Revision: 77e3fea02bf27c49ce9ebe7452aab43cc1235f8b

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

LOG: ValueTracking: Improve trunc handling in computeKnownFPClass

Added: 
    

Modified: 
    llvm/include/llvm/Analysis/ValueTracking.h
    llvm/lib/Analysis/ValueTracking.cpp
    llvm/test/Transforms/Attributor/nofpclass-trunc.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 0947dbb7b688..dc68691cae7c 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -238,6 +238,10 @@ struct KnownFPClass {
   /// definitely set or false if the sign bit is definitely unset.
   std::optional<bool> SignBit;
 
+  /// Return true if it's known this can never be one of the mask entries.
+  bool isKnownNever(FPClassTest Mask) const {
+    return (KnownFPClasses & Mask) == fcNone;
+  }
 
   bool isUnknown() const {
     return KnownFPClasses == fcAllFlags && !SignBit;
@@ -245,33 +249,43 @@ struct KnownFPClass {
 
   /// Return true if it's known this can never be a nan.
   bool isKnownNeverNaN() const {
-    return (KnownFPClasses & fcNan) == fcNone;
+    return isKnownNever(fcNan);
   }
 
   /// Return true if it's known this can never be an infinity.
   bool isKnownNeverInfinity() const {
-    return (KnownFPClasses & fcInf) == fcNone;
+    return isKnownNever(fcInf);
   }
 
   /// Return true if it's known this can never be +infinity.
   bool isKnownNeverPosInfinity() const {
-    return (KnownFPClasses & fcPosInf) == fcNone;
+    return isKnownNever(fcPosInf);
   }
 
   /// Return true if it's known this can never be -infinity.
   bool isKnownNeverNegInfinity() const {
-    return (KnownFPClasses & fcNegInf) == fcNone;
+    return isKnownNever(fcNegInf);
   }
 
   /// Return true if it's known this can never be a subnormal
   bool isKnownNeverSubnormal() const {
-    return (KnownFPClasses & fcSubnormal) == fcNone;
+    return isKnownNever(fcSubnormal);
+  }
+
+  /// Return true if it's known this can never be a negativesubnormal
+  bool isKnownNeverNegSubnormal() const {
+    return isKnownNever(fcNegSubnormal);
   }
 
   /// Return true if it's known this can never be a zero. This means a literal
   /// [+-]0, and does not include denormal inputs implicitly treated as [+-]0.
   bool isKnownNeverZero() const {
-    return (KnownFPClasses & fcZero) == fcNone;
+    return isKnownNever(fcZero);
+  }
+
+  /// Return true if it's known this can never be a literal negative zero.
+  bool isKnownNeverNegZero() const {
+    return isKnownNever(fcNegZero);
   }
 
   /// Return true if it's know this can never be interpreted as a zero. This

diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index fa5c21404b43..249b22873c78 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4620,8 +4620,13 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
       }
       case Intrinsic::trunc: {
         KnownFPClass KnownSrc;
-        computeKnownFPClass(II->getArgOperand(0), DemandedElts,
-                            InterestedClasses, KnownSrc, Depth + 1, Q, TLI);
+
+        FPClassTest InterestedSrcs = InterestedClasses;
+        if (InterestedClasses & fcZero)
+          InterestedClasses |= fcNormal | fcSubnormal;
+
+        computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedSrcs,
+                            KnownSrc, Depth + 1, Q, TLI);
 
         // Integer results cannot be subnormal.
         Known.knownNot(fcSubnormal);
@@ -4635,6 +4640,21 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
         // Non-constrained intrinsics do not guarantee signaling nan quieting.
         if (KnownSrc.isKnownNeverNaN())
           Known.knownNot(fcNan);
+
+        if (KnownSrc.isKnownNever(fcPosNormal))
+          Known.knownNot(fcPosNormal);
+
+        if (KnownSrc.isKnownNever(fcNegNormal))
+          Known.knownNot(fcNegNormal);
+
+        if (KnownSrc.isKnownNever(fcPosZero | fcPosSubnormal | fcPosNormal))
+          Known.knownNot(fcPosZero);
+
+        if (KnownSrc.isKnownNever(fcNegZero | fcNegSubnormal | fcNegNormal))
+          Known.knownNot(fcNegZero);
+
+        // Sign should be preserved
+        Known.SignBit = KnownSrc.SignBit;
         break;
       }
       case Intrinsic::exp:
@@ -4675,7 +4695,7 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
         if ((InterestedClasses & fcNegInf) != fcNone)
           InterestedSrcs |= fcZero | fcSubnormal;
         if ((InterestedClasses & fcNan) != fcNone)
-          InterestedSrcs |= fcNan | KnownFPClass::OrderedLessThanZeroMask;
+          InterestedSrcs |= fcNan | (fcNegative & ~fcNan);
 
         KnownFPClass KnownSrc;
         computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedSrcs,

diff  --git a/llvm/test/Transforms/Attributor/nofpclass-trunc.ll b/llvm/test/Transforms/Attributor/nofpclass-trunc.ll
index eda3bdf379af..63c9d2f066c7 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-trunc.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-trunc.ll
@@ -105,9 +105,9 @@ define float @ret_trunc_nonzero(float nofpclass(nzero) %arg0) {
 }
 
 define float @ret_trunc_nonorm(float nofpclass(norm) %arg0) {
-; CHECK-LABEL: define nofpclass(sub) float @ret_trunc_nonorm
+; CHECK-LABEL: define nofpclass(sub norm) float @ret_trunc_nonorm
 ; CHECK-SAME: (float nofpclass(norm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(sub) float @llvm.trunc.f32(float [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(sub norm) float @llvm.trunc.f32(float [[ARG0]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.trunc.f32(float %arg0)
@@ -115,9 +115,9 @@ define float @ret_trunc_nonorm(float nofpclass(norm) %arg0) {
 }
 
 define float @ret_trunc_nonnorm(float nofpclass(nnorm) %arg0) {
-; CHECK-LABEL: define nofpclass(sub) float @ret_trunc_nonnorm
+; CHECK-LABEL: define nofpclass(sub nnorm) float @ret_trunc_nonnorm
 ; CHECK-SAME: (float nofpclass(nnorm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(sub) float @llvm.trunc.f32(float [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(sub nnorm) float @llvm.trunc.f32(float [[ARG0]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.trunc.f32(float %arg0)
@@ -125,9 +125,9 @@ define float @ret_trunc_nonnorm(float nofpclass(nnorm) %arg0) {
 }
 
 define float @ret_trunc_nopnorm(float nofpclass(pnorm) %arg0) {
-; CHECK-LABEL: define nofpclass(sub) float @ret_trunc_nopnorm
+; CHECK-LABEL: define nofpclass(sub pnorm) float @ret_trunc_nopnorm
 ; CHECK-SAME: (float nofpclass(pnorm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(sub) float @llvm.trunc.f32(float [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(sub pnorm) float @llvm.trunc.f32(float [[ARG0]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.trunc.f32(float %arg0)
@@ -155,9 +155,9 @@ define float @ret_trunc_nopsub(float nofpclass(psub) %arg0) {
 }
 
 define float @ret_trunc_nonorm_nosub(float nofpclass(norm sub) %arg0) {
-; CHECK-LABEL: define nofpclass(sub) float @ret_trunc_nonorm_nosub
+; CHECK-LABEL: define nofpclass(sub norm) float @ret_trunc_nonorm_nosub
 ; CHECK-SAME: (float nofpclass(sub norm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(sub) float @llvm.trunc.f32(float [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(sub norm) float @llvm.trunc.f32(float [[ARG0]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.trunc.f32(float %arg0)
@@ -165,9 +165,9 @@ define float @ret_trunc_nonorm_nosub(float nofpclass(norm sub) %arg0) {
 }
 
 define float @ret_trunc_nopnorm_nopsub(float nofpclass(pnorm psub) %arg0) {
-; CHECK-LABEL: define nofpclass(sub) float @ret_trunc_nopnorm_nopsub
+; CHECK-LABEL: define nofpclass(sub pnorm) float @ret_trunc_nopnorm_nopsub
 ; CHECK-SAME: (float nofpclass(psub pnorm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(sub) float @llvm.trunc.f32(float [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(sub pnorm) float @llvm.trunc.f32(float [[ARG0]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.trunc.f32(float %arg0)
@@ -175,9 +175,9 @@ define float @ret_trunc_nopnorm_nopsub(float nofpclass(pnorm psub) %arg0) {
 }
 
 define float @ret_trunc_nonnorm_nonsub(float nofpclass(nnorm nsub) %arg0) {
-; CHECK-LABEL: define nofpclass(sub) float @ret_trunc_nonnorm_nonsub
+; CHECK-LABEL: define nofpclass(sub nnorm) float @ret_trunc_nonnorm_nonsub
 ; CHECK-SAME: (float nofpclass(nsub nnorm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(sub) float @llvm.trunc.f32(float [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(sub nnorm) float @llvm.trunc.f32(float [[ARG0]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.trunc.f32(float %arg0)
@@ -185,9 +185,9 @@ define float @ret_trunc_nonnorm_nonsub(float nofpclass(nnorm nsub) %arg0) {
 }
 
 define float @ret_trunc_nopnorm_nonsub(float nofpclass(pnorm nsub) %arg0) {
-; CHECK-LABEL: define nofpclass(sub) float @ret_trunc_nopnorm_nonsub
+; CHECK-LABEL: define nofpclass(sub pnorm) float @ret_trunc_nopnorm_nonsub
 ; CHECK-SAME: (float nofpclass(nsub pnorm) [[ARG0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(sub) float @llvm.trunc.f32(float [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(sub pnorm) float @llvm.trunc.f32(float [[ARG0]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.trunc.f32(float %arg0)


        


More information about the llvm-commits mailing list