[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