@@ -233,6 +233,22 @@ bool ProcessFuncAttributes::runOnModule(Module& M)
233
233
// It is not a defined function
234
234
continue ;
235
235
}
236
+
237
+ // If EnableOCLNoInlineAttr is on and F does have
238
+ // NoInline, do not reset it.
239
+ if (IGC_IS_FLAG_ENABLED (EnableOCLNoInlineAttr) &&
240
+ pCtx->type == ShaderType::OPENCL_SHADER &&
241
+ F->hasFnAttribute (llvm::Attribute::NoInline) &&
242
+ !F->hasFnAttribute (llvm::Attribute::Builtin))
243
+ {
244
+ continue ;
245
+ }
246
+
247
+ // Remove noinline attr if present.
248
+ F->removeFnAttr (llvm::Attribute::NoInline);
249
+
250
+ // Add AlwaysInline attribute to force inlining all calls.
251
+ F->addFnAttr (llvm::Attribute::AlwaysInline);
236
252
237
253
// Go through call sites and remove NoInline atrributes.
238
254
for (auto I : F->users ()) {
@@ -271,67 +287,86 @@ bool ProcessFuncAttributes::runOnModule(Module& M)
271
287
Changed = true ;
272
288
}
273
289
274
- // Always try inline unless we find reasons not to
275
- F->addFnAttr (llvm::Attribute::AlwaysInline);
276
-
277
290
// inline all OCL math functions if __FastRelaxedMath is set
278
- // Always inline builtins by default for now
279
- if ((IGC_GET_FLAG_VALUE (FunctionControl) == FLAG_FCALL_FORCE_INLINE) ||
280
- (fastMathFunct.find (F) != fastMathFunct.end ()) ||
281
- (F->hasFnAttribute (llvm::Attribute::Builtin)))
282
- {
283
- F->removeFnAttr (llvm::Attribute::NoInline);
284
- continue ;
285
- }
286
-
287
- bool keepAlwaysInline = true ;
288
-
289
- // Honor noinline attribute
290
- if (F->hasFnAttribute (llvm::Attribute::NoInline))
291
- keepAlwaysInline = false ;
291
+ if (fastMathFunct.find (F) != fastMathFunct.end ()) continue ;
292
292
293
- // Force inline mempool funcs
294
- if (!keepAlwaysInline && MemPoolFuncs.count (F) != 0 )
295
- keepAlwaysInline = true ;
296
-
297
- if (!keepAlwaysInline)
293
+ // The following subroutine check is added to disable two-phase-inlining
294
+ // when we do not enable subroutines.
295
+ bool keepAlwaysInline = (MemPoolFuncs.count (F) != 0 );
296
+ if (IGC_GET_FLAG_VALUE (FunctionControl) != FLAG_FCALL_FORCE_INLINE)
298
297
{
299
- for (auto &arg : F->args ())
298
+ // keep inline if function pointers not enabled and there are uses
299
+ // for function pointers other than call instructions
300
+ if (IGC_IS_FLAG_DISABLED (EnableFunctionPointer) && !keepAlwaysInline)
300
301
{
301
- // If argument contains an opaque type e.g. image, then always inline it.
302
- // If argument is a pointer to GAS, always inline it for perf reason.
303
- //
304
- // Note that this workaround should be removed.
305
- if (containsOpaque (arg.getType ()) || isSupportedAggregateArgument (&arg) ||
306
- isGASPointer (&arg))
302
+ for (auto U : F->users ())
307
303
{
308
- keepAlwaysInline = true ;
309
- break ;
304
+ if (!isa<CallInst>(U))
305
+ {
306
+ keepAlwaysInline = true ;
307
+ break ;
308
+ }
310
309
}
311
310
}
312
311
313
- // SPIR-V image functions don't contain opaque types for images,
314
- // they use i64 values instead.
315
- // We need to detect them based on function name.
316
- if (F->getName ().startswith (spv::kLLVMName ::builtinPrefix) &&
317
- F->getName ().contains (" Image" )) {
318
- keepAlwaysInline = true ;
312
+ if (!keepAlwaysInline)
313
+ {
314
+ for (auto &arg : F->args ())
315
+ {
316
+ // If argument contains an opaque type e.g. image, then always inline it.
317
+ // If argument is a pointer to GAS, always inline it for perf reason.
318
+ //
319
+ // Note that this workaround should be removed.
320
+ if (containsOpaque (arg.getType ()) || isSupportedAggregateArgument (&arg) ||
321
+ isGASPointer (&arg))
322
+ {
323
+ keepAlwaysInline = true ;
324
+ break ;
325
+ }
326
+ }
327
+
328
+ // SPIR-V image functions don't contain opaque types for images,
329
+ // they use i64 values instead.
330
+ // We need to detect them based on function name.
331
+ if (F->getName ().startswith (spv::kLLVMName ::builtinPrefix) &&
332
+ F->getName ().contains (" Image" )) {
333
+ keepAlwaysInline = true ;
334
+ }
335
+ }
336
+
337
+ if (!keepAlwaysInline)
338
+ {
339
+ F->removeFnAttr (llvm::Attribute::AlwaysInline);
340
+ }
341
+ }
342
+
343
+ // Add Optnone to user functions but not on builtins. This allows to run
344
+ // optimizations on builtins.
345
+ if (getAnalysis<MetaDataUtilsWrapper>().getModuleMetaData ()->compOpt .OptDisable )
346
+ {
347
+ if (!F->hasFnAttribute (llvm::Attribute::Builtin))
348
+ {
349
+ F->addFnAttr (llvm::Attribute::OptimizeNone);
319
350
}
320
351
}
321
352
322
353
if (notKernel)
323
354
{
324
- bool forceSubroutine = IGC_GET_FLAG_VALUE (FunctionControl) == FLAG_FCALL_FORCE_SUBROUTINE;
325
- bool forceStackCall = IGC_GET_FLAG_VALUE (FunctionControl) == FLAG_FCALL_FORCE_STACKCALL;
326
- if (forceSubroutine || forceStackCall)
355
+ if (!keepAlwaysInline)
327
356
{
328
- // add the following line in order to stress-test
329
- // subroutine call or stack call
330
- F->addFnAttr (llvm::Attribute::NoInline);
331
- keepAlwaysInline = false ;
332
- if (forceStackCall)
357
+ bool forceSubroutine = IGC_GET_FLAG_VALUE (FunctionControl) == FLAG_FCALL_FORCE_SUBROUTINE;
358
+ bool forceStackCall = IGC_GET_FLAG_VALUE (FunctionControl) == FLAG_FCALL_FORCE_STACKCALL;
359
+
360
+ if (forceSubroutine || forceStackCall)
333
361
{
334
- F->addFnAttr (" visaStackCall" );
362
+ // add the following line in order to stress-test
363
+ // subroutine call or stack call
364
+ F->removeFnAttr (llvm::Attribute::AlwaysInline);
365
+ F->addFnAttr (llvm::Attribute::NoInline);
366
+ if (forceStackCall)
367
+ {
368
+ F->addFnAttr (" visaStackCall" );
369
+ }
335
370
}
336
371
}
337
372
@@ -352,29 +387,14 @@ bool ProcessFuncAttributes::runOnModule(Module& M)
352
387
}
353
388
}
354
389
if (isIndirect)
355
- {
390
+ {
356
391
pCtx->m_enableFunctionPointer = true ;
392
+ pCtx->m_enableSubroutine = false ;
357
393
F->addFnAttr (" AsFunctionPointer" );
358
394
F->addFnAttr (" visaStackCall" );
359
395
}
360
396
}
361
397
}
362
-
363
- if (keepAlwaysInline)
364
- {
365
- F->removeFnAttr (llvm::Attribute::NoInline);
366
- }
367
- else
368
- {
369
- F->removeFnAttr (llvm::Attribute::AlwaysInline);
370
- }
371
-
372
- // Add Optnone to user functions but not on builtins. This allows to run
373
- // optimizations on builtins.
374
- if (getAnalysis<MetaDataUtilsWrapper>().getModuleMetaData ()->compOpt .OptDisable )
375
- {
376
- F->addFnAttr (llvm::Attribute::OptimizeNone);
377
- }
378
398
Changed = true ;
379
399
}
380
400
return Changed;
@@ -452,6 +472,10 @@ bool ProcessBuiltinMetaData::runOnModule(Module& M)
452
472
Function *F = &(*I);
453
473
if (!F || F->isDeclaration ()) continue ;
454
474
475
+ // add AlwaysInline for functions. It will be handle in optimization phase
476
+ if (!F->hasFnAttribute (llvm::Attribute::NoInline))
477
+ F->addFnAttr (llvm::Attribute::AlwaysInline);
478
+
455
479
// disable JumpThread optimization on the block that contains this function
456
480
F->setConvergent ();
457
481
0 commit comments