/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp
Line | Count | Source |
1 | | //===-- llvm/CodeGen/GlobalISel/Legalizer.cpp -----------------------------===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | // |
10 | | /// \file This file implements the LegalizerHelper class to legalize individual |
11 | | /// instructions and the LegalizePass wrapper pass for the primary |
12 | | /// legalization. |
13 | | // |
14 | | //===----------------------------------------------------------------------===// |
15 | | |
16 | | #include "llvm/CodeGen/GlobalISel/Legalizer.h" |
17 | | #include "llvm/ADT/SetVector.h" |
18 | | #include "llvm/CodeGen/GlobalISel/LegalizerCombiner.h" |
19 | | #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" |
20 | | #include "llvm/CodeGen/GlobalISel/Utils.h" |
21 | | #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" |
22 | | #include "llvm/CodeGen/MachineRegisterInfo.h" |
23 | | #include "llvm/CodeGen/TargetPassConfig.h" |
24 | | #include "llvm/Support/Debug.h" |
25 | | #include "llvm/Target/TargetInstrInfo.h" |
26 | | #include "llvm/Target/TargetSubtargetInfo.h" |
27 | | |
28 | | #include <iterator> |
29 | | |
30 | | #define DEBUG_TYPE "legalizer" |
31 | | |
32 | | using namespace llvm; |
33 | | |
34 | | char Legalizer::ID = 0; |
35 | 90.2k | INITIALIZE_PASS_BEGIN90.2k (Legalizer, DEBUG_TYPE,
|
36 | 90.2k | "Legalize the Machine IR a function's Machine IR", false, |
37 | 90.2k | false) |
38 | 90.2k | INITIALIZE_PASS_DEPENDENCY(TargetPassConfig) |
39 | 90.2k | INITIALIZE_PASS_END(Legalizer, DEBUG_TYPE, |
40 | | "Legalize the Machine IR a function's Machine IR", false, |
41 | | false) |
42 | | |
43 | 6.46k | Legalizer::Legalizer() : MachineFunctionPass(ID) { |
44 | 6.46k | initializeLegalizerPass(*PassRegistry::getPassRegistry()); |
45 | 6.46k | } |
46 | | |
47 | 6.44k | void Legalizer::getAnalysisUsage(AnalysisUsage &AU) const { |
48 | 6.44k | AU.addRequired<TargetPassConfig>(); |
49 | 6.44k | MachineFunctionPass::getAnalysisUsage(AU); |
50 | 6.44k | } |
51 | | |
52 | 221k | void Legalizer::init(MachineFunction &MF) { |
53 | 221k | } |
54 | | |
55 | 222k | bool Legalizer::runOnMachineFunction(MachineFunction &MF) { |
56 | 222k | // If the ISel pipeline failed, do not bother running that pass. |
57 | 222k | if (MF.getProperties().hasProperty( |
58 | 222k | MachineFunctionProperties::Property::FailedISel)) |
59 | 1.54k | return false; |
60 | 221k | DEBUG221k (dbgs() << "Legalize Machine IR for: " << MF.getName() << '\n'); |
61 | 221k | init(MF); |
62 | 221k | const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>(); |
63 | 221k | MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr); |
64 | 221k | LegalizerHelper Helper(MF); |
65 | 221k | |
66 | 221k | // FIXME: an instruction may need more than one pass before it is legal. For |
67 | 221k | // example on most architectures <3 x i3> is doubly-illegal. It would |
68 | 221k | // typically proceed along a path like: <3 x i3> -> <3 x i8> -> <8 x i8>. We |
69 | 221k | // probably want a worklist of instructions rather than naive iterate until |
70 | 221k | // convergence for performance reasons. |
71 | 221k | bool Changed = false; |
72 | 221k | MachineBasicBlock::iterator NextMI; |
73 | 973k | for (auto &MBB : MF) { |
74 | 12.9M | for (auto MI = MBB.begin(); MI != MBB.end()12.9M ; MI = NextMI12.0M ) { |
75 | 12.0M | // Get the next Instruction before we try to legalize, because there's a |
76 | 12.0M | // good chance MI will be deleted. |
77 | 12.0M | NextMI = std::next(MI); |
78 | 12.0M | |
79 | 12.0M | // Only legalize pre-isel generic instructions: others don't have types |
80 | 12.0M | // and are assumed to be legal. |
81 | 12.0M | if (!isPreISelGenericOpcode(MI->getOpcode())) |
82 | 6.11M | continue; |
83 | 5.93M | unsigned NumNewInsns = 0; |
84 | 5.93M | using VecType = SetVector<MachineInstr *, SmallVector<MachineInstr *, 8>>; |
85 | 5.93M | VecType WorkList; |
86 | 5.93M | VecType CombineList; |
87 | 1.89M | Helper.MIRBuilder.recordInsertions([&](MachineInstr *MI) { |
88 | 1.89M | // Only legalize pre-isel generic instructions. |
89 | 1.89M | // Legalization process could generate Target specific pseudo |
90 | 1.89M | // instructions with generic types. Don't record them |
91 | 1.89M | if (isPreISelGenericOpcode(MI->getOpcode())1.89M ) { |
92 | 1.77M | ++NumNewInsns; |
93 | 1.77M | WorkList.insert(MI); |
94 | 1.77M | CombineList.insert(MI); |
95 | 1.77M | } |
96 | 1.89M | }); |
97 | 5.93M | WorkList.insert(&*MI); |
98 | 5.93M | LegalizerCombiner C(Helper.MIRBuilder, MF.getRegInfo()); |
99 | 5.93M | bool Changed = false; |
100 | 5.93M | LegalizerHelper::LegalizeResult Res; |
101 | 5.97M | do { |
102 | 5.97M | assert(!WorkList.empty() && "Expecting illegal ops"); |
103 | 13.6M | while (!WorkList.empty()13.6M ) { |
104 | 7.71M | NumNewInsns = 0; |
105 | 7.71M | MachineInstr *CurrInst = WorkList.pop_back_val(); |
106 | 7.71M | Res = Helper.legalizeInstrStep(*CurrInst); |
107 | 7.71M | // Error out if we couldn't legalize this instruction. We may want to |
108 | 7.71M | // fall back to DAG ISel instead in the future. |
109 | 7.71M | if (Res == LegalizerHelper::UnableToLegalize7.71M ) { |
110 | 41.7k | Helper.MIRBuilder.stopRecordingInsertions(); |
111 | 41.7k | if (Res == LegalizerHelper::UnableToLegalize41.7k ) { |
112 | 41.7k | reportGISelFailure(MF, TPC, MORE, "gisel-legalize", |
113 | 41.7k | "unable to legalize instruction", *CurrInst); |
114 | 41.7k | return false; |
115 | 41.7k | } |
116 | 7.67M | } |
117 | 7.67M | Changed |= Res == LegalizerHelper::Legalized; |
118 | 7.67M | // If CurrInst was legalized, there's a good chance that it might have |
119 | 7.67M | // been erased. So remove it from the Combine List. |
120 | 7.67M | if (Res == LegalizerHelper::Legalized) |
121 | 770k | CombineList.remove(CurrInst); |
122 | 7.67M | |
123 | | #ifndef NDEBUG |
124 | | if (NumNewInsns) |
125 | | for (unsigned I = WorkList.size() - NumNewInsns, |
126 | | E = WorkList.size(); |
127 | | I != E; ++I) |
128 | | DEBUG(dbgs() << ".. .. New MI: " << *WorkList[I];); |
129 | | #endif |
130 | | } |
131 | 5.97M | // Do the combines. |
132 | 7.67M | while (5.93M !CombineList.empty()7.67M ) { |
133 | 1.74M | NumNewInsns = 0; |
134 | 1.74M | MachineInstr *CurrInst = CombineList.pop_back_val(); |
135 | 1.74M | SmallVector<MachineInstr *, 4> DeadInstructions; |
136 | 1.74M | Changed |= C.tryCombineInstruction(*CurrInst, DeadInstructions); |
137 | 104k | for (auto *DeadMI : DeadInstructions) { |
138 | 104k | DEBUG(dbgs() << ".. Erasing Dead Instruction " << *DeadMI); |
139 | 104k | CombineList.remove(DeadMI); |
140 | 104k | WorkList.remove(DeadMI); |
141 | 104k | DeadMI->eraseFromParent(); |
142 | 104k | } |
143 | | #ifndef NDEBUG |
144 | | if (NumNewInsns) |
145 | | for (unsigned I = CombineList.size() - NumNewInsns, |
146 | | E = CombineList.size(); |
147 | | I != E; ++I) |
148 | | DEBUG(dbgs() << ".. .. Combine New MI: " << *CombineList[I];); |
149 | | #endif |
150 | | } |
151 | 5.93M | } while (!WorkList.empty()); |
152 | 5.93M | |
153 | 5.89M | Helper.MIRBuilder.stopRecordingInsertions(); |
154 | 5.89M | } |
155 | 973k | } |
156 | 221k | |
157 | 179k | MachineRegisterInfo &MRI = MF.getRegInfo(); |
158 | 179k | MachineIRBuilder MIRBuilder(MF); |
159 | 179k | LegalizerCombiner C(MIRBuilder, MRI); |
160 | 676k | for (auto &MBB : MF) { |
161 | 10.2M | for (auto MI = MBB.begin(); MI != MBB.end()10.2M ; MI = NextMI9.53M ) { |
162 | 9.53M | // Get the next Instruction before we try to legalize, because there's a |
163 | 9.53M | // good chance MI will be deleted. |
164 | 9.53M | // TOOD: Perhaps move this to a combiner pass later?. |
165 | 9.53M | NextMI = std::next(MI); |
166 | 9.53M | SmallVector<MachineInstr *, 4> DeadInsts; |
167 | 9.53M | Changed |= C.tryCombineMerges(*MI, DeadInsts); |
168 | 9.53M | for (auto *DeadMI : DeadInsts) |
169 | 38 | DeadMI->eraseFromParent(); |
170 | 9.53M | } |
171 | 676k | } |
172 | 179k | |
173 | 179k | return Changed; |
174 | 222k | } |