12
12
// /
13
13
// ===----------------------------------------------------------------------===//
14
14
15
- #include " AMDGPU.h"
16
15
#include " AMDGPUPerfHintAnalysis.h"
16
+ #include " AMDGPU.h"
17
+ #include " AMDGPUTargetMachine.h"
17
18
#include " Utils/AMDGPUBaseInfo.h"
18
19
#include " llvm/ADT/SmallSet.h"
19
20
#include " llvm/ADT/Statistic.h"
20
21
#include " llvm/Analysis/CallGraph.h"
22
+ #include " llvm/Analysis/CallGraphSCCPass.h"
23
+ #include " llvm/Analysis/LazyCallGraph.h"
21
24
#include " llvm/Analysis/ValueTracking.h"
22
25
#include " llvm/CodeGen/TargetLowering.h"
23
26
#include " llvm/CodeGen/TargetPassConfig.h"
@@ -54,20 +57,14 @@ static cl::opt<unsigned>
54
57
STATISTIC (NumMemBound, " Number of functions marked as memory bound" );
55
58
STATISTIC (NumLimitWave, " Number of functions marked as needing limit wave" );
56
59
57
- char llvm::AMDGPUPerfHintAnalysis::ID = 0 ;
58
- char &llvm::AMDGPUPerfHintAnalysisID = AMDGPUPerfHintAnalysis::ID;
59
-
60
- INITIALIZE_PASS (AMDGPUPerfHintAnalysis, DEBUG_TYPE,
61
- " Analysis if a function is memory bound" , true , true )
62
-
63
60
namespace {
64
61
65
62
struct AMDGPUPerfHint {
66
63
friend AMDGPUPerfHintAnalysis;
67
64
68
65
public:
69
66
AMDGPUPerfHint (AMDGPUPerfHintAnalysis::FuncInfoMap &FIM_,
70
- const TargetLowering *TLI_)
67
+ const SITargetLowering *TLI_)
71
68
: FIM(FIM_), TLI(TLI_) {}
72
69
73
70
bool runOnFunction (Function &F);
@@ -97,7 +94,7 @@ struct AMDGPUPerfHint {
97
94
98
95
const DataLayout *DL = nullptr ;
99
96
100
- const TargetLowering *TLI;
97
+ const SITargetLowering *TLI;
101
98
102
99
AMDGPUPerfHintAnalysis::FuncInfo *visit (const Function &F);
103
100
static bool isMemBound (const AMDGPUPerfHintAnalysis::FuncInfo &F);
@@ -388,23 +385,52 @@ bool AMDGPUPerfHint::MemAccessInfo::isLargeStride(
388
385
<< Reference.print () << " Result:" << Result << ' \n ' );
389
386
return Result;
390
387
}
388
+
389
+ class AMDGPUPerfHintAnalysisLegacy : public CallGraphSCCPass {
390
+ private:
391
+ // FIXME: This is relying on maintaining state between different SCCs.
392
+ AMDGPUPerfHintAnalysis Impl;
393
+
394
+ public:
395
+ static char ID;
396
+
397
+ AMDGPUPerfHintAnalysisLegacy () : CallGraphSCCPass(ID) {}
398
+
399
+ bool runOnSCC (CallGraphSCC &SCC) override ;
400
+
401
+ void getAnalysisUsage (AnalysisUsage &AU) const override {
402
+ AU.setPreservesAll ();
403
+ }
404
+ };
405
+
391
406
} // namespace
392
407
393
- bool AMDGPUPerfHintAnalysis::runOnSCC (CallGraphSCC &SCC) {
394
- auto *TPC = getAnalysisIfAvailable<TargetPassConfig>( );
395
- if (!TPC )
408
+ bool AMDGPUPerfHintAnalysis::isMemoryBound ( const Function *F) const {
409
+ auto FI = FIM. find (F );
410
+ if (FI == FIM. end () )
396
411
return false ;
397
412
398
- const TargetMachine &TM = TPC->getTM <TargetMachine>();
413
+ return AMDGPUPerfHint::isMemBound (FI->second );
414
+ }
415
+
416
+ bool AMDGPUPerfHintAnalysis::needsWaveLimiter (const Function *F) const {
417
+ auto FI = FIM.find (F);
418
+ if (FI == FIM.end ())
419
+ return false ;
420
+
421
+ return AMDGPUPerfHint::needLimitWave (FI->second );
422
+ }
399
423
424
+ bool AMDGPUPerfHintAnalysis::runOnSCC (const GCNTargetMachine &TM,
425
+ CallGraphSCC &SCC) {
400
426
bool Changed = false ;
401
427
for (CallGraphNode *I : SCC) {
402
428
Function *F = I->getFunction ();
403
429
if (!F || F->isDeclaration ())
404
430
continue ;
405
431
406
- const TargetSubtargetInfo * ST = TM.getSubtargetImpl (*F);
407
- AMDGPUPerfHint Analyzer (FIM, ST-> getTargetLowering ());
432
+ const GCNSubtarget & ST = TM.getSubtarget <GCNSubtarget> (*F);
433
+ AMDGPUPerfHint Analyzer (FIM, ST. getTargetLowering ());
408
434
409
435
if (Analyzer.runOnFunction (*F))
410
436
Changed = true ;
@@ -413,18 +439,56 @@ bool AMDGPUPerfHintAnalysis::runOnSCC(CallGraphSCC &SCC) {
413
439
return Changed;
414
440
}
415
441
416
- bool AMDGPUPerfHintAnalysis::isMemoryBound (const Function *F) const {
417
- auto FI = FIM.find (F);
418
- if (FI == FIM.end ())
419
- return false ;
442
+ bool AMDGPUPerfHintAnalysis::run (const GCNTargetMachine &TM,
443
+ LazyCallGraph &CG) {
420
444
421
- return AMDGPUPerfHint::isMemBound (FI->second );
445
+ SmallVector<Function *, 16 > Worklist;
446
+ CG.buildRefSCCs ();
447
+ for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs ()) {
448
+ for (LazyCallGraph::SCC &SCC : RC) {
449
+ if (SCC.size () != 1 )
450
+ continue ;
451
+ Function &F = SCC.begin ()->getFunction ();
452
+ Worklist.push_back (&F);
453
+ }
454
+ }
455
+
456
+ bool Changed = false ;
457
+ for (auto *F : llvm::reverse (Worklist)) {
458
+ const GCNSubtarget &ST = TM.getSubtarget <GCNSubtarget>(*F);
459
+ AMDGPUPerfHint Analyzer (FIM, ST.getTargetLowering ());
460
+
461
+ if (Analyzer.runOnFunction (*F))
462
+ Changed = true ;
463
+ }
464
+
465
+ return Changed;
422
466
}
423
467
424
- bool AMDGPUPerfHintAnalysis::needsWaveLimiter (const Function *F) const {
425
- auto FI = FIM.find (F);
426
- if (FI == FIM.end ())
468
+ char AMDGPUPerfHintAnalysisLegacy::ID = 0 ;
469
+ char &llvm::AMDGPUPerfHintAnalysisLegacyID = AMDGPUPerfHintAnalysisLegacy::ID;
470
+
471
+ INITIALIZE_PASS (AMDGPUPerfHintAnalysisLegacy, DEBUG_TYPE,
472
+ " Analysis if a function is memory bound" , true , true )
473
+
474
+ bool AMDGPUPerfHintAnalysisLegacy::runOnSCC(CallGraphSCC &SCC) {
475
+ auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
476
+ if (!TPC)
427
477
return false ;
428
478
429
- return AMDGPUPerfHint::needLimitWave (FI->second );
479
+ const GCNTargetMachine &TM = TPC->getTM <GCNTargetMachine>();
480
+ return Impl.runOnSCC (TM, SCC);
481
+ }
482
+
483
+ PreservedAnalyses AMDGPUPerfHintAnalysisPass::run (Module &M,
484
+ ModuleAnalysisManager &AM) {
485
+ auto &CG = AM.getResult <LazyCallGraphAnalysis>(M);
486
+
487
+ bool Changed = Impl->run (TM, CG);
488
+ if (!Changed)
489
+ return PreservedAnalyses::all ();
490
+
491
+ PreservedAnalyses PA;
492
+ PA.preserve <LazyCallGraphAnalysis>();
493
+ return PA;
430
494
}
0 commit comments