1 /*========================== begin_copyright_notice ============================
2
3 Copyright (C) 2017-2021 Intel Corporation
4
5 SPDX-License-Identifier: MIT
6
7 ============================= end_copyright_notice ===========================*/
8
9 //
10 // GenXPrinter is a pass that prints the LLVM IR for a function, together
11 // GenX specific analyses (instruction baling, liveness, register allocation).
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "FunctionGroup.h"
16 #include "GenX.h"
17 #include "GenXBaling.h"
18 #include "GenXLiveness.h"
19 #include "GenXNumbering.h"
20 #include "GenXVisaRegAlloc.h"
21 #include "llvm/IR/Function.h"
22 #include "llvm/IR/Value.h"
23 #include "llvm/Support/raw_ostream.h"
24 #include "Probe/Assertion.h"
25
26 using namespace llvm;
27 using namespace genx;
28
29 namespace {
30
31 // GenXPrinter : an analysis to print a Function, with GenX specific analyses
32 class GenXPrinter : public FunctionPass {
33 raw_ostream &OS;
34 const std::string Banner;
35 public:
36 static char ID;
GenXPrinter(raw_ostream & OS,const std::string & Banner)37 explicit GenXPrinter(raw_ostream &OS, const std::string &Banner)
38 : FunctionPass(ID), OS(OS), Banner(Banner) { }
getPassName() const39 StringRef getPassName() const override { return "GenX printer pass"; }
getAnalysisUsage(AnalysisUsage & AU) const40 void getAnalysisUsage(AnalysisUsage &AU) const override {
41 AU.setPreservesAll();
42 }
43 bool runOnFunction(Function &F) override;
44 };
45
46 // GenXGroupPrinter : an analysis to print Module with all FunctionGroups, with
47 // GenX specific analyses
48 class GenXGroupPrinter : public ModulePass {
49 raw_ostream &OS;
50 const std::string Banner;
51 public:
52 static char ID;
GenXGroupPrinter(raw_ostream & OS,const std::string & Banner)53 explicit GenXGroupPrinter(raw_ostream &OS, const std::string &Banner)
54 : ModulePass(ID), OS(OS), Banner(Banner) {}
getPassName() const55 StringRef getPassName() const override {
56 return "GenX FunctionGroup printer pass";
57 }
getAnalysisUsage(AnalysisUsage & AU) const58 void getAnalysisUsage(AnalysisUsage &AU) const override {
59 AU.addRequired<FunctionGroupAnalysis>();
60 AU.addPreserved<FunctionGroupAnalysis>();
61 AU.setPreservesAll();
62 }
runOnModule(Module & M)63 bool runOnModule(Module &M) override {
64 bool Changed = false;
65 FunctionGroupAnalysis &FGA = getAnalysis<FunctionGroupAnalysis>();
66 for (auto *FunctionGroup : FGA.AllGroups())
67 Changed |= runOnFunctionGroup(*FunctionGroup);
68 return Changed;
69 }
70 bool runOnFunctionGroup(FunctionGroup &FG);
71 };
72
73 } // end namespace llvm
74
75 char GenXPrinter::ID = 0;
76
createGenXPrinterPass(raw_ostream & O,const std::string & Banner)77 FunctionPass *llvm::createGenXPrinterPass(raw_ostream &O, const std::string &Banner)
78 {
79 FunctionPass *Created = new GenXPrinter(O, Banner);
80 IGC_ASSERT(Created);
81 return Created;
82 }
83
84 char GenXGroupPrinter::ID = 0;
85
createGenXGroupPrinterPass(raw_ostream & O,const std::string & Banner)86 ModulePass *llvm::createGenXGroupPrinterPass(raw_ostream &O,
87 const std::string &Banner) {
88 ModulePass *Created = new GenXGroupPrinter(O, Banner);
89 IGC_ASSERT(Created);
90 return Created;
91 }
92
93 /***********************************************************************
94 * printFunction : print function with GenX analyses
95 */
printFunction(raw_ostream & OS,Function & F,GenXBaling * Baling,GenXLiveness * Liveness,GenXNumbering * Numbering,GenXVisaRegAlloc * RA)96 static void printFunction(raw_ostream &OS, Function &F, GenXBaling *Baling,
97 GenXLiveness *Liveness, GenXNumbering *Numbering, GenXVisaRegAlloc *RA)
98 {
99 // This code is a downmarket version of AssemblyWriter::printFunction.
100 // We have our own version so we can show bales.
101 OS << "\ndefine ";
102 cast<FunctionType>(cast<PointerType>(F.getType())->getElementType())->getReturnType()->print(OS);
103 OS << " @" << F.getName() << "(";
104 for (Function::arg_iterator fb = F.arg_begin(), fi = fb, fe = F.arg_end();
105 fi != fe; ) {
106 if (fi != fb)
107 OS << ", ";
108 Argument *Arg = &*fi;
109 ++fi;
110 Arg->getType()->print(OS);
111 OS << " ";
112 // Only show register number if there is a register allocator.
113 GenXVisaRegAlloc::Reg* Reg = nullptr;
114 if (RA)
115 Reg = RA->getRegForValueUntyped(&F, SimpleValue(Arg));
116 if (Reg) {
117 OS << "[";
118 Reg->print(OS);
119 OS << "]";
120 }
121 OS << "%" << Arg->getName();
122 }
123 OS << ") {\n";
124 for (Function::iterator fi = F.begin(), fe = F.end(); fi != fe; ++fi) {
125 BasicBlock *BB = &*fi;
126 if (!BB->use_empty())
127 OS << BB->getName() << ":\n";
128 for (BasicBlock::iterator bi = BB->begin(), be = BB->end(); bi != be; ++bi) {
129 Instruction *Inst = &*bi;
130 if (!Baling || !Baling->isBaled(Inst)) {
131 if (RA && !Inst->getType()->isVoidTy()) {
132 // Show allocated register in brackets. If it is struct type,
133 // we show the multiple registers. For an alias, show its base
134 // register in braces as well.
135 for (unsigned i = 0,
136 e = IndexFlattener::getNumElements(Inst->getType());
137 i != e; ++i) {
138 auto Reg = RA->getRegForValueUntyped(&F, SimpleValue(Inst, i));
139 if (Reg && Reg->Category) {
140 OS << (!i ? "[" : ",");
141 Reg->print(OS);
142 auto BaseReg = RA->getRegForValueUntyped(&F, SimpleValue(Inst, i));
143 if (BaseReg != Reg) {
144 OS << "{";
145 IGC_ASSERT(BaseReg);
146 BaseReg->print(OS);
147 OS << "}";
148 }
149 if (i + 1 == e)
150 OS << "]";
151 }
152 }
153 }
154 // Show instruction number in brackets.
155 unsigned Num = 0;
156 if (Numbering)
157 Num = Numbering->getNumber(Inst);
158 if (Num)
159 OS << "[" << Num << "]";
160 if (!Baling) {
161 Inst->print(OS);
162 OS << "\n";
163 } else {
164 Bale B;
165 Baling->buildBale(Inst, &B);
166 if (B.size() == 1) {
167 Inst->print(OS);
168 OS << "\n";
169 } else {
170 OS << " bale {\n";
171 for (Bale::iterator i = B.begin(),
172 e = B.end(); i != e; ++i) {
173 unsigned Num = 0;
174 if (Numbering)
175 Num = Numbering->getNumber(i->Inst);
176 if (Num)
177 OS << "[" << Num << "]";
178 OS << " ";
179 i->Inst->print(OS);
180 switch (i->Info.Type) {
181 case BaleInfo::MAININST: break;
182 default: OS << " {" << i->Info.getTypeString() << "}"; break;
183 }
184 OS << "\n";
185 }
186 if (Num)
187 OS << "[" << Num << "]";
188 OS << " }\n";
189 }
190 }
191 }
192 }
193 }
194 OS << "}\n";
195 }
196
197 /***********************************************************************
198 * GenXPrinter::runOnFunction : dump function with GenX analyses
199 */
runOnFunction(Function & F)200 bool GenXPrinter::runOnFunction(Function &F)
201 {
202 auto *FGA = getAnalysisIfAvailable<FunctionGroupAnalysis>();
203 GenXVisaRegAlloc *RA = nullptr;
204 GenXLiveness *Liveness = nullptr;
205 GenXNumbering *Numbering = nullptr;
206 if (FGA) {
207 auto *currentFG = FGA->getAnyGroup(&F);
208 if (auto *RAWrapper = getAnalysisIfAvailable<GenXVisaRegAllocWrapper>()) {
209 RA = &(RAWrapper->getFGPassImpl(currentFG));
210 }
211 if (auto *NumberingWrapper = getAnalysisIfAvailable<GenXNumberingWrapper>())
212 Numbering = &(NumberingWrapper->getFGPassImpl(currentFG));
213 if (auto *LivenessWrapper = getAnalysisIfAvailable<GenXLivenessWrapper>())
214 Liveness = &(LivenessWrapper->getFGPassImpl(currentFG));
215 }
216
217 GenXBaling *Baling = getAnalysisIfAvailable<GenXFuncBaling>();
218 OS << Banner;
219 printFunction(OS, F, Baling, Liveness, Numbering, RA);
220 return false;
221 }
222
223 /***********************************************************************
224 * GenXGroupPrinter::runOnFunctionGroup : dump functions with GenX analyses
225 */
runOnFunctionGroup(FunctionGroup & FG)226 bool GenXGroupPrinter::runOnFunctionGroup(FunctionGroup &FG)
227 {
228 GenXVisaRegAlloc *RA = nullptr;
229 if (auto *RAWrapper = getAnalysisIfAvailable<GenXVisaRegAllocWrapper>())
230 RA = &(RAWrapper->getFGPassImpl(&FG));
231
232 GenXLiveness *Liveness = nullptr;
233 GenXNumbering *Numbering = nullptr;
234 if (!RA) {
235 if (auto *LivenessWrapper = getAnalysisIfAvailable<GenXLivenessWrapper>())
236 Liveness = &(LivenessWrapper->getFGPassImpl(&FG));
237 if (auto *NumberingWrapper = getAnalysisIfAvailable<GenXNumberingWrapper>())
238 Numbering = &(NumberingWrapper->getFGPassImpl(&FG));
239 }
240 GenXBaling *Baling = nullptr;
241 if (auto *GroupBalingWrapper =
242 getAnalysisIfAvailable<GenXGroupBalingWrapper>())
243 Baling = &(GroupBalingWrapper->getFGPassImpl(&FG));
244 if (!Baling)
245 Baling = getAnalysisIfAvailable<GenXFuncBaling>();
246 OS << Banner;
247 if (Liveness)
248 OS << " (see below for GenXLiveness)";
249 for (auto i = FG.begin(), e = FG.end(); i != e; ++i)
250 printFunction(OS, **i, Baling, Liveness, Numbering, RA);
251 if (Liveness) {
252 Liveness->print(OS);
253 OS << "\n";
254 }
255 OS << "\n";
256 return false;
257 }
258
259