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/Debug.h" | |||
20 | #include "llvm/Support/MathExtras.h" | |||
21 | #include "llvm/Target/TargetInstrInfo.h" | |||
22 | #include "llvm/Target/TargetMachine.h" | |||
23 | #include "llvm/Target/TargetRegisterInfo.h" | |||
24 | ||||
25 | using namespace llvm; | |||
26 | ||||
27 | #define DEBUG_TYPE"hexagon_cfg" "hexagon_cfg" | |||
28 | ||||
29 | namespace llvm { | |||
30 | FunctionPass *createHexagonCFGOptimizer(); | |||
31 | void initializeHexagonCFGOptimizerPass(PassRegistry&); | |||
32 | } | |||
33 | ||||
34 | ||||
35 | namespace { | |||
36 | ||||
37 | class HexagonCFGOptimizer : public MachineFunctionPass { | |||
38 | ||||
39 | private: | |||
40 | void InvertAndChangeJumpTarget(MachineInstr*, MachineBasicBlock*); | |||
41 | ||||
42 | public: | |||
43 | static char ID; | |||
44 | HexagonCFGOptimizer() : MachineFunctionPass(ID) { | |||
45 | initializeHexagonCFGOptimizerPass(*PassRegistry::getPassRegistry()); | |||
46 | } | |||
47 | ||||
48 | const char *getPassName() const override { | |||
49 | return "Hexagon CFG Optimizer"; | |||
50 | } | |||
51 | bool runOnMachineFunction(MachineFunction &Fn) override; | |||
52 | MachineFunctionProperties getRequiredProperties() const override { | |||
53 | return MachineFunctionProperties().set( | |||
54 | MachineFunctionProperties::Property::AllVRegsAllocated); | |||
55 | } | |||
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 TargetInstrInfo *TII = | |||
76 | MI->getParent()->getParent()->getSubtarget().getInstrInfo(); | |||
77 | int NewOpcode = 0; | |||
78 | switch(MI->getOpcode()) { | |||
79 | case Hexagon::J2_jumpt: | |||
80 | NewOpcode = Hexagon::J2_jumpf; | |||
81 | break; | |||
82 | ||||
83 | case Hexagon::J2_jumpf: | |||
84 | NewOpcode = Hexagon::J2_jumpt; | |||
85 | break; | |||
86 | ||||
87 | case Hexagon::J2_jumptnewpt: | |||
88 | NewOpcode = Hexagon::J2_jumpfnewpt; | |||
89 | break; | |||
90 | ||||
91 | case Hexagon::J2_jumpfnewpt: | |||
92 | NewOpcode = Hexagon::J2_jumptnewpt; | |||
93 | break; | |||
94 | ||||
95 | default: | |||
96 | llvm_unreachable("Cannot handle this case")::llvm::llvm_unreachable_internal("Cannot handle this case", "/tmp/buildd/llvm-toolchain-snapshot-3.9~svn267387/lib/Target/Hexagon/HexagonCFGOptimizer.cpp" , 96); | |||
97 | } | |||
98 | ||||
99 | MI->setDesc(TII->get(NewOpcode)); | |||
100 | MI->getOperand(1).setMBB(NewTarget); | |||
101 | } | |||
102 | ||||
103 | ||||
104 | bool HexagonCFGOptimizer::runOnMachineFunction(MachineFunction &Fn) { | |||
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->replaceSuccessor(JumpAroundTarget, UncondTarget); | |||
193 | ||||
194 | // Remove the unconditional branch in LayoutSucc. | |||
195 | LayoutSucc->erase(LayoutSucc->begin()); | |||
196 | LayoutSucc->replaceSuccessor(UncondTarget, JumpAroundTarget); | |||
197 | ||||
198 | // This code performs the conversion for case 2, which moves | |||
199 | // the block to the fall-thru case (BB3 in the code above). | |||
200 | if (case2 && !case1) { | |||
201 | JumpAroundTarget->moveAfter(LayoutSucc); | |||
202 | // only move a block if it doesn't have a fall-thru. otherwise | |||
203 | // the CFG will be incorrect. | |||
204 | if (!UncondTarget->canFallThrough()) { | |||
205 | UncondTarget->moveAfter(JumpAroundTarget); | |||
206 | } | |||
207 | } | |||
208 | ||||
209 | // | |||
210 | // Correct live-in information. Is used by post-RA scheduler | |||
211 | // The live-in to LayoutSucc is now all values live-in to | |||
212 | // JumpAroundTarget. | |||
213 | // | |||
214 | std::vector<MachineBasicBlock::RegisterMaskPair> OrigLiveIn( | |||
215 | LayoutSucc->livein_begin(), LayoutSucc->livein_end()); | |||
216 | std::vector<MachineBasicBlock::RegisterMaskPair> NewLiveIn( | |||
217 | JumpAroundTarget->livein_begin(), | |||
218 | JumpAroundTarget->livein_end()); | |||
219 | for (const auto &OrigLI : OrigLiveIn) | |||
220 | LayoutSucc->removeLiveIn(OrigLI.PhysReg); | |||
221 | for (const auto &NewLI : NewLiveIn) | |||
222 | LayoutSucc->addLiveIn(NewLI); | |||
223 | } | |||
224 | } | |||
225 | } | |||
226 | } | |||
227 | } | |||
228 | } | |||
229 | return true; | |||
230 | } | |||
231 | } | |||
232 | ||||
233 | ||||
234 | //===----------------------------------------------------------------------===// | |||
235 | // Public Constructor Functions | |||
236 | //===----------------------------------------------------------------------===// | |||
237 | ||||
238 | static void initializePassOnce(PassRegistry &Registry) { | |||
239 | PassInfo *PI = new PassInfo("Hexagon CFG Optimizer", "hexagon-cfg", | |||
240 | &HexagonCFGOptimizer::ID, nullptr, false, false); | |||
241 | Registry.registerPass(*PI, true); | |||
242 | } | |||
243 | ||||
244 | void llvm::initializeHexagonCFGOptimizerPass(PassRegistry &Registry) { | |||
245 | 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(); ; ; initialized = 2; ; } else { sys::cas_flag tmp = initialized; sys::MemoryFence (); while (tmp != 2) { tmp = initialized; sys::MemoryFence(); } } ; | |||
246 | } | |||
247 | ||||
248 | FunctionPass *llvm::createHexagonCFGOptimizer() { | |||
249 | return new HexagonCFGOptimizer(); | |||
250 | } |