Skip to content

Commit 931ea39

Browse files
dlei6gsys_zuul
authored andcommitted
Refactor for function alwaysinline attribute.
Allows testing subroutines/stack-calls/indirect-calls without causing perf issues in default mode. Change-Id: I7695623205fb6660d39df503dd5bf87209d25784
1 parent a0a8f2b commit 931ea39

File tree

1 file changed

+71
-79
lines changed

1 file changed

+71
-79
lines changed

IGC/AdaptorCommon/ProcessFuncAttributes.cpp

Lines changed: 71 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ bool ProcessFuncAttributes::runOnModule(Module& M)
241241
bool Changed = false;
242242
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
243243
{
244-
Function *F = &(*I);
244+
Function* F = &(*I);
245245
if (F->isDeclaration())
246246
{
247247
if (F->getName() == "__translate_sampler_initializer")
@@ -275,32 +275,6 @@ bool ProcessFuncAttributes::runOnModule(Module& M)
275275
// Remove noinline attr if present.
276276
F->removeFnAttr(llvm::Attribute::NoInline);
277277

278-
if (IGC_IS_FLAG_ENABLED(DisableAddingAlwaysAttribute))
279-
{
280-
// Add always attribute if function has an argument with opaque type
281-
// Curently, ExtensionArgAnalysis assumes that all functions with image arguments to be inlined
282-
// This patch makes sure that we add always inline for such cases
283-
for (auto& arg : F->args())
284-
{
285-
if (containsOpaque(arg.getType()))
286-
{
287-
F->addFnAttr(llvm::Attribute::AlwaysInline);
288-
break;
289-
}
290-
}
291-
292-
// Add always attribtue if function is a builtin
293-
if (F->hasFnAttribute(llvm::Attribute::Builtin))
294-
{
295-
F->addFnAttr(llvm::Attribute::AlwaysInline);
296-
}
297-
}
298-
else
299-
{
300-
// Add AlwaysInline attribute to force inlining all calls.
301-
F->addFnAttr(llvm::Attribute::AlwaysInline);
302-
}
303-
304278
// Go through call sites and remove NoInline atrributes.
305279
for (auto I : F->users()) {
306280
if (CallInst* callInst = dyn_cast<CallInst>(&*I)) {
@@ -314,7 +288,7 @@ bool ProcessFuncAttributes::runOnModule(Module& M)
314288
// inliner doesn't conservatively turn off unsafe optimizations
315289
// when inlining BIFs (see mergeAttributesForInlining() in inliner).
316290

317-
const auto &opts = modMD->compOpt;
291+
const auto& opts = modMD->compOpt;
318292

319293
if (opts.MadEnable)
320294
F->addFnAttr("less-precise-fpmad", "true");
@@ -330,82 +304,100 @@ bool ProcessFuncAttributes::runOnModule(Module& M)
330304

331305
// F is not a kernel
332306
// it is builtin, or user function
333-
const bool notKernel = pMdUtils->findFunctionsInfoItem(F) == pMdUtils->end_FunctionsInfo();
307+
const bool notKernel = pMdUtils->findFunctionsInfoItem(F) == pMdUtils->end_FunctionsInfo();
334308

335309
if (notKernel)
336310
{
337311
F->setLinkage(GlobalValue::InternalLinkage);
338312
Changed = true;
339313
}
340314

315+
// Add Optnone to user functions but not on builtins. This allows to run
316+
// optimizations on builtins.
317+
if (getAnalysis<MetaDataUtilsWrapper>().getModuleMetaData()->compOpt.OptDisable)
318+
{
319+
if (!F->hasFnAttribute(llvm::Attribute::Builtin))
320+
{
321+
F->addFnAttr(llvm::Attribute::OptimizeNone);
322+
}
323+
}
324+
325+
// Flag for function calls where alwaysinline must be true
326+
bool mustAlwaysInline = false;
327+
328+
// Add always attribute if function has an argument with opaque type
329+
for (auto& arg : F->args())
330+
{
331+
if (containsOpaque(arg.getType()))
332+
{
333+
mustAlwaysInline = true;
334+
break;
335+
}
336+
}
337+
// Add always attribtue if function is a builtin
338+
if (F->hasFnAttribute(llvm::Attribute::Builtin) ||
339+
F->getName().startswith(spv::kLLVMName::builtinPrefix))
340+
{
341+
mustAlwaysInline = true;
342+
}
341343
// inline all OCL math functions if __FastRelaxedMath is set
342-
if (fastMathFunct.find(F) != fastMathFunct.end()) continue;
344+
else if (fastMathFunct.find(F) != fastMathFunct.end())
345+
{
346+
mustAlwaysInline = true;
347+
}
348+
if (mustAlwaysInline)
349+
{
350+
F->addFnAttr(llvm::Attribute::AlwaysInline);
351+
Changed = true;
352+
continue;
353+
}
343354

344-
// The following subroutine check is added to disable two-phase-inlining
345-
// when we do not enable subroutines.
346-
bool keepAlwaysInline = (MemPoolFuncs.count(F) != 0);
347-
if (IGC_GET_FLAG_VALUE(FunctionControl) != FLAG_FCALL_FORCE_INLINE)
355+
if (IGC_GET_FLAG_VALUE(FunctionControl) == FLAG_FCALL_DEFAULT)
348356
{
349-
if (!keepAlwaysInline)
357+
// Set default inline mode
358+
if (IGC_IS_FLAG_DISABLED(DisableAddingAlwaysAttribute))
350359
{
351-
for (auto &arg : F->args())
360+
bool shouldAlwaysInline = (MemPoolFuncs.count(F) != 0);
361+
if (!shouldAlwaysInline)
352362
{
353-
// If argument contains an opaque type e.g. image, then always inline it.
354-
// If argument is a pointer to GAS, always inline it for perf reason.
355-
//
356-
// Note that this workaround should be removed.
357-
if (containsOpaque(arg.getType()) || isSupportedAggregateArgument(&arg) ||
358-
isGASPointer(&arg))
363+
for (auto& arg : F->args())
359364
{
360-
keepAlwaysInline = true;
361-
break;
365+
// If argument is a pointer to GAS or aggregate type, always inline it for perf reasons
366+
if (isSupportedAggregateArgument(&arg) || isGASPointer(&arg))
367+
{
368+
shouldAlwaysInline = true;
369+
break;
370+
}
362371
}
363372
}
364-
365-
// SPIR-V image functions don't contain opaque types for images,
366-
// they use i64 values instead.
367-
// We need to detect them based on function name.
368-
if (F->getName().startswith(spv::kLLVMName::builtinPrefix) &&
369-
F->getName().contains("Image")) {
370-
keepAlwaysInline = true;
373+
if (shouldAlwaysInline)
374+
{
375+
F->addFnAttr(llvm::Attribute::AlwaysInline);
371376
}
372377
}
373-
374-
if (!keepAlwaysInline)
375-
{
376-
F->removeFnAttr(llvm::Attribute::AlwaysInline);
377-
}
378378
}
379-
380-
// Add Optnone to user functions but not on builtins. This allows to run
381-
// optimizations on builtins.
382-
if (getAnalysis<MetaDataUtilsWrapper>().getModuleMetaData()->compOpt.OptDisable)
379+
else if (IGC_GET_FLAG_VALUE(FunctionControl) == FLAG_FCALL_FORCE_INLINE)
383380
{
384-
if (!F->hasFnAttribute(llvm::Attribute::Builtin))
385-
{
386-
F->addFnAttr(llvm::Attribute::OptimizeNone);
387-
}
381+
// Forced inlining all functions
382+
F->addFnAttr(llvm::Attribute::AlwaysInline);
388383
}
389384

390385
bool istrue = false;
386+
// Forcing subroutines/stack-call/indirect-call
387+
// Do not add alwaysinline
391388
if (notKernel || istrue)
392389
{
393-
if (!keepAlwaysInline)
390+
bool forceSubroutine = IGC_GET_FLAG_VALUE(FunctionControl) == FLAG_FCALL_FORCE_SUBROUTINE;
391+
bool forceStackCall = IGC_GET_FLAG_VALUE(FunctionControl) == FLAG_FCALL_FORCE_STACKCALL;
392+
if ((forceSubroutine || forceStackCall) && (istrue == false))
394393
{
395-
bool forceSubroutine = IGC_GET_FLAG_VALUE(FunctionControl) == FLAG_FCALL_FORCE_SUBROUTINE;
396-
bool forceStackCall = IGC_GET_FLAG_VALUE(FunctionControl) == FLAG_FCALL_FORCE_STACKCALL;
397-
398-
if ((forceSubroutine || forceStackCall) && (istrue == false))
394+
F->removeFnAttr(llvm::Attribute::AlwaysInline);
395+
F->addFnAttr(llvm::Attribute::NoInline);
396+
if (forceStackCall)
399397
{
400-
// add the following line in order to stress-test
401-
// subroutine call or stack call
402-
F->removeFnAttr(llvm::Attribute::AlwaysInline);
403-
F->addFnAttr(llvm::Attribute::NoInline);
404-
if (forceStackCall)
405-
{
406-
F->addFnAttr("visaStackCall");
407-
}
398+
F->addFnAttr("visaStackCall");
408399
}
400+
Changed = true;
409401
}
410402

411403
if (IGC_IS_FLAG_ENABLED(EnableFunctionPointer))
@@ -430,17 +422,17 @@ bool ProcessFuncAttributes::runOnModule(Module& M)
430422
pCtx->m_enableFunctionPointer = true;
431423
SetIndirectFuncAttributes(F);
432424

433-
if(istrue)
425+
if (istrue)
434426
F->removeFnAttr("visaStackCall");
435427

436428
if (isExtern)
437429
{
438430
F->setLinkage(GlobalValue::ExternalLinkage);
439431
}
432+
Changed = true;
440433
}
441434
}
442435
}
443-
Changed = true;
444436
}
445437
return Changed;
446438
}

0 commit comments

Comments
 (0)