Skip to content

Commit 60c642e

Browse files
committed
[TLI] Per-function fveclib for math library used for vectorization
Summary: Encode `-fveclib` setting as per-function attribute so it can threaded through to LTO backends. Accordingly per-function TLI now reads the attributes and select available vector function list based on that. Now we also populate function list for all supported vector libraries for the shared per-module `TargetLibraryInfoImpl`, so each function can select its available vector list independently but without duplicating the vector function lists. Inlining between incompatbile vectlib attributed is also prohibited now. Subscribers: hiraditya, dexonsmith, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D77632
1 parent 5b18b6e commit 60c642e

File tree

8 files changed

+250
-120
lines changed

8 files changed

+250
-120
lines changed

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -352,24 +352,8 @@ static void addMemTagOptimizationPasses(const PassManagerBuilder &Builder,
352352
PM.add(createStackSafetyGlobalInfoWrapperPass(/*SetMetadata=*/true));
353353
}
354354

355-
static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple,
356-
const CodeGenOptions &CodeGenOpts) {
357-
TargetLibraryInfoImpl *TLII = new TargetLibraryInfoImpl(TargetTriple);
358-
359-
switch (CodeGenOpts.getVecLib()) {
360-
case CodeGenOptions::Accelerate:
361-
TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::Accelerate);
362-
break;
363-
case CodeGenOptions::MASSV:
364-
TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::MASSV);
365-
break;
366-
case CodeGenOptions::SVML:
367-
TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::SVML);
368-
break;
369-
default:
370-
break;
371-
}
372-
return TLII;
355+
static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple) {
356+
return new TargetLibraryInfoImpl(TargetTriple);
373357
}
374358

375359
static void addSymbolRewriterPass(const CodeGenOptions &Opts,
@@ -562,8 +546,7 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
562546
// are inserted before PMBuilder ones - they'd get the default-constructed
563547
// TLI with an unknown target otherwise.
564548
Triple TargetTriple(TheModule->getTargetTriple());
565-
std::unique_ptr<TargetLibraryInfoImpl> TLII(
566-
createTLII(TargetTriple, CodeGenOpts));
549+
std::unique_ptr<TargetLibraryInfoImpl> TLII(createTLII(TargetTriple));
567550

568551
// If we reached here with a non-empty index file name, then the index file
569552
// was empty and we are not performing ThinLTO backend compilation (used in
@@ -805,8 +788,7 @@ bool EmitAssemblyHelper::AddEmitPasses(legacy::PassManager &CodeGenPasses,
805788
raw_pwrite_stream *DwoOS) {
806789
// Add LibraryInfo.
807790
llvm::Triple TargetTriple(TheModule->getTargetTriple());
808-
std::unique_ptr<TargetLibraryInfoImpl> TLII(
809-
createTLII(TargetTriple, CodeGenOpts));
791+
std::unique_ptr<TargetLibraryInfoImpl> TLII(createTLII(TargetTriple));
810792
CodeGenPasses.add(new TargetLibraryInfoWrapperPass(*TLII));
811793

812794
// Normal mode, emit a .s or .o file by running the code generator. Note,
@@ -1142,8 +1124,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
11421124
// Register the target library analysis directly and give it a customized
11431125
// preset TLI.
11441126
Triple TargetTriple(TheModule->getTargetTriple());
1145-
std::unique_ptr<TargetLibraryInfoImpl> TLII(
1146-
createTLII(TargetTriple, CodeGenOpts));
1127+
std::unique_ptr<TargetLibraryInfoImpl> TLII(createTLII(TargetTriple));
11471128
FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
11481129

11491130
// Register all the basic analyses with the managers.

clang/lib/CodeGen/CGCall.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1868,6 +1868,24 @@ static void addNoBuiltinAttributes(llvm::AttrBuilder &FuncAttrs,
18681868
llvm::for_each(NBA->builtinNames(), AddNoBuiltinAttr);
18691869
}
18701870

1871+
static void addVectLibAttributes(llvm::AttrBuilder &FuncAttrs,
1872+
const CodeGenOptions &CodeGenOpts) {
1873+
StringRef AttributeName = "veclib";
1874+
switch (CodeGenOpts.getVecLib()) {
1875+
case CodeGenOptions::Accelerate:
1876+
FuncAttrs.addAttribute(AttributeName, "Accelerate");
1877+
break;
1878+
case CodeGenOptions::MASSV:
1879+
FuncAttrs.addAttribute(AttributeName, "MASSV");
1880+
break;
1881+
case CodeGenOptions::SVML:
1882+
FuncAttrs.addAttribute(AttributeName, "SVML");
1883+
break;
1884+
case CodeGenOptions::NoLibrary:
1885+
break;
1886+
}
1887+
}
1888+
18711889
void CodeGenModule::ConstructAttributeList(
18721890
StringRef Name, const CGFunctionInfo &FI, CGCalleeInfo CalleeInfo,
18731891
llvm::AttributeList &AttrList, unsigned &CallingConv, bool AttrOnCallSite) {
@@ -1966,6 +1984,9 @@ void CodeGenModule::ConstructAttributeList(
19661984
// * FunctionDecl attributes: __attribute__((no_builtin(...)))
19671985
addNoBuiltinAttributes(FuncAttrs, getLangOpts(), NBA);
19681986

1987+
// Attach "veclib" attribute to function based on '-fveclib' setting.
1988+
addVectLibAttributes(FuncAttrs, getCodeGenOpts());
1989+
19691990
ConstructDefaultFnAttrList(Name, HasOptnone, AttrOnCallSite, FuncAttrs);
19701991

19711992
// This must run after constructing the default function attribute list
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %clang_cc1 -S -emit-llvm -fveclib=SVML -o - %s | FileCheck --check-prefixes=SVML %s
2+
// RUN: %clang_cc1 -S -emit-llvm -fveclib=Accelerate -o - %s | FileCheck --check-prefixes=ACCELERATE %s
3+
// RUN: %clang_cc1 -S -emit-llvm -fveclib=MASSV -o - %s | FileCheck --check-prefixes=MASSV %s
4+
// RUN: %clang_cc1 -S -emit-llvm -fveclib=none -o - %s | FileCheck --check-prefixes=NOLIB %s
5+
// RUN: %clang_cc1 -S -emit-llvm -o - %s | FileCheck --check-prefixes=NOLIB %s
6+
7+
int main() {
8+
return 0;
9+
}
10+
11+
// SVML: "veclib"="SVML"
12+
// ACCELERATE: "veclib"="Accelerate"
13+
// MASSV: "veclib"="MASSV"
14+
// NOLIB-NOT: "veclib"

llvm/include/llvm/Analysis/TargetLibraryInfo.h

Lines changed: 86 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,23 @@ struct VecDesc {
4848
class TargetLibraryInfoImpl {
4949
friend class TargetLibraryInfo;
5050

51+
public:
52+
/// List of known vector-functions libraries.
53+
///
54+
/// The vector-functions library defines, which functions are vectorizable
55+
/// and with which factor. The library can be specified by either frontend,
56+
/// or a commandline option, and then used by
57+
/// addVectorizableFunctionsFromVecLib for filling up the tables of
58+
/// vectorizable functions.
59+
enum VectorLibrary {
60+
Accelerate, // Use Accelerate framework.
61+
MASSV, // IBM MASS vector library.
62+
SVML, // Intel short vector math library.
63+
NumVecLibs, // Number of supported vector libraries.
64+
NoLibrary // Don't use any vector library.
65+
};
66+
67+
private:
5168
unsigned char AvailableArray[(NumLibFuncs+3)/4];
5269
llvm::DenseMap<unsigned, std::string> CustomNames;
5370
static StringLiteral const StandardNames[NumLibFuncs];
@@ -66,32 +83,31 @@ class TargetLibraryInfoImpl {
6683
return static_cast<AvailabilityState>((AvailableArray[F/4] >> 2*(F&3)) & 3);
6784
}
6885

69-
/// Vectorization descriptors - sorted by ScalarFnName.
70-
std::vector<VecDesc> VectorDescs;
71-
/// Scalarization descriptors - same content as VectorDescs but sorted based
72-
/// on VectorFnName rather than ScalarFnName.
73-
std::vector<VecDesc> ScalarDescs;
86+
/// Vector library descriptor for all supported ones.
87+
struct VectorLibraryDescriptors {
88+
/// Vectorization descriptors - sorted by ScalarFnName.
89+
std::vector<VecDesc> VectorDescs;
90+
/// Scalarization descriptors - same content as VectorDescs but sorted based
91+
/// on VectorFnName rather than ScalarFnName.
92+
std::vector<VecDesc> ScalarDescs;
93+
} VecLibDescs[NumVecLibs];
7494

7595
/// Return true if the function type FTy is valid for the library function
7696
/// F, regardless of whether the function is available.
7797
bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc F,
7898
const DataLayout *DL) const;
7999

80-
public:
81-
/// List of known vector-functions libraries.
82-
///
83-
/// The vector-functions library defines, which functions are vectorizable
84-
/// and with which factor. The library can be specified by either frontend,
85-
/// or a commandline option, and then used by
86-
/// addVectorizableFunctionsFromVecLib for filling up the tables of
87-
/// vectorizable functions.
88-
enum VectorLibrary {
89-
NoLibrary, // Don't use any vector library.
90-
Accelerate, // Use Accelerate framework.
91-
MASSV, // IBM MASS vector library.
92-
SVML // Intel short vector math library.
93-
};
100+
/// Add a set of scalar -> vector mappings, queryable via
101+
/// getVectorizedFunction and getScalarizedFunction.
102+
void addVectorizableFunctions(ArrayRef<VecDesc> Fns,
103+
VectorLibraryDescriptors &VetLibDescs);
94104

105+
/// Calls addVectorizableFunctionsFromVecLib with a known preset of functions
106+
/// for the given vector library.
107+
void addVectorizableFunctionsFromVecLib(enum VectorLibrary VecLib,
108+
VectorLibraryDescriptors &VetLibDesc);
109+
110+
public:
95111
TargetLibraryInfoImpl();
96112
explicit TargetLibraryInfoImpl(const Triple &T);
97113

@@ -141,39 +157,38 @@ class TargetLibraryInfoImpl {
141157
/// This can be used for options like -fno-builtin.
142158
void disableAllFunctions();
143159

144-
/// Add a set of scalar -> vector mappings, queryable via
145-
/// getVectorizedFunction and getScalarizedFunction.
146-
void addVectorizableFunctions(ArrayRef<VecDesc> Fns);
147-
148-
/// Calls addVectorizableFunctions with a known preset of functions for the
149-
/// given vector library.
150-
void addVectorizableFunctionsFromVecLib(enum VectorLibrary VecLib);
160+
/// Populate VectorLibraryDescriptors for all supported vector libraries.
161+
void addAllVectorizableFunctions();
151162

152163
/// Return true if the function F has a vector equivalent with vectorization
153164
/// factor VF.
154-
bool isFunctionVectorizable(StringRef F, unsigned VF) const {
155-
return !getVectorizedFunction(F, VF).empty();
165+
bool isFunctionVectorizable(StringRef F, unsigned VF,
166+
VectorLibrary vecLib) const {
167+
return !getVectorizedFunction(F, VF, vecLib).empty();
156168
}
157169

158170
/// Return true if the function F has a vector equivalent with any
159171
/// vectorization factor.
160-
bool isFunctionVectorizable(StringRef F) const;
172+
bool isFunctionVectorizable(StringRef F, VectorLibrary vecLib) const;
161173

162174
/// Return the name of the equivalent of F, vectorized with factor VF. If no
163175
/// such mapping exists, return the empty string.
164-
StringRef getVectorizedFunction(StringRef F, unsigned VF) const;
176+
StringRef getVectorizedFunction(StringRef F, unsigned VF,
177+
VectorLibrary vecLib) const;
165178

166179
/// Return true if the function F has a scalar equivalent, and set VF to be
167180
/// the vectorization factor.
168-
bool isFunctionScalarizable(StringRef F, unsigned &VF) const {
169-
return !getScalarizedFunction(F, VF).empty();
181+
bool isFunctionScalarizable(StringRef F, unsigned &VF,
182+
VectorLibrary vecLib) const {
183+
return !getScalarizedFunction(F, VF, vecLib).empty();
170184
}
171185

172186
/// Return the name of the equivalent of F, scalarized. If no such mapping
173187
/// exists, return the empty string.
174188
///
175189
/// Set VF to the vectorization factor.
176-
StringRef getScalarizedFunction(StringRef F, unsigned &VF) const;
190+
StringRef getScalarizedFunction(StringRef F, unsigned &VF,
191+
VectorLibrary vecLib) const;
177192

178193
/// Set to true iff i32 parameters to library functions should have signext
179194
/// or zeroext attributes if they correspond to C-level int or unsigned int,
@@ -201,7 +216,7 @@ class TargetLibraryInfoImpl {
201216

202217
/// Returns the largest vectorization factor used in the list of
203218
/// vector functions.
204-
unsigned getWidestVF(StringRef ScalarF) const;
219+
unsigned getWidestVF(StringRef ScalarF, VectorLibrary vecLib) const;
205220
};
206221

207222
/// Provides information about what library functions are available for
@@ -216,63 +231,66 @@ class TargetLibraryInfo {
216231
/// The global (module level) TLI info.
217232
const TargetLibraryInfoImpl *Impl;
218233

234+
/// Vector library available for vectorization.
235+
TargetLibraryInfoImpl::VectorLibrary VectLibrary =
236+
TargetLibraryInfoImpl::NoLibrary;
237+
219238
/// Support for -fno-builtin* options as function attributes, overrides
220239
/// information in global TargetLibraryInfoImpl.
221240
BitVector OverrideAsUnavailable;
222241

242+
TargetLibraryInfoImpl::VectorLibrary
243+
getVecLibFromName(const StringRef &VecLibName) {
244+
if (VecLibName == "Accelerate")
245+
return TargetLibraryInfoImpl::Accelerate;
246+
else if (VecLibName == "MASSV")
247+
return TargetLibraryInfoImpl::MASSV;
248+
else if (VecLibName == "SVML")
249+
return TargetLibraryInfoImpl::SVML;
250+
return TargetLibraryInfoImpl::NoLibrary;
251+
}
252+
223253
public:
224254
explicit TargetLibraryInfo(const TargetLibraryInfoImpl &Impl,
225-
Optional<const Function *> F = None)
226-
: Impl(&Impl), OverrideAsUnavailable(NumLibFuncs) {
227-
if (!F)
228-
return;
229-
if ((*F)->hasFnAttribute("no-builtins"))
230-
disableAllFunctions();
231-
else {
232-
// Disable individual libc/libm calls in TargetLibraryInfo.
233-
LibFunc LF;
234-
AttributeSet FnAttrs = (*F)->getAttributes().getFnAttributes();
235-
for (const Attribute &Attr : FnAttrs) {
236-
if (!Attr.isStringAttribute())
237-
continue;
238-
auto AttrStr = Attr.getKindAsString();
239-
if (!AttrStr.consume_front("no-builtin-"))
240-
continue;
241-
if (getLibFunc(AttrStr, LF))
242-
setUnavailable(LF);
243-
}
244-
}
245-
}
255+
Optional<const Function *> F = None);
246256

247257
// Provide value semantics.
248258
TargetLibraryInfo(const TargetLibraryInfo &TLI)
249-
: Impl(TLI.Impl), OverrideAsUnavailable(TLI.OverrideAsUnavailable) {}
259+
: Impl(TLI.Impl), VectLibrary(TLI.VectLibrary),
260+
OverrideAsUnavailable(TLI.OverrideAsUnavailable) {}
250261
TargetLibraryInfo(TargetLibraryInfo &&TLI)
251-
: Impl(TLI.Impl), OverrideAsUnavailable(TLI.OverrideAsUnavailable) {}
262+
: Impl(TLI.Impl), VectLibrary(TLI.VectLibrary),
263+
OverrideAsUnavailable(TLI.OverrideAsUnavailable) {}
252264
TargetLibraryInfo &operator=(const TargetLibraryInfo &TLI) {
253265
Impl = TLI.Impl;
266+
VectLibrary = TLI.VectLibrary;
254267
OverrideAsUnavailable = TLI.OverrideAsUnavailable;
255268
return *this;
256269
}
257270
TargetLibraryInfo &operator=(TargetLibraryInfo &&TLI) {
258271
Impl = TLI.Impl;
272+
VectLibrary = TLI.VectLibrary;
259273
OverrideAsUnavailable = TLI.OverrideAsUnavailable;
260274
return *this;
261275
}
262276

263277
/// Determine whether a callee with the given TLI can be inlined into
264-
/// caller with this TLI, based on 'nobuiltin' attributes. When requested,
265-
/// allow inlining into a caller with a superset of the callee's nobuiltin
266-
/// attributes, which is conservatively correct.
278+
/// caller with this TLI, based on 'nobuiltin', `veclib` attributes.
279+
/// When requested, allow inlining into a caller with a superset of the
280+
/// callee's attributes, which is conservatively correct.
267281
bool areInlineCompatible(const TargetLibraryInfo &CalleeTLI,
268282
bool AllowCallerSuperset) const {
269283
if (!AllowCallerSuperset)
270-
return OverrideAsUnavailable == CalleeTLI.OverrideAsUnavailable;
284+
return VectLibrary == CalleeTLI.VectLibrary &&
285+
OverrideAsUnavailable == CalleeTLI.OverrideAsUnavailable;
271286
BitVector B = OverrideAsUnavailable;
272287
B |= CalleeTLI.OverrideAsUnavailable;
273-
// We can inline if the union of the caller and callee's nobuiltin
274-
// attributes is no stricter than the caller's nobuiltin attributes.
275-
return B == OverrideAsUnavailable;
288+
// We can inline if the union of the caller and callee's attributes
289+
// is no stricter than the caller's attributes.
290+
bool VecLibCompatible =
291+
(VectLibrary == CalleeTLI.VectLibrary) ||
292+
CalleeTLI.VectLibrary == TargetLibraryInfoImpl::NoLibrary;
293+
return B == OverrideAsUnavailable && VecLibCompatible;
276294
}
277295

278296
/// Searches for a particular function name.
@@ -317,13 +335,13 @@ class TargetLibraryInfo {
317335
return getState(F) != TargetLibraryInfoImpl::Unavailable;
318336
}
319337
bool isFunctionVectorizable(StringRef F, unsigned VF) const {
320-
return Impl->isFunctionVectorizable(F, VF);
338+
return Impl->isFunctionVectorizable(F, VF, VectLibrary);
321339
}
322340
bool isFunctionVectorizable(StringRef F) const {
323-
return Impl->isFunctionVectorizable(F);
341+
return Impl->isFunctionVectorizable(F, VectLibrary);
324342
}
325343
StringRef getVectorizedFunction(StringRef F, unsigned VF) const {
326-
return Impl->getVectorizedFunction(F, VF);
344+
return Impl->getVectorizedFunction(F, VF, VectLibrary);
327345
}
328346

329347
/// Tests if the function is both available and a candidate for optimized code
@@ -408,7 +426,7 @@ class TargetLibraryInfo {
408426
/// Returns the largest vectorization factor used in the list of
409427
/// vector functions.
410428
unsigned getWidestVF(StringRef ScalarF) const {
411-
return Impl->getWidestVF(ScalarF);
429+
return Impl->getWidestVF(ScalarF, VectLibrary);
412430
}
413431

414432
/// Check if the function "F" is listed in a library known to LLVM.

llvm/lib/Analysis/InlineCost.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,9 @@ static cl::opt<bool> OptComputeFullInlineCost(
104104
cl::desc("Compute the full inline cost of a call site even when the cost "
105105
"exceeds the threshold."));
106106

107-
static cl::opt<bool> InlineCallerSupersetNoBuiltin(
108-
"inline-caller-superset-nobuiltin", cl::Hidden, cl::init(true),
109-
cl::ZeroOrMore,
110-
cl::desc("Allow inlining when caller has a superset of callee's nobuiltin "
107+
static cl::opt<bool> InlineCallerSupersetTLI(
108+
"inline-caller-superset-tli", cl::Hidden, cl::init(true), cl::ZeroOrMore,
109+
cl::desc("Allow inlining when caller has a superset of callee's TLI "
111110
"attributes."));
112111

113112
namespace {
@@ -2169,7 +2168,7 @@ static bool functionsHaveCompatibleAttributes(
21692168
auto CalleeTLI = GetTLI(*Callee);
21702169
return TTI.areInlineCompatible(Caller, Callee) &&
21712170
GetTLI(*Caller).areInlineCompatible(CalleeTLI,
2172-
InlineCallerSupersetNoBuiltin) &&
2171+
InlineCallerSupersetTLI) &&
21732172
AttributeFuncs::areInlineCompatible(*Caller, *Callee);
21742173
}
21752174

0 commit comments

Comments
 (0)