File: | lib/Target/Hexagon/HexagonCFGOptimizer.cpp |
Location: | line 184, column 26 |
Description: | Called C++ object pointer is null |
1 | //===-- HexagonCFGOptimizer.cpp - CFG optimizations -----------------------===// | |||
2 | // The LLVM Compiler Infrastructure | |||
3 | // | |||
4 | // This file is distributed under the University of Illinois Open Source | |||
5 | // License. See LICENSE.TXT for details. | |||
6 | // | |||
7 | //===----------------------------------------------------------------------===// | |||
8 | ||||
9 | #include "Hexagon.h" | |||
10 | #include "HexagonMachineFunctionInfo.h" | |||
11 | #include "HexagonSubtarget.h" | |||
12 | #include "HexagonTargetMachine.h" | |||
13 | #include "llvm/CodeGen/MachineDominators.h" | |||
14 | #include "llvm/CodeGen/MachineFunctionPass.h" | |||
15 | #include "llvm/CodeGen/MachineInstrBuilder.h" | |||
16 | #include "llvm/CodeGen/MachineLoopInfo.h" | |||
17 | #include "llvm/CodeGen/MachineRegisterInfo.h" | |||
18 | #include "llvm/CodeGen/Passes.h" | |||
19 | #include "llvm/Support/Compiler.h" | |||
20 | #include "llvm/Support/Debug.h" | |||
21 | #include "llvm/Support/MathExtras.h" | |||
22 | #include "llvm/Target/TargetInstrInfo.h" | |||
23 | #include "llvm/Target/TargetMachine.h" | |||
24 | #include "llvm/Target/TargetRegisterInfo.h" | |||
25 | ||||
26 | using namespace llvm; | |||
27 | ||||
28 | #define DEBUG_TYPE"hexagon_cfg" "hexagon_cfg" | |||
29 | ||||
30 | namespace llvm { | |||
31 | void initializeHexagonCFGOptimizerPass(PassRegistry&); | |||
32 | } | |||
33 | ||||
34 | ||||
35 | namespace { | |||
36 | ||||
37 | class HexagonCFGOptimizer : public MachineFunctionPass { | |||
38 | ||||
39 | private: | |||
40 | const HexagonTargetMachine& QTM; | |||
41 | const HexagonSubtarget &QST; | |||
42 | ||||
43 | void InvertAndChangeJumpTarget(MachineInstr*, MachineBasicBlock*); | |||
44 | ||||
45 | public: | |||
46 | static char ID; | |||
47 | HexagonCFGOptimizer(const HexagonTargetMachine& TM) | |||
48 | : MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) { | |||
49 | initializeHexagonCFGOptimizerPass(*PassRegistry::getPassRegistry()); | |||
50 | } | |||
51 | ||||
52 | const char *getPassName() const override { | |||
53 | return "Hexagon CFG Optimizer"; | |||
54 | } | |||
55 | bool runOnMachineFunction(MachineFunction &Fn) override; | |||
56 | }; | |||
57 | ||||
58 | ||||
59 | char HexagonCFGOptimizer::ID = 0; | |||
60 | ||||
61 | static bool IsConditionalBranch(int Opc) { | |||
62 | return (Opc == Hexagon::J2_jumpt) || (Opc == Hexagon::J2_jumpf) | |||
63 | || (Opc == Hexagon::J2_jumptnewpt) || (Opc == Hexagon::J2_jumpfnewpt); | |||
64 | } | |||
65 | ||||
66 | ||||
67 | static bool IsUnconditionalJump(int Opc) { | |||
68 | return (Opc == Hexagon::J2_jump); | |||
69 | } | |||
70 | ||||
71 | ||||
72 | void | |||
73 | HexagonCFGOptimizer::InvertAndChangeJumpTarget(MachineInstr* MI, | |||
74 | MachineBasicBlock* NewTarget) { | |||
75 | const HexagonInstrInfo *QII = QTM.getSubtargetImpl()->getInstrInfo(); | |||
76 | int NewOpcode = 0; | |||
77 | switch(MI->getOpcode()) { | |||
78 | case Hexagon::J2_jumpt: | |||
79 | NewOpcode = Hexagon::J2_jumpf; | |||
80 | break; | |||
81 | ||||
82 | case Hexagon::J2_jumpf: | |||
83 | NewOpcode = Hexagon::J2_jumpt; | |||
84 | break; | |||
85 | ||||
86 | case Hexagon::J2_jumptnewpt: | |||
87 | NewOpcode = Hexagon::J2_jumpfnewpt; | |||
88 | break; | |||
89 | ||||
90 | case Hexagon::J2_jumpfnewpt: | |||
91 | NewOpcode = Hexagon::J2_jumptnewpt; | |||
92 | break; | |||
93 | ||||
94 | default: | |||
95 | llvm_unreachable("Cannot handle this case")::llvm::llvm_unreachable_internal("Cannot handle this case", "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn227765/lib/Target/Hexagon/HexagonCFGOptimizer.cpp" , 95); | |||
96 | } | |||
97 | ||||
98 | MI->setDesc(QII->get(NewOpcode)); | |||
99 | MI->getOperand(1).setMBB(NewTarget); | |||
100 | } | |||
101 | ||||
102 | ||||
103 | bool HexagonCFGOptimizer::runOnMachineFunction(MachineFunction &Fn) { | |||
104 | ||||
105 | // Loop over all of the basic blocks. | |||
106 | for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end(); | |||
| ||||
107 | MBBb != MBBe; ++MBBb) { | |||
108 | MachineBasicBlock* MBB = MBBb; | |||
109 | ||||
110 | // Traverse the basic block. | |||
111 | MachineBasicBlock::iterator MII = MBB->getFirstTerminator(); | |||
112 | if (MII != MBB->end()) { | |||
113 | MachineInstr *MI = MII; | |||
114 | int Opc = MI->getOpcode(); | |||
115 | if (IsConditionalBranch(Opc)) { | |||
116 | ||||
117 | // | |||
118 | // (Case 1) Transform the code if the following condition occurs: | |||
119 | // BB1: if (p0) jump BB3 | |||
120 | // ...falls-through to BB2 ... | |||
121 | // BB2: jump BB4 | |||
122 | // ...next block in layout is BB3... | |||
123 | // BB3: ... | |||
124 | // | |||
125 | // Transform this to: | |||
126 | // BB1: if (!p0) jump BB4 | |||
127 | // Remove BB2 | |||
128 | // BB3: ... | |||
129 | // | |||
130 | // (Case 2) A variation occurs when BB3 contains a JMP to BB4: | |||
131 | // BB1: if (p0) jump BB3 | |||
132 | // ...falls-through to BB2 ... | |||
133 | // BB2: jump BB4 | |||
134 | // ...other basic blocks ... | |||
135 | // BB4: | |||
136 | // ...not a fall-thru | |||
137 | // BB3: ... | |||
138 | // jump BB4 | |||
139 | // | |||
140 | // Transform this to: | |||
141 | // BB1: if (!p0) jump BB4 | |||
142 | // Remove BB2 | |||
143 | // BB3: ... | |||
144 | // BB4: ... | |||
145 | // | |||
146 | unsigned NumSuccs = MBB->succ_size(); | |||
147 | MachineBasicBlock::succ_iterator SI = MBB->succ_begin(); | |||
148 | MachineBasicBlock* FirstSucc = *SI; | |||
149 | MachineBasicBlock* SecondSucc = *(++SI); | |||
150 | MachineBasicBlock* LayoutSucc = nullptr; | |||
151 | MachineBasicBlock* JumpAroundTarget = nullptr; | |||
152 | ||||
153 | if (MBB->isLayoutSuccessor(FirstSucc)) { | |||
154 | LayoutSucc = FirstSucc; | |||
155 | JumpAroundTarget = SecondSucc; | |||
156 | } else if (MBB->isLayoutSuccessor(SecondSucc)) { | |||
157 | LayoutSucc = SecondSucc; | |||
158 | JumpAroundTarget = FirstSucc; | |||
159 | } else { | |||
160 | // Odd case...cannot handle. | |||
161 | } | |||
162 | ||||
163 | // The target of the unconditional branch must be JumpAroundTarget. | |||
164 | // TODO: If not, we should not invert the unconditional branch. | |||
165 | MachineBasicBlock* CondBranchTarget = nullptr; | |||
166 | if ((MI->getOpcode() == Hexagon::J2_jumpt) || | |||
167 | (MI->getOpcode() == Hexagon::J2_jumpf)) { | |||
168 | CondBranchTarget = MI->getOperand(1).getMBB(); | |||
169 | } | |||
170 | ||||
171 | if (!LayoutSucc || (CondBranchTarget != JumpAroundTarget)) { | |||
172 | continue; | |||
173 | } | |||
174 | ||||
175 | if ((NumSuccs == 2) && LayoutSucc && (LayoutSucc->pred_size() == 1)) { | |||
176 | ||||
177 | // Ensure that BB2 has one instruction -- an unconditional jump. | |||
178 | if ((LayoutSucc->size() == 1) && | |||
179 | IsUnconditionalJump(LayoutSucc->front().getOpcode())) { | |||
180 | MachineBasicBlock* UncondTarget = | |||
181 | LayoutSucc->front().getOperand(0).getMBB(); | |||
182 | // Check if the layout successor of BB2 is BB3. | |||
183 | bool case1 = LayoutSucc->isLayoutSuccessor(JumpAroundTarget); | |||
184 | bool case2 = JumpAroundTarget->isSuccessor(UncondTarget) && | |||
| ||||
185 | JumpAroundTarget->size() >= 1 && | |||
186 | IsUnconditionalJump(JumpAroundTarget->back().getOpcode()) && | |||
187 | JumpAroundTarget->pred_size() == 1 && | |||
188 | JumpAroundTarget->succ_size() == 1; | |||
189 | ||||
190 | if (case1 || case2) { | |||
191 | InvertAndChangeJumpTarget(MI, UncondTarget); | |||
192 | MBB->removeSuccessor(JumpAroundTarget); | |||
193 | MBB->addSuccessor(UncondTarget); | |||
194 | ||||
195 | // Remove the unconditional branch in LayoutSucc. | |||
196 | LayoutSucc->erase(LayoutSucc->begin()); | |||
197 | LayoutSucc->removeSuccessor(UncondTarget); | |||
198 | LayoutSucc->addSuccessor(JumpAroundTarget); | |||
199 | ||||
200 | // This code performs the conversion for case 2, which moves | |||
201 | // the block to the fall-thru case (BB3 in the code above). | |||
202 | if (case2 && !case1) { | |||
203 | JumpAroundTarget->moveAfter(LayoutSucc); | |||
204 | // only move a block if it doesn't have a fall-thru. otherwise | |||
205 | // the CFG will be incorrect. | |||
206 | if (!UncondTarget->canFallThrough()) { | |||
207 | UncondTarget->moveAfter(JumpAroundTarget); | |||
208 | } | |||
209 | } | |||
210 | ||||
211 | // | |||
212 | // Correct live-in information. Is used by post-RA scheduler | |||
213 | // The live-in to LayoutSucc is now all values live-in to | |||
214 | // JumpAroundTarget. | |||
215 | // | |||
216 | std::vector<unsigned> OrigLiveIn(LayoutSucc->livein_begin(), | |||
217 | LayoutSucc->livein_end()); | |||
218 | std::vector<unsigned> NewLiveIn(JumpAroundTarget->livein_begin(), | |||
219 | JumpAroundTarget->livein_end()); | |||
220 | for (unsigned i = 0; i < OrigLiveIn.size(); ++i) { | |||
221 | LayoutSucc->removeLiveIn(OrigLiveIn[i]); | |||
222 | } | |||
223 | for (unsigned i = 0; i < NewLiveIn.size(); ++i) { | |||
224 | LayoutSucc->addLiveIn(NewLiveIn[i]); | |||
225 | } | |||
226 | } | |||
227 | } | |||
228 | } | |||
229 | } | |||
230 | } | |||
231 | } | |||
232 | return true; | |||
233 | } | |||
234 | } | |||
235 | ||||
236 | ||||
237 | //===----------------------------------------------------------------------===// | |||
238 | // Public Constructor Functions | |||
239 | //===----------------------------------------------------------------------===// | |||
240 | ||||
241 | static void initializePassOnce(PassRegistry &Registry) { | |||
242 | PassInfo *PI = new PassInfo("Hexagon CFG Optimizer", "hexagon-cfg", | |||
243 | &HexagonCFGOptimizer::ID, nullptr, false, false); | |||
244 | Registry.registerPass(*PI, true); | |||
245 | } | |||
246 | ||||
247 | void llvm::initializeHexagonCFGOptimizerPass(PassRegistry &Registry) { | |||
248 | CALL_ONCE_INITIALIZATION(initializePassOnce)static volatile sys::cas_flag initialized = 0; sys::cas_flag old_val = sys::CompareAndSwap(&initialized, 1, 0); if (old_val == 0) { initializePassOnce(Registry); sys::MemoryFence(); AnnotateIgnoreWritesBegin ("/tmp/buildd/llvm-toolchain-snapshot-3.7~svn227765/lib/Target/Hexagon/HexagonCFGOptimizer.cpp" , 248); AnnotateHappensBefore("/tmp/buildd/llvm-toolchain-snapshot-3.7~svn227765/lib/Target/Hexagon/HexagonCFGOptimizer.cpp" , 248, &initialized); initialized = 2; AnnotateIgnoreWritesEnd ("/tmp/buildd/llvm-toolchain-snapshot-3.7~svn227765/lib/Target/Hexagon/HexagonCFGOptimizer.cpp" , 248); } else { sys::cas_flag tmp = initialized; sys::MemoryFence (); while (tmp != 2) { tmp = initialized; sys::MemoryFence(); } } AnnotateHappensAfter("/tmp/buildd/llvm-toolchain-snapshot-3.7~svn227765/lib/Target/Hexagon/HexagonCFGOptimizer.cpp" , 248, &initialized); | |||
249 | } | |||
250 | ||||
251 | FunctionPass *llvm::createHexagonCFGOptimizer(const HexagonTargetMachine &TM) { | |||
252 | return new HexagonCFGOptimizer(TM); | |||
253 | } |