Skip to content

Commit 45c01e8

Browse files
authored
[NFC][TargetTransformInfo][VectorUtils] Consolidate isVectorIntrinsic... api (#117635)
- update `VectorUtils:isVectorIntrinsicWithScalarOpAtArg` to use TTI for all uses, to allow specifiction of target specific intrinsics - add TTI to the `isVectorIntrinsicWithStructReturnOverloadAtField` api - update TTI api to provide `isTargetIntrinsicWith...` functions and consistently name them - move `isTriviallyScalarizable` to VectorUtils - update all uses of the api and provide the TTI parameter Resolves #117030
1 parent b5d0278 commit 45c01e8

15 files changed

+145
-85
lines changed

llvm/include/llvm/Analysis/TargetTransformInfo.h

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -905,14 +905,20 @@ class TargetTransformInfo {
905905

906906
bool isTargetIntrinsicTriviallyScalarizable(Intrinsic::ID ID) const;
907907

908+
/// Identifies if the vector form of the intrinsic has a scalar operand.
908909
bool isTargetIntrinsicWithScalarOpAtArg(Intrinsic::ID ID,
909910
unsigned ScalarOpdIdx) const;
910911

911912
/// Identifies if the vector form of the intrinsic is overloaded on the type
912913
/// of the operand at index \p OpdIdx, or on the return type if \p OpdIdx is
913914
/// -1.
914-
bool isVectorIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID,
915-
int ScalarOpdIdx) const;
915+
bool isTargetIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID,
916+
int OpdIdx) const;
917+
918+
/// Identifies if the vector form of the intrinsic that returns a struct is
919+
/// overloaded at the struct element index \p RetIdx.
920+
bool isTargetIntrinsicWithStructReturnOverloadAtField(Intrinsic::ID ID,
921+
int RetIdx) const;
916922

917923
/// Estimate the overhead of scalarizing an instruction. Insert and Extract
918924
/// are set if the demanded result elements need to be inserted and/or
@@ -2020,8 +2026,11 @@ class TargetTransformInfo::Concept {
20202026
virtual bool isTargetIntrinsicTriviallyScalarizable(Intrinsic::ID ID) = 0;
20212027
virtual bool isTargetIntrinsicWithScalarOpAtArg(Intrinsic::ID ID,
20222028
unsigned ScalarOpdIdx) = 0;
2023-
virtual bool isVectorIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID,
2024-
int ScalarOpdIdx) = 0;
2029+
virtual bool isTargetIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID,
2030+
int OpdIdx) = 0;
2031+
virtual bool
2032+
isTargetIntrinsicWithStructReturnOverloadAtField(Intrinsic::ID ID,
2033+
int RetIdx) = 0;
20252034
virtual InstructionCost
20262035
getScalarizationOverhead(VectorType *Ty, const APInt &DemandedElts,
20272036
bool Insert, bool Extract, TargetCostKind CostKind,
@@ -2610,9 +2619,14 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
26102619
return Impl.isTargetIntrinsicWithScalarOpAtArg(ID, ScalarOpdIdx);
26112620
}
26122621

2613-
bool isVectorIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID,
2614-
int ScalarOpdIdx) override {
2615-
return Impl.isVectorIntrinsicWithOverloadTypeAtArg(ID, ScalarOpdIdx);
2622+
bool isTargetIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID,
2623+
int OpdIdx) override {
2624+
return Impl.isTargetIntrinsicWithOverloadTypeAtArg(ID, OpdIdx);
2625+
}
2626+
2627+
bool isTargetIntrinsicWithStructReturnOverloadAtField(Intrinsic::ID ID,
2628+
int RetIdx) override {
2629+
return Impl.isTargetIntrinsicWithStructReturnOverloadAtField(ID, RetIdx);
26162630
}
26172631

26182632
InstructionCost getScalarizationOverhead(VectorType *Ty,

llvm/include/llvm/Analysis/TargetTransformInfoImpl.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -396,9 +396,14 @@ class TargetTransformInfoImplBase {
396396
return false;
397397
}
398398

399-
bool isVectorIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID,
400-
int ScalarOpdIdx) const {
401-
return ScalarOpdIdx == -1;
399+
bool isTargetIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID,
400+
int OpdIdx) const {
401+
return OpdIdx == -1;
402+
}
403+
404+
bool isTargetIntrinsicWithStructReturnOverloadAtField(Intrinsic::ID ID,
405+
int RetIdx) const {
406+
return RetIdx == 0;
402407
}
403408

404409
InstructionCost getScalarizationOverhead(VectorType *Ty,

llvm/include/llvm/Analysis/VectorUtils.h

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,25 @@ typedef unsigned ID;
132132
/// This method returns true if the intrinsic's argument types are all scalars
133133
/// for the scalar form of the intrinsic and all vectors (or scalars handled by
134134
/// isVectorIntrinsicWithScalarOpAtArg) for the vector form of the intrinsic.
135+
///
136+
/// Note: isTriviallyVectorizable implies isTriviallyScalarizable.
135137
bool isTriviallyVectorizable(Intrinsic::ID ID);
136138

139+
/// Identify if the intrinsic is trivially scalarizable.
140+
/// This method returns true following the same predicates of
141+
/// isTriviallyVectorizable.
142+
143+
/// Note: There are intrinsics where implementing vectorization for the
144+
/// intrinsic is redundant, but we want to implement scalarization of the
145+
/// vector. To prevent the requirement that an intrinsic also implements
146+
/// vectorization we provide this seperate function.
147+
bool isTriviallyScalarizable(Intrinsic::ID ID, const TargetTransformInfo *TTI);
148+
137149
/// Identifies if the vector form of the intrinsic has a scalar operand.
138-
bool isVectorIntrinsicWithScalarOpAtArg(Intrinsic::ID ID,
139-
unsigned ScalarOpdIdx);
150+
/// \p TTI is used to consider target specific intrinsics, if no target specific
151+
/// intrinsics will be considered then it is appropriate to pass in nullptr.
152+
bool isVectorIntrinsicWithScalarOpAtArg(Intrinsic::ID ID, unsigned ScalarOpdIdx,
153+
const TargetTransformInfo *TTI);
140154

141155
/// Identifies if the vector form of the intrinsic is overloaded on the type of
142156
/// the operand at index \p OpdIdx, or on the return type if \p OpdIdx is -1.
@@ -146,9 +160,11 @@ bool isVectorIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID, int OpdIdx,
146160
const TargetTransformInfo *TTI);
147161

148162
/// Identifies if the vector form of the intrinsic that returns a struct is
149-
/// overloaded at the struct element index \p RetIdx.
150-
bool isVectorIntrinsicWithStructReturnOverloadAtField(Intrinsic::ID ID,
151-
int RetIdx);
163+
/// overloaded at the struct element index \p RetIdx. /// \p TTI is used to
164+
/// consider target specific intrinsics, if no target specific intrinsics
165+
/// will be considered then it is appropriate to pass in nullptr.
166+
bool isVectorIntrinsicWithStructReturnOverloadAtField(
167+
Intrinsic::ID ID, int RetIdx, const TargetTransformInfo *TTI);
152168

153169
/// Returns intrinsic ID for call.
154170
/// For the input call instruction it finds mapping intrinsic and returns

llvm/include/llvm/CodeGen/BasicTTIImpl.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -819,9 +819,14 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
819819
return false;
820820
}
821821

822-
bool isVectorIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID,
823-
int ScalarOpdIdx) const {
824-
return ScalarOpdIdx == -1;
822+
bool isTargetIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID,
823+
int OpdIdx) const {
824+
return OpdIdx == -1;
825+
}
826+
827+
bool isTargetIntrinsicWithStructReturnOverloadAtField(Intrinsic::ID ID,
828+
int RetIdx) const {
829+
return RetIdx == 0;
825830
}
826831

827832
/// Helper wrapper for the DemandedElts variant of getScalarizationOverhead.

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3447,7 +3447,7 @@ static Constant *ConstantFoldFixedVectorCall(
34473447
// Gather a column of constants.
34483448
for (unsigned J = 0, JE = Operands.size(); J != JE; ++J) {
34493449
// Some intrinsics use a scalar type for certain arguments.
3450-
if (isVectorIntrinsicWithScalarOpAtArg(IntrinsicID, J)) {
3450+
if (isVectorIntrinsicWithScalarOpAtArg(IntrinsicID, J, /*TTI=*/nullptr)) {
34513451
Lane[J] = Operands[J];
34523452
continue;
34533453
}

llvm/lib/Analysis/TargetTransformInfo.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -615,9 +615,14 @@ bool TargetTransformInfo::isTargetIntrinsicWithScalarOpAtArg(
615615
return TTIImpl->isTargetIntrinsicWithScalarOpAtArg(ID, ScalarOpdIdx);
616616
}
617617

618-
bool TargetTransformInfo::isVectorIntrinsicWithOverloadTypeAtArg(
619-
Intrinsic::ID ID, int ScalarOpdIdx) const {
620-
return TTIImpl->isVectorIntrinsicWithOverloadTypeAtArg(ID, ScalarOpdIdx);
618+
bool TargetTransformInfo::isTargetIntrinsicWithOverloadTypeAtArg(
619+
Intrinsic::ID ID, int OpdIdx) const {
620+
return TTIImpl->isTargetIntrinsicWithOverloadTypeAtArg(ID, OpdIdx);
621+
}
622+
623+
bool TargetTransformInfo::isTargetIntrinsicWithStructReturnOverloadAtField(
624+
Intrinsic::ID ID, int RetIdx) const {
625+
return TTIImpl->isTargetIntrinsicWithStructReturnOverloadAtField(ID, RetIdx);
621626
}
622627

623628
InstructionCost TargetTransformInfo::getScalarizationOverhead(

llvm/lib/Analysis/VectorUtils.cpp

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,31 @@ bool llvm::isTriviallyVectorizable(Intrinsic::ID ID) {
113113
}
114114
}
115115

116+
bool llvm::isTriviallyScalarizable(Intrinsic::ID ID,
117+
const TargetTransformInfo *TTI) {
118+
if (isTriviallyVectorizable(ID))
119+
return true;
120+
121+
if (TTI && Intrinsic::isTargetIntrinsic(ID))
122+
return TTI->isTargetIntrinsicTriviallyScalarizable(ID);
123+
124+
// TODO: Move frexp to isTriviallyVectorizable.
125+
// https://github.com/llvm/llvm-project/issues/112408
126+
switch (ID) {
127+
case Intrinsic::frexp:
128+
return true;
129+
}
130+
return false;
131+
}
132+
116133
/// Identifies if the vector form of the intrinsic has a scalar operand.
117134
bool llvm::isVectorIntrinsicWithScalarOpAtArg(Intrinsic::ID ID,
118-
unsigned ScalarOpdIdx) {
135+
unsigned ScalarOpdIdx,
136+
const TargetTransformInfo *TTI) {
137+
138+
if (TTI && Intrinsic::isTargetIntrinsic(ID))
139+
return TTI->isTargetIntrinsicWithScalarOpAtArg(ID, ScalarOpdIdx);
140+
119141
switch (ID) {
120142
case Intrinsic::abs:
121143
case Intrinsic::vp_abs:
@@ -142,7 +164,7 @@ bool llvm::isVectorIntrinsicWithOverloadTypeAtArg(
142164
assert(ID != Intrinsic::not_intrinsic && "Not an intrinsic!");
143165

144166
if (TTI && Intrinsic::isTargetIntrinsic(ID))
145-
return TTI->isVectorIntrinsicWithOverloadTypeAtArg(ID, OpdIdx);
167+
return TTI->isTargetIntrinsicWithOverloadTypeAtArg(ID, OpdIdx);
146168

147169
if (VPCastIntrinsic::isVPCast(ID))
148170
return OpdIdx == -1 || OpdIdx == 0;
@@ -167,8 +189,12 @@ bool llvm::isVectorIntrinsicWithOverloadTypeAtArg(
167189
}
168190
}
169191

170-
bool llvm::isVectorIntrinsicWithStructReturnOverloadAtField(Intrinsic::ID ID,
171-
int RetIdx) {
192+
bool llvm::isVectorIntrinsicWithStructReturnOverloadAtField(
193+
Intrinsic::ID ID, int RetIdx, const TargetTransformInfo *TTI) {
194+
195+
if (TTI && Intrinsic::isTargetIntrinsic(ID))
196+
return TTI->isTargetIntrinsicWithStructReturnOverloadAtField(ID, RetIdx);
197+
172198
switch (ID) {
173199
case Intrinsic::frexp:
174200
return RetIdx == 0 || RetIdx == 1;

llvm/lib/CodeGen/ReplaceWithVeclib.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ static bool replaceWithCallToVeclib(const TargetLibraryInfo &TLI,
121121
auto *ArgTy = Arg.value()->getType();
122122
bool IsOloadTy = isVectorIntrinsicWithOverloadTypeAtArg(IID, Arg.index(),
123123
/*TTI=*/nullptr);
124-
if (isVectorIntrinsicWithScalarOpAtArg(IID, Arg.index())) {
124+
if (isVectorIntrinsicWithScalarOpAtArg(IID, Arg.index(), /*TTI=*/nullptr)) {
125125
ScalarArgTypes.push_back(ArgTy);
126126
if (IsOloadTy)
127127
OloadTys.push_back(ArgTy);

llvm/lib/Target/DirectX/DirectXTargetTransformInfo.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ bool DirectXTTIImpl::isTargetIntrinsicWithScalarOpAtArg(Intrinsic::ID ID,
2525
}
2626
}
2727

28-
bool DirectXTTIImpl::isVectorIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID,
29-
int ScalarOpdIdx) {
28+
bool DirectXTTIImpl::isTargetIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID,
29+
int OpdIdx) {
3030
switch (ID) {
3131
case Intrinsic::dx_asdouble:
32-
return ScalarOpdIdx == 0;
32+
return OpdIdx == 0;
3333
default:
34-
return ScalarOpdIdx == -1;
34+
return OpdIdx == -1;
3535
}
3636
}
3737

llvm/lib/Target/DirectX/DirectXTargetTransformInfo.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ class DirectXTTIImpl : public BasicTTIImplBase<DirectXTTIImpl> {
3737
bool isTargetIntrinsicTriviallyScalarizable(Intrinsic::ID ID) const;
3838
bool isTargetIntrinsicWithScalarOpAtArg(Intrinsic::ID ID,
3939
unsigned ScalarOpdIdx);
40-
bool isVectorIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID,
41-
int ScalarOpdIdx);
40+
bool isTargetIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID, int OpdIdx);
4241
};
4342
} // namespace llvm
4443

llvm/lib/Transforms/Scalar/Scalarizer.cpp

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,6 @@ class ScalarizerVisitor : public InstVisitor<ScalarizerVisitor, bool> {
279279

280280
bool visit(Function &F);
281281

282-
bool isTriviallyScalarizable(Intrinsic::ID ID);
283-
284282
// InstVisitor methods. They return true if the instruction was scalarized,
285283
// false if nothing changed.
286284
bool visitInstruction(Instruction &I) { return false; }
@@ -683,19 +681,6 @@ bool ScalarizerVisitor::splitBinary(Instruction &I, const Splitter &Split) {
683681
return true;
684682
}
685683

686-
bool ScalarizerVisitor::isTriviallyScalarizable(Intrinsic::ID ID) {
687-
if (isTriviallyVectorizable(ID))
688-
return true;
689-
// TODO: Move frexp to isTriviallyVectorizable.
690-
// https://github.com/llvm/llvm-project/issues/112408
691-
switch (ID) {
692-
case Intrinsic::frexp:
693-
return true;
694-
}
695-
return Intrinsic::isTargetIntrinsic(ID) &&
696-
TTI->isTargetIntrinsicTriviallyScalarizable(ID);
697-
}
698-
699684
/// If a call to a vector typed intrinsic function, split into a scalar call per
700685
/// element if possible for the intrinsic.
701686
bool ScalarizerVisitor::splitCall(CallInst &CI) {
@@ -715,7 +700,7 @@ bool ScalarizerVisitor::splitCall(CallInst &CI) {
715700

716701
Intrinsic::ID ID = F->getIntrinsicID();
717702

718-
if (ID == Intrinsic::not_intrinsic || !isTriviallyScalarizable(ID))
703+
if (ID == Intrinsic::not_intrinsic || !isTriviallyScalarizable(ID, TTI))
719704
return false;
720705

721706
// unsigned NumElems = VT->getNumElements();
@@ -743,7 +728,7 @@ bool ScalarizerVisitor::splitCall(CallInst &CI) {
743728
// will only scalarize when the struct elements have the same bitness.
744729
if (!CurrVS || CurrVS->NumPacked != VS->NumPacked)
745730
return false;
746-
if (isVectorIntrinsicWithStructReturnOverloadAtField(ID, I))
731+
if (isVectorIntrinsicWithStructReturnOverloadAtField(ID, I, TTI))
747732
Tys.push_back(CurrVS->SplitTy);
748733
}
749734
}
@@ -794,8 +779,7 @@ bool ScalarizerVisitor::splitCall(CallInst &CI) {
794779
Tys[0] = VS->RemainderTy;
795780

796781
for (unsigned J = 0; J != NumArgs; ++J) {
797-
if (isVectorIntrinsicWithScalarOpAtArg(ID, J) ||
798-
TTI->isTargetIntrinsicWithScalarOpAtArg(ID, J)) {
782+
if (isVectorIntrinsicWithScalarOpAtArg(ID, J, TTI)) {
799783
ScalarCallOps.push_back(ScalarOperands[J]);
800784
} else {
801785
ScalarCallOps.push_back(Scattered[J][I]);
@@ -1089,7 +1073,7 @@ bool ScalarizerVisitor::visitExtractValueInst(ExtractValueInst &EVI) {
10891073
if (!F)
10901074
return false;
10911075
Intrinsic::ID ID = F->getIntrinsicID();
1092-
if (ID == Intrinsic::not_intrinsic || !isTriviallyScalarizable(ID))
1076+
if (ID == Intrinsic::not_intrinsic || !isTriviallyScalarizable(ID, TTI))
10931077
return false;
10941078
// Note: Fall through means Operand is a`CallInst` and it is defined in
10951079
// `isTriviallyScalarizable`.

llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -926,7 +926,7 @@ bool LoopVectorizationLegality::canVectorizeInstrs() {
926926
auto *SE = PSE.getSE();
927927
Intrinsic::ID IntrinID = getVectorIntrinsicIDForCall(CI, TLI);
928928
for (unsigned Idx = 0; Idx < CI->arg_size(); ++Idx)
929-
if (isVectorIntrinsicWithScalarOpAtArg(IntrinID, Idx)) {
929+
if (isVectorIntrinsicWithScalarOpAtArg(IntrinID, Idx, TTI)) {
930930
if (!SE->isLoopInvariant(PSE.getSCEV(CI->getOperand(Idx)),
931931
TheLoop)) {
932932
reportVectorizationFailure("Found unvectorizable intrinsic",

0 commit comments

Comments
 (0)