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