[llvm] 8e70ed6 - ValueTracking: Handle insertelement in computeKnownFPClass

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 19 05:18:51 PDT 2023


Author: Matt Arsenault
Date: 2023-04-19T08:18:37-04:00
New Revision: 8e70ed6efd212f7a261542e8d924219e80c5ccac

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

LOG: ValueTracking: Handle insertelement in computeKnownFPClass

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 1daef70b483d..ccf0ccf36ded 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -239,6 +239,10 @@ struct KnownFPClass {
   std::optional<bool> SignBit;
 
 
+  bool isUnknown() const {
+    return KnownFPClasses == fcAllFlags && !SignBit;
+  }
+
   /// Return true if it's known this can never be a nan.
   bool isKnownNeverNaN() const {
     return (KnownFPClasses & fcNan) == fcNone;

diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index b8ca38d084e6..dbf9c63789a0 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4388,12 +4388,28 @@ static FPClassTest computeKnownFPClassFromAssumes(const Value *V,
   return KnownFromAssume;
 }
 
+void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
+                         FPClassTest InterestedClasses, KnownFPClass &Known,
+                         unsigned Depth, const Query &Q,
+                         const TargetLibraryInfo *TLI);
+
+static void computeKnownFPClass(const Value *V, KnownFPClass &Known,
+                                FPClassTest InterestedClasses, unsigned Depth,
+                                const Query &Q, const TargetLibraryInfo *TLI) {
+  auto *FVTy = dyn_cast<FixedVectorType>(V->getType());
+  APInt DemandedElts =
+      FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1);
+  computeKnownFPClass(V, DemandedElts, InterestedClasses, Known, Depth, Q, TLI);
+}
+
 // TODO: Merge implementations of isKnownNeverNaN, isKnownNeverInfinity,
 // CannotBeNegativeZero, cannotBeOrderedLessThanZero into here.
 void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
                          FPClassTest InterestedClasses, KnownFPClass &Known,
                          unsigned Depth, const Query &Q,
                          const TargetLibraryInfo *TLI) {
+  assert(Known.isUnknown() && "should not be called with known information");
+
   if (!DemandedElts) {
     // No demanded elts, better to assume we don't know anything.
     Known.resetAll();
@@ -4668,6 +4684,41 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
 
     break;
   }
+  case Instruction::InsertElement: {
+    if (isa<ScalableVectorType>(Op->getType()))
+      return;
+
+    const Value *Vec = Op->getOperand(0);
+    const Value *Elt = Op->getOperand(1);
+    auto *CIdx = dyn_cast<ConstantInt>(Op->getOperand(2));
+    // Early out if the index is non-constant or out-of-range.
+    unsigned NumElts = DemandedElts.getBitWidth();
+    if (!CIdx || CIdx->getValue().uge(NumElts))
+      return;
+
+    unsigned EltIdx = CIdx->getZExtValue();
+    // Do we demand the inserted element?
+    if (DemandedElts[EltIdx]) {
+      computeKnownFPClass(Elt, Known, InterestedClasses, Depth + 1, Q, TLI);
+      // If we don't know any bits, early out.
+      if (Known.isUnknown())
+        break;
+    } else {
+      Known.KnownFPClasses = fcNone;
+    }
+
+    // We don't need the base vector element that has been inserted.
+    APInt DemandedVecElts = DemandedElts;
+    DemandedVecElts.clearBit(EltIdx);
+    if (!!DemandedVecElts) {
+      KnownFPClass Known2;
+      computeKnownFPClass(Vec, DemandedVecElts, InterestedClasses, Known2,
+                          Depth + 1, Q, TLI);
+      Known |= Known2;
+    }
+
+    break;
+  }
   case Instruction::ExtractValue: {
     computeKnownFPClass(Op->getOperand(0), DemandedElts, InterestedClasses,
                         Known, Depth + 1, Q, TLI);
@@ -4697,10 +4748,7 @@ llvm::computeKnownFPClass(const Value *V, const DataLayout &DL,
                           const Instruction *CxtI, const DominatorTree *DT,
                           OptimizationRemarkEmitter *ORE, bool UseInstrInfo) {
   KnownFPClass Known;
-  auto *FVTy = dyn_cast<FixedVectorType>(V->getType());
-  APInt DemandedElts =
-      FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1);
-  ::computeKnownFPClass(V, DemandedElts, InterestedClasses, Known, Depth,
+  ::computeKnownFPClass(V, Known, InterestedClasses, Depth,
                         Query(DL, AC, safeCxtI(V, CxtI), DT, UseInstrInfo, ORE),
                         TLI);
   return Known;

diff  --git a/llvm/test/Transforms/Attributor/nofpclass.ll b/llvm/test/Transforms/Attributor/nofpclass.ll
index 0ae2de3b4410..5dc56b83eb97 100644
--- a/llvm/test/Transforms/Attributor/nofpclass.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass.ll
@@ -884,3 +884,141 @@ define float @returned_extractvalue([4 x float] nofpclass(nan) %array) {
   %extract = extractvalue [4 x float] %array, 0
   ret float %extract
 }
+
+define float @return_nofpclass_freeze_nan_arg(float nofpclass(nan) %arg) {
+; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none)
+; CHECK-LABEL: define noundef float @return_nofpclass_freeze_nan_arg
+; CHECK-SAME: (float nofpclass(nan) [[ARG:%.*]]) #[[ATTR2]] {
+; CHECK-NEXT:    [[FREEZE:%.*]] = freeze float [[ARG]]
+; CHECK-NEXT:    ret float [[FREEZE]]
+;
+  %freeze = freeze float %arg
+  ret float %freeze
+}
+
+define float @return_nofpclass_extractelement_freeze_pinf_arg(<2 x float> nofpclass(pinf) %arg) {
+; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none)
+; CHECK-LABEL: define noundef float @return_nofpclass_extractelement_freeze_pinf_arg
+; CHECK-SAME: (<2 x float> nofpclass(pinf) [[ARG:%.*]]) #[[ATTR2]] {
+; CHECK-NEXT:    [[FREEZE:%.*]] = freeze <2 x float> [[ARG]]
+; CHECK-NEXT:    [[ELT:%.*]] = extractelement <2 x float> [[FREEZE]], i32 0
+; CHECK-NEXT:    ret float [[ELT]]
+;
+  %freeze = freeze <2 x float> %arg
+  %elt = extractelement <2 x float> %freeze, i32 0
+  ret float %elt
+}
+
+define <4 x float> @insertelement_constant_chain() {
+; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none)
+; CHECK-LABEL: define nofpclass(nan ninf nzero sub) <4 x float> @insertelement_constant_chain
+; CHECK-SAME: () #[[ATTR2]] {
+; CHECK-NEXT:    [[INS_0:%.*]] = insertelement <4 x float> poison, float 1.000000e+00, i32 0
+; CHECK-NEXT:    [[INS_1:%.*]] = insertelement <4 x float> [[INS_0]], float 0.000000e+00, i32 1
+; CHECK-NEXT:    [[INS_2:%.*]] = insertelement <4 x float> [[INS_1]], float -9.000000e+00, i32 2
+; CHECK-NEXT:    [[INS_3:%.*]] = insertelement <4 x float> [[INS_2]], float 0x7FF0000000000000, i32 3
+; CHECK-NEXT:    ret <4 x float> [[INS_3]]
+;
+  %ins.0 = insertelement <4 x float> poison, float 1.0, i32 0
+  %ins.1 = insertelement <4 x float> %ins.0, float 0.0, i32 1
+  %ins.2 = insertelement <4 x float> %ins.1, float -9.0, i32 2
+  %ins.3 = insertelement <4 x float> %ins.2, float 0x7FF0000000000000, i32 3
+  ret <4 x float> %ins.3
+}
+
+define <vscale x 4 x float> @insertelement_scalable_constant_chain() {
+; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none)
+; CHECK-LABEL: define <vscale x 4 x float> @insertelement_scalable_constant_chain
+; CHECK-SAME: () #[[ATTR2]] {
+; CHECK-NEXT:    [[INS_0:%.*]] = insertelement <vscale x 4 x float> poison, float 1.000000e+00, i32 0
+; CHECK-NEXT:    [[INS_1:%.*]] = insertelement <vscale x 4 x float> [[INS_0]], float 0.000000e+00, i32 1
+; CHECK-NEXT:    [[INS_2:%.*]] = insertelement <vscale x 4 x float> [[INS_1]], float -9.000000e+00, i32 2
+; CHECK-NEXT:    [[INS_3:%.*]] = insertelement <vscale x 4 x float> [[INS_2]], float 0x7FF0000000000000, i32 3
+; CHECK-NEXT:    ret <vscale x 4 x float> [[INS_3]]
+;
+  %ins.0 = insertelement <vscale x 4 x float> poison, float 1.0, i32 0
+  %ins.1 = insertelement <vscale x 4 x float> %ins.0, float 0.0, i32 1
+  %ins.2 = insertelement <vscale x 4 x float> %ins.1, float -9.0, i32 2
+  %ins.3 = insertelement <vscale x 4 x float> %ins.2, float 0x7FF0000000000000, i32 3
+  ret <vscale x 4 x float> %ins.3
+}
+
+define <4 x float> @insertelement_unknown_base(<4 x float> %arg0) {
+; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none)
+; CHECK-LABEL: define <4 x float> @insertelement_unknown_base
+; CHECK-SAME: (<4 x float> [[ARG0:%.*]]) #[[ATTR2]] {
+; CHECK-NEXT:    [[INSERT:%.*]] = insertelement <4 x float> [[ARG0]], float 0.000000e+00, i32 1
+; CHECK-NEXT:    ret <4 x float> [[INSERT]]
+;
+  %insert = insertelement <4 x float> %arg0, float 0.0, i32 1
+  ret <4 x float> %insert
+}
+
+define float @insertelement_extractelement_same(<4 x float> %arg0) {
+; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none)
+; CHECK-LABEL: define nofpclass(nan inf nzero sub norm) float @insertelement_extractelement_same
+; CHECK-SAME: (<4 x float> [[ARG0:%.*]]) #[[ATTR2]] {
+; CHECK-NEXT:    [[INSERT:%.*]] = insertelement <4 x float> [[ARG0]], float 0.000000e+00, i32 1
+; CHECK-NEXT:    [[EXTRACT:%.*]] = extractelement <4 x float> [[INSERT]], i32 1
+; CHECK-NEXT:    ret float [[EXTRACT]]
+;
+  %insert = insertelement <4 x float> %arg0, float 0.0, i32 1
+  %extract = extractelement <4 x float> %insert, i32 1
+  ret float %extract
+}
+
+define float @insertelement_extractelement_
diff erent(<4 x float> nofpclass(zero) %arg0) {
+; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none)
+; CHECK-LABEL: define nofpclass(zero) float @insertelement_extractelement_
diff erent
+; CHECK-SAME: (<4 x float> nofpclass(zero) [[ARG0:%.*]]) #[[ATTR2]] {
+; CHECK-NEXT:    [[INSERT:%.*]] = insertelement <4 x float> [[ARG0]], float 0.000000e+00, i32 1
+; CHECK-NEXT:    [[EXTRACT:%.*]] = extractelement <4 x float> [[INSERT]], i32 2
+; CHECK-NEXT:    ret float [[EXTRACT]]
+;
+  %insert = insertelement <4 x float> %arg0, float 0.0, i32 1
+  %extract = extractelement <4 x float> %insert, i32 2
+  ret float %extract
+}
+
+define float @insertelement_extractelement_unknown(<4 x float> nofpclass(zero) %arg0, i32 %idx) {
+; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none)
+; CHECK-LABEL: define nofpclass(nzero) float @insertelement_extractelement_unknown
+; CHECK-SAME: (<4 x float> nofpclass(zero) [[ARG0:%.*]], i32 [[IDX:%.*]]) #[[ATTR2]] {
+; CHECK-NEXT:    [[INSERT:%.*]] = insertelement <4 x float> [[ARG0]], float 0.000000e+00, i32 1
+; CHECK-NEXT:    [[EXTRACT:%.*]] = extractelement <4 x float> [[INSERT]], i32 [[IDX]]
+; CHECK-NEXT:    ret float [[EXTRACT]]
+;
+  %insert = insertelement <4 x float> %arg0, float 0.0, i32 1
+  %extract = extractelement <4 x float> %insert, i32 %idx
+  ret float %extract
+}
+
+define <4 x float> @insertelement_index_oob_chain() {
+; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none)
+; CHECK-LABEL: define <4 x float> @insertelement_index_oob_chain
+; CHECK-SAME: () #[[ATTR2]] {
+; CHECK-NEXT:    [[INSERT:%.*]] = insertelement <4 x float> zeroinitializer, float 0x7FF0000000000000, i32 4
+; CHECK-NEXT:    ret <4 x float> [[INSERT]]
+;
+  %insert = insertelement <4 x float> zeroinitializer, float 0x7FF0000000000000, i32 4
+  ret <4 x float> %insert
+}
+
+define <2 x float> @multiple_extractelement(<4 x float> nofpclass(zero) %arg0) {
+; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none)
+; CHECK-LABEL: define nofpclass(zero) <2 x float> @multiple_extractelement
+; CHECK-SAME: (<4 x float> nofpclass(zero) [[ARG0:%.*]]) #[[ATTR2]] {
+; CHECK-NEXT:    [[INSERT:%.*]] = insertelement <4 x float> [[ARG0]], float 0.000000e+00, i32 1
+; CHECK-NEXT:    [[EXTRACT2:%.*]] = extractelement <4 x float> [[INSERT]], i32 2
+; CHECK-NEXT:    [[EXTRACT3:%.*]] = extractelement <4 x float> [[INSERT]], i32 3
+; CHECK-NEXT:    [[INS_0:%.*]] = insertelement <2 x float> poison, float [[EXTRACT3]], i32 0
+; CHECK-NEXT:    [[INS_1:%.*]] = insertelement <2 x float> [[INS_0]], float [[EXTRACT2]], i32 1
+; CHECK-NEXT:    ret <2 x float> [[INS_1]]
+;
+  %insert = insertelement <4 x float> %arg0, float 0.0, i32 1
+  %extract2 = extractelement <4 x float> %insert, i32 2
+  %extract3 = extractelement <4 x float> %insert, i32 3
+  %ins.0 = insertelement <2 x float> poison, float %extract3, i32 0
+  %ins.1 = insertelement <2 x float> %ins.0, float %extract2, i32 1
+  ret <2 x float> %ins.1
+}


        


More information about the llvm-commits mailing list