1
+ /* ========================== begin_copyright_notice ============================
2
+
3
+ Copyright (C) 2025 Intel Corporation
4
+
5
+ SPDX-License-Identifier: MIT
6
+
7
+ ============================= end_copyright_notice ===========================*/
8
+
9
+ #include " Compiler/CISACodeGen/RematChainsAnalysis.hpp"
10
+ #include " Compiler/IGCPassSupport.h"
11
+ #include " Compiler/CodeGenContextWrapper.hpp"
12
+ #include " Compiler/CodeGenPublic.h"
13
+ #include " common/debug/Debug.hpp"
14
+
15
+ #include " GenISAIntrinsics/GenIntrinsicInst.h"
16
+ #include " llvmWrapper/IR/Function.h"
17
+ #include " llvmWrapper/IR/Value.h"
18
+ #include " llvmWrapper/IR/DerivedTypes.h"
19
+
20
+ using namespace llvm ;
21
+ using namespace IGC ::Debug;
22
+
23
+ char RematChainsAnalysis::ID = 0 ;
24
+
25
+ // Register pass to igc-opt
26
+ #define PASS_FLAG " igc-remat-chain-analysis"
27
+ #define PASS_DESCRIPTION " Recognizes rematerialization chain patterns"
28
+ #define PASS_CFG_ONLY false
29
+ #define PASS_ANALYSIS true
30
+ IGC_INITIALIZE_PASS_BEGIN (RematChainsAnalysis, PASS_FLAG, PASS_DESCRIPTION, PASS_CFG_ONLY, PASS_ANALYSIS)
31
+ IGC_INITIALIZE_PASS_END(RematChainsAnalysis, PASS_FLAG, PASS_DESCRIPTION, PASS_CFG_ONLY, PASS_ANALYSIS)
32
+
33
+ RematChainsAnalysis::RematChainsAnalysis() : FunctionPass(ID) {
34
+ initializeRematChainsAnalysisPass (*PassRegistry::getPassRegistry ());
35
+ };
36
+
37
+ static bool hasRematMetadata (llvm::Value *V) {
38
+ if (auto *I = dyn_cast<Instruction>(V)) {
39
+ if (auto *MD = I->getMetadata (" remat" )) {
40
+ return true ;
41
+ }
42
+ }
43
+ return false ;
44
+ }
45
+
46
+ Value *getAddressOperand (llvm::Instruction *I) {
47
+ if (!I) return nullptr ;
48
+
49
+ // Check if the instruction is a Load or Store and return the address operand
50
+ if (auto *LI = dyn_cast<LoadInst>(I)) {
51
+ return LI->getPointerOperand ();
52
+ } else if (auto *SI = dyn_cast<StoreInst>(I)) {
53
+ return SI->getPointerOperand ();
54
+ }
55
+
56
+ // If it's not a Load or Store, return nullptr
57
+ return nullptr ;
58
+ }
59
+
60
+ // There are many passes that could change the remat chain,
61
+ // So we consider not only the instructions that has remat metadata,
62
+ // But also the instructions that have only one undroppable user,
63
+ // which will be the load/store or the instruction that is rematerialized
64
+ RematChainSet getRematChain (Value *V, Instruction *User) {
65
+ if (!V) return {};
66
+ Instruction *I = dyn_cast<Instruction>(V);
67
+ if (!I) return {};
68
+ if (!User) return {};
69
+
70
+ if (!isa<IntToPtrInst>(I) && !isa<AddrSpaceCastInst>(I)
71
+ && !isa<BitCastInst>(I) && !isa<GetElementPtrInst>(I)
72
+ && !isa<BinaryOperator>(I) && !isa<UnaryOperator>(I)) {
73
+ return {};
74
+ }
75
+
76
+ if (I->getParent () != User->getParent ()) {
77
+ return {};
78
+ }
79
+
80
+ RematChainSet Chain;
81
+ if ((IGCLLVM::getUniqueUndroppableUser (I) == User) || (hasRematMetadata (I))) {
82
+ Chain.insert (I);
83
+
84
+ for (auto &Op : I->operands ()) {
85
+ Value *OpV = Op.get ();
86
+ if (auto *OpI = dyn_cast<Instruction>(OpV)) {
87
+ auto SubChain = getRematChain (OpI, I);
88
+ Chain.insert (SubChain.begin (), SubChain.end ());
89
+ }
90
+ }
91
+ }
92
+
93
+ return Chain;
94
+ }
95
+
96
+ bool RematChainsAnalysis::runOnFunction (llvm::Function &F) {
97
+ for (auto &BB : F) {
98
+ for (Instruction &I : BB) {
99
+ Value *AddrOperand = getAddressOperand (&I);
100
+ if (!AddrOperand)
101
+ continue ;
102
+
103
+ Instruction *AI = dyn_cast<Instruction>(AddrOperand);
104
+ if (!AI)
105
+ continue ;
106
+
107
+ RematChainSet Chain = getRematChain (AddrOperand, &I);
108
+
109
+ if (!Chain.empty ()) {
110
+ RematChainPatterns.push_back (std::make_unique<RematChainPattern>(Chain, AI, &I));
111
+ for (auto *Inst : Chain) {
112
+ ValueToRematChainMap[Inst] = RematChainPatterns.back ().get ();
113
+ }
114
+ }
115
+ }
116
+ for (Instruction &I : BB) {
117
+ if (RematChainPattern *Pattern = getRematChainPattern (&I)) {
118
+ if (Pattern->getFirstInst () == nullptr ) {
119
+ Pattern->setFirstInst (&I);
120
+ }
121
+ }
122
+ }
123
+ }
124
+
125
+ #ifdef _DEBUG
126
+ for (const auto &Pattern : RematChainPatterns) {
127
+ IGC_ASSERT (Pattern->getFirstInst () != nullptr && " Remat chain pattern must have a first instruction" );
128
+ IGC_ASSERT (Pattern->getLastInst () != nullptr && " Remat chain pattern must have a last instruction" );
129
+ IGC_ASSERT (Pattern->getRematTargetInst () != nullptr && " Remat chain pattern must have a remat target instruction" );
130
+ }
131
+ #endif
132
+
133
+ return true ;
134
+ }
0 commit comments