Skip to content

Commit 01797da

Browse files
Fix mechanism propagating mangled names for TLI function mappings (#66656)
Currently the mappings from TLI are used to generate the list of available "scalar to vector" mappings attached to scalar calls as "vector-function-abi-variant" LLVM IR attribute. Function names from TLI are wrapped in mangled name following the pattern: _ZGV<isa><mask><vlen><parameters>_<scalar_name>[(<vector_redirection>)] The problem is the mangled name uses _LLVM_ as the ISA name which prevents the compiler to compute vectorization factor for scalable vectors as it cannot make any decision based on the _LLVM_ ISA. If we use "s" as the ISA name, the compiler can make decisions based on VFABI specification where SVE spacific rules are described. This patch is only a refactoring stage where there is no change to the compiler's behaviour.
1 parent 2db8540 commit 01797da

File tree

10 files changed

+769
-759
lines changed

10 files changed

+769
-759
lines changed

llvm/include/llvm/Analysis/TargetLibraryInfo.h

+46-4
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,46 @@ class Function;
2424
class Module;
2525
class Triple;
2626

27-
/// Describes a possible vectorization of a function.
28-
/// Function 'VectorFnName' is equivalent to 'ScalarFnName' vectorized
29-
/// by a factor 'VectorizationFactor'.
30-
struct VecDesc {
27+
/// Provides info so a possible vectorization of a function can be
28+
/// computed. Function 'VectorFnName' is equivalent to 'ScalarFnName'
29+
/// vectorized by a factor 'VectorizationFactor'.
30+
/// The VABIPrefix string holds information about isa, mask, vlen,
31+
/// and vparams so a scalar-to-vector mapping of the form:
32+
/// _ZGV<isa><mask><vlen><vparams>_<scalarname>(<vectorname>)
33+
/// can be constructed where:
34+
///
35+
/// <isa> = "_LLVM_"
36+
/// <mask> = "M" if masked, "N" if no mask.
37+
/// <vlen> = Number of concurrent lanes, stored in the `VectorizationFactor`
38+
/// field of the `VecDesc` struct. If the number of lanes is scalable
39+
/// then 'x' is printed instead.
40+
/// <vparams> = "v", as many as are the numArgs.
41+
/// <scalarname> = the name of the scalar function.
42+
/// <vectorname> = the name of the vector function.
43+
class VecDesc {
3144
StringRef ScalarFnName;
3245
StringRef VectorFnName;
3346
ElementCount VectorizationFactor;
3447
bool Masked;
48+
StringRef VABIPrefix;
49+
50+
public:
51+
VecDesc() = delete;
52+
VecDesc(StringRef ScalarFnName, StringRef VectorFnName,
53+
ElementCount VectorizationFactor, bool Masked, StringRef VABIPrefix)
54+
: ScalarFnName(ScalarFnName), VectorFnName(VectorFnName),
55+
VectorizationFactor(VectorizationFactor), Masked(Masked),
56+
VABIPrefix(VABIPrefix) {}
57+
58+
StringRef getScalarFnName() const { return ScalarFnName; }
59+
StringRef getVectorFnName() const { return VectorFnName; }
60+
ElementCount getVectorizationFactor() const { return VectorizationFactor; }
61+
bool isMasked() const { return Masked; }
62+
StringRef getVABIPrefix() const { return VABIPrefix; }
63+
64+
/// Returns a vector function ABI variant string on the form:
65+
/// _ZGV<isa><mask><vlen><vparams>_<scalarname>(<vectorname>)
66+
std::string getVectorFunctionABIVariantString() const;
3567
};
3668

3769
enum LibFunc : unsigned {
@@ -176,6 +208,12 @@ class TargetLibraryInfoImpl {
176208
StringRef getVectorizedFunction(StringRef F, const ElementCount &VF,
177209
bool Masked) const;
178210

211+
/// Return a pointer to a VecDesc object holding all info for scalar to vector
212+
/// mappings in TLI for the equivalent of F, vectorized with factor VF.
213+
/// If no such mapping exists, return nullpointer.
214+
const VecDesc *getVectorMappingInfo(StringRef F, const ElementCount &VF,
215+
bool Masked) const;
216+
179217
/// Set to true iff i32 parameters to library functions should have signext
180218
/// or zeroext attributes if they correspond to C-level int or unsigned int,
181219
/// respectively.
@@ -354,6 +392,10 @@ class TargetLibraryInfo {
354392
bool Masked = false) const {
355393
return Impl->getVectorizedFunction(F, VF, Masked);
356394
}
395+
const VecDesc *getVectorMappingInfo(StringRef F, const ElementCount &VF,
396+
bool Masked) const {
397+
return Impl->getVectorMappingInfo(F, VF, Masked);
398+
}
357399

358400
/// Tests if the function is both available and a candidate for optimized code
359401
/// generation.

llvm/include/llvm/Analysis/VecFuncs.def

+667-667
Large diffs are not rendered by default.

llvm/include/llvm/Analysis/VectorUtils.h

-21
Original file line numberDiff line numberDiff line change
@@ -182,27 +182,6 @@ static constexpr char const *_LLVM_Scalarize_ = "_LLVM_Scalarize_";
182182
std::optional<VFInfo> tryDemangleForVFABI(StringRef MangledName,
183183
const Module &M);
184184

185-
/// This routine mangles the given VectorName according to the LangRef
186-
/// specification for vector-function-abi-variant attribute and is specific to
187-
/// the TLI mappings. It is the responsibility of the caller to make sure that
188-
/// this is only used if all parameters in the vector function are vector type.
189-
/// This returned string holds scalar-to-vector mapping:
190-
/// _ZGV<isa><mask><vlen><vparams>_<scalarname>(<vectorname>)
191-
///
192-
/// where:
193-
///
194-
/// <isa> = "_LLVM_"
195-
/// <mask> = "M" if masked, "N" if no mask.
196-
/// <vlen> = Number of concurrent lanes, stored in the `VectorizationFactor`
197-
/// field of the `VecDesc` struct. If the number of lanes is scalable
198-
/// then 'x' is printed instead.
199-
/// <vparams> = "v", as many as are the numArgs.
200-
/// <scalarname> = the name of the scalar function.
201-
/// <vectorname> = the name of the vector function.
202-
std::string mangleTLIVectorName(StringRef VectorName, StringRef ScalarName,
203-
unsigned numArgs, ElementCount VF,
204-
bool Masked = false);
205-
206185
/// Retrieve the `VFParamKind` from a string token.
207186
VFParamKind getVFParamKindFromString(const StringRef Token);
208187

llvm/lib/Analysis/TargetLibraryInfo.cpp

+38-17
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "llvm/Analysis/TargetLibraryInfo.h"
1414
#include "llvm/ADT/DenseMap.h"
15+
#include "llvm/ADT/SmallString.h"
1516
#include "llvm/IR/Constants.h"
1617
#include "llvm/InitializePasses.h"
1718
#include "llvm/Support/CommandLine.h"
@@ -44,6 +45,13 @@ StringLiteral const TargetLibraryInfoImpl::StandardNames[LibFunc::NumLibFuncs] =
4445
#include "llvm/Analysis/TargetLibraryInfo.def"
4546
};
4647

48+
std::string VecDesc::getVectorFunctionABIVariantString() const {
49+
SmallString<256> Buffer;
50+
llvm::raw_svector_ostream Out(Buffer);
51+
Out << VABIPrefix << "_" << ScalarFnName << "(" << VectorFnName << ")";
52+
return std::string(Out.str());
53+
}
54+
4755
// Recognized types of library function arguments and return types.
4856
enum FuncArgTypeID : char {
4957
Void = 0, // Must be zero.
@@ -1138,15 +1146,15 @@ void TargetLibraryInfoImpl::disableAllFunctions() {
11381146
}
11391147

11401148
static bool compareByScalarFnName(const VecDesc &LHS, const VecDesc &RHS) {
1141-
return LHS.ScalarFnName < RHS.ScalarFnName;
1149+
return LHS.getScalarFnName() < RHS.getScalarFnName();
11421150
}
11431151

11441152
static bool compareByVectorFnName(const VecDesc &LHS, const VecDesc &RHS) {
1145-
return LHS.VectorFnName < RHS.VectorFnName;
1153+
return LHS.getVectorFnName() < RHS.getVectorFnName();
11461154
}
11471155

11481156
static bool compareWithScalarFnName(const VecDesc &LHS, StringRef S) {
1149-
return LHS.ScalarFnName < S;
1157+
return LHS.getScalarFnName() < S;
11501158
}
11511159

11521160
void TargetLibraryInfoImpl::addVectorizableFunctions(ArrayRef<VecDesc> Fns) {
@@ -1203,17 +1211,20 @@ void TargetLibraryInfoImpl::addVectorizableFunctionsFromVecLib(
12031211
case SLEEFGNUABI: {
12041212
const VecDesc VecFuncs_VF2[] = {
12051213
#define TLI_DEFINE_SLEEFGNUABI_VF2_VECFUNCS
1206-
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF) {SCAL, VEC, VF, /* MASK = */ false},
1214+
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) \
1215+
{SCAL, VEC, VF, /* MASK = */ false, VABI_PREFIX},
12071216
#include "llvm/Analysis/VecFuncs.def"
12081217
};
12091218
const VecDesc VecFuncs_VF4[] = {
12101219
#define TLI_DEFINE_SLEEFGNUABI_VF4_VECFUNCS
1211-
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF) {SCAL, VEC, VF, /* MASK = */ false},
1220+
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) \
1221+
{SCAL, VEC, VF, /* MASK = */ false, VABI_PREFIX},
12121222
#include "llvm/Analysis/VecFuncs.def"
12131223
};
12141224
const VecDesc VecFuncs_VFScalable[] = {
12151225
#define TLI_DEFINE_SLEEFGNUABI_SCALABLE_VECFUNCS
1216-
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK) {SCAL, VEC, VF, MASK},
1226+
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \
1227+
{SCAL, VEC, VF, MASK, VABI_PREFIX},
12171228
#include "llvm/Analysis/VecFuncs.def"
12181229
};
12191230

@@ -1232,7 +1243,8 @@ void TargetLibraryInfoImpl::addVectorizableFunctionsFromVecLib(
12321243
case ArmPL: {
12331244
const VecDesc VecFuncs[] = {
12341245
#define TLI_DEFINE_ARMPL_VECFUNCS
1235-
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK) {SCAL, VEC, VF, MASK},
1246+
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \
1247+
{SCAL, VEC, VF, MASK, VABI_PREFIX},
12361248
#include "llvm/Analysis/VecFuncs.def"
12371249
};
12381250

@@ -1258,23 +1270,32 @@ bool TargetLibraryInfoImpl::isFunctionVectorizable(StringRef funcName) const {
12581270

12591271
std::vector<VecDesc>::const_iterator I =
12601272
llvm::lower_bound(VectorDescs, funcName, compareWithScalarFnName);
1261-
return I != VectorDescs.end() && StringRef(I->ScalarFnName) == funcName;
1273+
return I != VectorDescs.end() && StringRef(I->getScalarFnName()) == funcName;
12621274
}
12631275

12641276
StringRef TargetLibraryInfoImpl::getVectorizedFunction(StringRef F,
12651277
const ElementCount &VF,
12661278
bool Masked) const {
1279+
const VecDesc *VD = getVectorMappingInfo(F, VF, Masked);
1280+
if (VD)
1281+
return VD->getVectorFnName();
1282+
return StringRef();
1283+
}
1284+
1285+
const VecDesc *
1286+
TargetLibraryInfoImpl::getVectorMappingInfo(StringRef F, const ElementCount &VF,
1287+
bool Masked) const {
12671288
F = sanitizeFunctionName(F);
12681289
if (F.empty())
1269-
return F;
1290+
return nullptr;
12701291
std::vector<VecDesc>::const_iterator I =
12711292
llvm::lower_bound(VectorDescs, F, compareWithScalarFnName);
1272-
while (I != VectorDescs.end() && StringRef(I->ScalarFnName) == F) {
1273-
if ((I->VectorizationFactor == VF) && (I->Masked == Masked))
1274-
return I->VectorFnName;
1293+
while (I != VectorDescs.end() && StringRef(I->getScalarFnName()) == F) {
1294+
if ((I->getVectorizationFactor() == VF) && (I->isMasked() == Masked))
1295+
return &(*I);
12751296
++I;
12761297
}
1277-
return StringRef();
1298+
return nullptr;
12781299
}
12791300

12801301
TargetLibraryInfo TargetLibraryAnalysis::run(const Function &F,
@@ -1346,11 +1367,11 @@ void TargetLibraryInfoImpl::getWidestVF(StringRef ScalarF,
13461367

13471368
std::vector<VecDesc>::const_iterator I =
13481369
llvm::lower_bound(VectorDescs, ScalarF, compareWithScalarFnName);
1349-
while (I != VectorDescs.end() && StringRef(I->ScalarFnName) == ScalarF) {
1370+
while (I != VectorDescs.end() && StringRef(I->getScalarFnName()) == ScalarF) {
13501371
ElementCount *VF =
1351-
I->VectorizationFactor.isScalable() ? &ScalableVF : &FixedVF;
1352-
if (ElementCount::isKnownGT(I->VectorizationFactor, *VF))
1353-
*VF = I->VectorizationFactor;
1372+
I->getVectorizationFactor().isScalable() ? &ScalableVF : &FixedVF;
1373+
if (ElementCount::isKnownGT(I->getVectorizationFactor(), *VF))
1374+
*VF = I->getVectorizationFactor();
13541375
++I;
13551376
}
13561377
}

llvm/lib/Analysis/VectorUtils.cpp

-16
Original file line numberDiff line numberDiff line change
@@ -1453,22 +1453,6 @@ void InterleaveGroup<Instruction>::addMetadata(Instruction *NewInst) const {
14531453
}
14541454
}
14551455

1456-
std::string VFABI::mangleTLIVectorName(StringRef VectorName,
1457-
StringRef ScalarName, unsigned numArgs,
1458-
ElementCount VF, bool Masked) {
1459-
SmallString<256> Buffer;
1460-
llvm::raw_svector_ostream Out(Buffer);
1461-
Out << "_ZGV" << VFABI::_LLVM_ << (Masked ? "M" : "N");
1462-
if (VF.isScalable())
1463-
Out << 'x';
1464-
else
1465-
Out << VF.getFixedValue();
1466-
for (unsigned I = 0; I < numArgs; ++I)
1467-
Out << "v";
1468-
Out << "_" << ScalarName << "(" << VectorName << ")";
1469-
return std::string(Out.str());
1470-
}
1471-
14721456
void VFABI::getVectorVariantNames(
14731457
const CallInst &CI, SmallVectorImpl<std::string> &VariantMappings) {
14741458
const StringRef S = CI.getFnAttr(VFABI::MappingsAttrName).getValueAsString();

llvm/lib/CodeGen/ReplaceWithVeclib.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,7 @@ static bool replaceWithCallToVeclib(const TargetLibraryInfo &TLI,
155155
// Try to find the mapping for the scalar version of this intrinsic
156156
// and the exact vector width of the call operands in the
157157
// TargetLibraryInfo.
158-
const std::string TLIName =
159-
std::string(TLI.getVectorizedFunction(ScalarName, VF));
158+
StringRef TLIName = TLI.getVectorizedFunction(ScalarName, VF);
160159

161160
LLVM_DEBUG(dbgs() << DEBUG_TYPE << ": Looking up TLI mapping for `"
162161
<< ScalarName << "` and vector width " << VF << ".\n");

llvm/lib/Transforms/Utils/InjectTLIMappings.cpp

+5-7
Original file line numberDiff line numberDiff line change
@@ -91,18 +91,16 @@ static void addMappingsFromTLI(const TargetLibraryInfo &TLI, CallInst &CI) {
9191
Mappings.end());
9292

9393
auto AddVariantDecl = [&](const ElementCount &VF, bool Predicate) {
94-
const std::string TLIName =
95-
std::string(TLI.getVectorizedFunction(ScalarName, VF, Predicate));
96-
if (!TLIName.empty()) {
97-
std::string MangledName = VFABI::mangleTLIVectorName(
98-
TLIName, ScalarName, CI.arg_size(), VF, Predicate);
94+
const VecDesc *VD = TLI.getVectorMappingInfo(ScalarName, VF, Predicate);
95+
if (VD) {
96+
std::string MangledName = VD->getVectorFunctionABIVariantString();
9997
if (!OriginalSetOfMappings.count(MangledName)) {
10098
Mappings.push_back(MangledName);
10199
++NumCallInjected;
102100
}
103-
Function *VariantF = M->getFunction(TLIName);
101+
Function *VariantF = M->getFunction(VD->getVectorFnName());
104102
if (!VariantF)
105-
addVariantDeclaration(CI, VF, Predicate, TLIName);
103+
addVariantDeclaration(CI, VF, Predicate, VD->getVectorFnName());
106104
}
107105
};
108106

llvm/test/Transforms/LoopVectorize/AArch64/veclib-calls-libsystem-darwin.ll

+8-8
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ for.end:
195195
ret void
196196
}
197197

198-
declare float @atan2f(float) nounwind readnone
198+
declare float @atan2f(float, float) nounwind readnone
199199
define void @atan2f_v4f32(i64 %n, ptr noalias %y, ptr noalias %x) {
200200
; CHECK-LABEL: @atan2f_v4f32(
201201
; CHECK: call <4 x float> @_simd_atan2_f4(
@@ -208,7 +208,7 @@ for.body:
208208
%iv = phi i64 [ %iv.next, %for.body ], [ 0, %entry ]
209209
%gep.y = getelementptr inbounds float, ptr %y, i64 %iv
210210
%lv = load float, ptr %gep.y, align 4
211-
%call = tail call float @atan2f(float %lv)
211+
%call = tail call float @atan2f(float %lv, float %lv)
212212
%gep.x = getelementptr inbounds float, ptr %x, i64 %iv
213213
store float %call, ptr %gep.x, align 4
214214
%iv.next = add i64 %iv, 1
@@ -219,7 +219,7 @@ for.end:
219219
ret void
220220
}
221221

222-
declare double @atan2(double) nounwind readnone
222+
declare double @atan2(double, double) nounwind readnone
223223
define void @atan2_v2f64(i64 %n, ptr noalias %y, ptr noalias %x) {
224224
; CHECK-LABEL: @atan2_v2f64(
225225
; CHECK: call <2 x double> @_simd_atan2_d2(
@@ -232,7 +232,7 @@ for.body:
232232
%iv = phi i64 [ %iv.next, %for.body ], [ 0, %entry ]
233233
%gep.y = getelementptr inbounds double, ptr %y, i64 %iv
234234
%lv = load double, ptr %gep.y, align 4
235-
%call = tail call double @atan2(double %lv)
235+
%call = tail call double @atan2(double %lv, double %lv)
236236
%gep.x = getelementptr inbounds double, ptr %x, i64 %iv
237237
store double %call, ptr %gep.x, align 4
238238
%iv.next = add i64 %iv, 1
@@ -387,7 +387,7 @@ for.end:
387387
ret void
388388
}
389389

390-
declare float @powf(float) nounwind readnone
390+
declare float @powf(float, float) nounwind readnone
391391
define void @powf_v4f32(i64 %n, ptr noalias %y, ptr noalias %x) {
392392
; CHECK-LABEL: @powf_v4f32(
393393
; CHECK: call <4 x float> @_simd_pow_f4(
@@ -400,7 +400,7 @@ for.body:
400400
%iv = phi i64 [ %iv.next, %for.body ], [ 0, %entry ]
401401
%gep.y = getelementptr inbounds float, ptr %y, i64 %iv
402402
%lv = load float, ptr %gep.y, align 4
403-
%call = tail call float @powf(float %lv)
403+
%call = tail call float @powf(float %lv, float %lv)
404404
%gep.x = getelementptr inbounds float, ptr %x, i64 %iv
405405
store float %call, ptr %gep.x, align 4
406406
%iv.next = add i64 %iv, 1
@@ -411,7 +411,7 @@ for.end:
411411
ret void
412412
}
413413

414-
declare double @pow(double) nounwind readnone
414+
declare double @pow(double, double) nounwind readnone
415415
define void @pow_v2f64(i64 %n, ptr noalias %y, ptr noalias %x) {
416416
; CHECK-LABEL: @pow_v2f64(
417417
; CHECK: call <2 x double> @_simd_pow_d2(
@@ -424,7 +424,7 @@ for.body:
424424
%iv = phi i64 [ %iv.next, %for.body ], [ 0, %entry ]
425425
%gep.y = getelementptr inbounds double, ptr %y, i64 %iv
426426
%lv = load double, ptr %gep.y, align 4
427-
%call = tail call double @pow(double %lv)
427+
%call = tail call double @pow(double %lv, double %lv)
428428
%gep.x = getelementptr inbounds double, ptr %x, i64 %iv
429429
store double %call, ptr %gep.x, align 4
430430
%iv.next = add i64 %iv, 1

llvm/test/Transforms/LoopVectorize/PowerPC/massv-calls.ll

+4-4
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ declare float @acosf(float) #0
6565
declare double @atan(double) #0
6666
declare float @atanf(float) #0
6767

68-
declare double @atan2(double) #0
69-
declare float @atan2f(float) #0
68+
declare double @atan2(double, double) #0
69+
declare float @atan2f(float, float) #0
7070

7171
declare double @sinh(double) #0
7272
declare float @sinhf(float) #0
@@ -1210,7 +1210,7 @@ for.body:
12101210
%iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
12111211
%tmp = trunc i64 %iv to i32
12121212
%conv = sitofp i32 %tmp to double
1213-
%call = tail call double @atan2(double %conv)
1213+
%call = tail call double @atan2(double %conv, double %conv)
12141214
%arrayidx = getelementptr inbounds double, ptr %varray, i64 %iv
12151215
store double %call, ptr %arrayidx, align 4
12161216
%iv.next = add nuw nsw i64 %iv, 1
@@ -1233,7 +1233,7 @@ for.body:
12331233
%iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
12341234
%tmp = trunc i64 %iv to i32
12351235
%conv = sitofp i32 %tmp to float
1236-
%call = tail call float @atan2f(float %conv)
1236+
%call = tail call float @atan2f(float %conv, float %conv)
12371237
%arrayidx = getelementptr inbounds float, ptr %varray, i64 %iv
12381238
store float %call, ptr %arrayidx, align 4
12391239
%iv.next = add nuw nsw i64 %iv, 1

0 commit comments

Comments
 (0)