|
18 | 18 | #include "llvm/IR/DebugLoc.h"
|
19 | 19 | #include "llvm/Support/ErrorHandling.h"
|
20 | 20 | #include <cassert>
|
21 |
| -#include <iterator> |
22 | 21 |
|
23 | 22 | #define GET_INSTRINFO_CTOR_DTOR
|
24 | 23 | #include "SBFGenInstrInfo.inc"
|
25 | 24 |
|
26 | 25 | using namespace llvm;
|
27 | 26 |
|
| 27 | +static inline bool isUncondBranchOpcode(int Opc) { return Opc == SBF::JMP; } |
| 28 | + |
| 29 | +static inline bool isCondBranchOpcode(int Opc) { |
| 30 | + switch (Opc) { |
| 31 | + case SBF::JEQ_ri: |
| 32 | + case SBF::JEQ_rr: |
| 33 | + case SBF::JUGT_ri: |
| 34 | + case SBF::JUGT_rr: |
| 35 | + case SBF::JUGE_ri: |
| 36 | + case SBF::JUGE_rr: |
| 37 | + case SBF::JNE_ri: |
| 38 | + case SBF::JNE_rr: |
| 39 | + case SBF::JSGT_ri: |
| 40 | + case SBF::JSGT_rr: |
| 41 | + case SBF::JSGE_ri: |
| 42 | + case SBF::JSGE_rr: |
| 43 | + case SBF::JULT_ri: |
| 44 | + case SBF::JULT_rr: |
| 45 | + case SBF::JULE_ri: |
| 46 | + case SBF::JULE_rr: |
| 47 | + case SBF::JSLT_ri: |
| 48 | + case SBF::JSLT_rr: |
| 49 | + case SBF::JSLE_ri: |
| 50 | + case SBF::JSLE_rr: |
| 51 | + return true; |
| 52 | + default: |
| 53 | + return false; |
| 54 | + } |
| 55 | +} |
| 56 | + |
| 57 | +static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target, |
| 58 | + SmallVectorImpl<MachineOperand> &Cond) { |
| 59 | + Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode())); |
| 60 | + Cond.push_back(LastInst->getOperand(0)); |
| 61 | + Cond.push_back(LastInst->getOperand(1)); |
| 62 | + Target = LastInst->getOperand(2).getMBB(); |
| 63 | +} |
| 64 | + |
28 | 65 | SBFInstrInfo::SBFInstrInfo()
|
29 | 66 | : SBFGenInstrInfo(SBF::ADJCALLSTACKDOWN, SBF::ADJCALLSTACKUP) {}
|
30 | 67 |
|
@@ -104,94 +141,262 @@ bool SBFInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
|
104 | 141 | MachineBasicBlock *&FBB,
|
105 | 142 | SmallVectorImpl<MachineOperand> &Cond,
|
106 | 143 | bool AllowModify) const {
|
107 |
| - // Start from the bottom of the block and work up, examining the |
108 |
| - // terminator instructions. |
109 |
| - MachineBasicBlock::iterator I = MBB.end(); |
110 |
| - while (I != MBB.begin()) { |
111 |
| - --I; |
112 |
| - if (I->isDebugInstr()) |
113 |
| - continue; |
114 |
| - |
115 |
| - // Working from the bottom, when we see a non-terminator |
116 |
| - // instruction, we're done. |
117 |
| - if (!isUnpredicatedTerminator(*I)) |
118 |
| - break; |
119 |
| - |
120 |
| - // A terminator that isn't a branch can't easily be handled |
121 |
| - // by this analysis. |
122 |
| - if (!I->isBranch()) |
123 |
| - return true; |
124 |
| - |
125 |
| - // Handle unconditional branches. |
126 |
| - if (I->getOpcode() == SBF::JMP) { |
127 |
| - if (!AllowModify) { |
128 |
| - TBB = I->getOperand(0).getMBB(); |
129 |
| - continue; |
130 |
| - } |
| 144 | + // If the block has no terminators, it just falls into the block after it. |
| 145 | + MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); |
| 146 | + if (I == MBB.end()) |
| 147 | + return false; |
| 148 | + |
| 149 | + if (!isUnpredicatedTerminator(*I)) |
| 150 | + return false; |
| 151 | + |
| 152 | + // Get the last instruction in the block. |
| 153 | + MachineInstr *LastInst = &*I; |
| 154 | + |
| 155 | + // If there is only one terminator instruction, process it. |
| 156 | + unsigned LastOpc = LastInst->getOpcode(); |
| 157 | + if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) { |
| 158 | + if (isUncondBranchOpcode(LastOpc)) { |
| 159 | + TBB = LastInst->getOperand(0).getMBB(); |
| 160 | + return false; |
| 161 | + } |
| 162 | + if (isCondBranchOpcode(LastOpc)) { |
| 163 | + // Block ends with fall-through condbranch. |
| 164 | + parseCondBranch(LastInst, TBB, Cond); |
| 165 | + return false; |
| 166 | + } |
| 167 | + return true; // Unknown case |
| 168 | + } |
| 169 | + |
| 170 | + // Get the instruction before it if it is a terminator. |
| 171 | + MachineInstr *SecondLastInst = &*I; |
| 172 | + unsigned SecondLastOpc = SecondLastInst->getOpcode(); |
131 | 173 |
|
132 |
| - // If the block has any instructions after a J, delete them. |
133 |
| - MBB.erase(std::next(I), MBB.end()); |
134 |
| - Cond.clear(); |
135 |
| - FBB = nullptr; |
136 |
| - |
137 |
| - // Delete the J if it's equivalent to a fall-through. |
138 |
| - if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { |
139 |
| - TBB = nullptr; |
140 |
| - I->eraseFromParent(); |
141 |
| - I = MBB.end(); |
142 |
| - continue; |
| 174 | + // If AllowModify is true and the block ends with two or more unconditional |
| 175 | + // branches, delete all but the first unconditional branch. |
| 176 | + if (AllowModify && isUncondBranchOpcode(LastOpc)) { |
| 177 | + while (isUncondBranchOpcode(SecondLastOpc)) { |
| 178 | + LastInst->eraseFromParent(); |
| 179 | + LastInst = SecondLastInst; |
| 180 | + LastOpc = LastInst->getOpcode(); |
| 181 | + if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) { |
| 182 | + // Return now the only terminator is an unconditional branch. |
| 183 | + TBB = LastInst->getOperand(0).getMBB(); |
| 184 | + return false; |
143 | 185 | }
|
| 186 | + SecondLastInst = &*I; |
| 187 | + SecondLastOpc = SecondLastInst->getOpcode(); |
| 188 | + } |
| 189 | + } |
144 | 190 |
|
145 |
| - // TBB is used to indicate the unconditinal destination. |
146 |
| - TBB = I->getOperand(0).getMBB(); |
147 |
| - continue; |
| 191 | + // If we're allowed to modify and the block ends in a unconditional branch |
| 192 | + // which could simply fallthrough, remove the branch. (Note: This case only |
| 193 | + // matters when we can't understand the whole sequence, otherwise it's also |
| 194 | + // handled by BranchFolding.cpp.) |
| 195 | + if (AllowModify && isUncondBranchOpcode(LastOpc) && |
| 196 | + MBB.isLayoutSuccessor(getBranchDestBlock(*LastInst))) { |
| 197 | + LastInst->eraseFromParent(); |
| 198 | + LastInst = SecondLastInst; |
| 199 | + LastOpc = LastInst->getOpcode(); |
| 200 | + if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) { |
| 201 | + assert(!isUncondBranchOpcode(LastOpc) && |
| 202 | + "unreachable unconditional branches removed above"); |
| 203 | + |
| 204 | + if (isCondBranchOpcode(LastOpc)) { |
| 205 | + // Block ends with fall-through condbranch. |
| 206 | + parseCondBranch(LastInst, TBB, Cond); |
| 207 | + return false; |
| 208 | + } |
| 209 | + return true; // Can't handle indirect branch. |
148 | 210 | }
|
149 |
| - // Cannot handle conditional branches |
| 211 | + SecondLastInst = &*I; |
| 212 | + SecondLastOpc = SecondLastInst->getOpcode(); |
| 213 | + } |
| 214 | + |
| 215 | + // If there are three terminators, we don't know what sort of block this is. |
| 216 | + if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I)) |
150 | 217 | return true;
|
| 218 | + |
| 219 | + // If the block ends with a conditional jump and a JA, handle it. |
| 220 | + if (isCondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) { |
| 221 | + parseCondBranch(SecondLastInst, TBB, Cond); |
| 222 | + FBB = LastInst->getOperand(0).getMBB(); |
| 223 | + return false; |
151 | 224 | }
|
152 | 225 |
|
153 |
| - return false; |
| 226 | + // If the block ends with two unconditional branches, handle it. The second |
| 227 | + // one is not executed, so remove it. |
| 228 | + if (isUncondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) { |
| 229 | + TBB = SecondLastInst->getOperand(0).getMBB(); |
| 230 | + I = LastInst; |
| 231 | + if (AllowModify) |
| 232 | + I->eraseFromParent(); |
| 233 | + return false; |
| 234 | + } |
| 235 | + |
| 236 | + // Otherwise, can't handle this. |
| 237 | + return true; |
154 | 238 | }
|
155 | 239 |
|
156 | 240 | unsigned SBFInstrInfo::insertBranch(MachineBasicBlock &MBB,
|
157 | 241 | MachineBasicBlock *TBB,
|
158 | 242 | MachineBasicBlock *FBB,
|
159 | 243 | ArrayRef<MachineOperand> Cond,
|
160 |
| - const DebugLoc &DL, |
161 |
| - int *BytesAdded) const { |
| 244 | + const DebugLoc &DL, int *BytesAdded) const { |
162 | 245 | assert(!BytesAdded && "code size not handled");
|
163 | 246 |
|
164 | 247 | // Shouldn't be a fall through.
|
165 | 248 | assert(TBB && "insertBranch must not be told to insert a fallthrough");
|
166 | 249 |
|
| 250 | + if (BytesAdded) |
| 251 | + *BytesAdded = 8; |
| 252 | + |
167 | 253 | if (Cond.empty()) {
|
168 | 254 | // Unconditional branch
|
169 | 255 | assert(!FBB && "Unconditional branch with multiple successors!");
|
170 | 256 | BuildMI(&MBB, DL, get(SBF::JMP)).addMBB(TBB);
|
171 | 257 | return 1;
|
172 | 258 | }
|
173 | 259 |
|
174 |
| - llvm_unreachable("Unexpected conditional branch"); |
| 260 | + // See the order we parse the jump information in `parseCondBranch` |
| 261 | + BuildMI(&MBB, DL, get(Cond[0].getImm())) |
| 262 | + .add(Cond[1]) |
| 263 | + .add(Cond[2]) |
| 264 | + .addMBB(TBB); |
| 265 | + |
| 266 | + if (FBB) { |
| 267 | + BuildMI(&MBB, DL, get(SBF::JMP)).addMBB(FBB); |
| 268 | + if (BytesAdded) |
| 269 | + *BytesAdded += 8; |
| 270 | + } |
| 271 | + |
| 272 | + return 1; |
175 | 273 | }
|
176 | 274 |
|
177 | 275 | unsigned SBFInstrInfo::removeBranch(MachineBasicBlock &MBB,
|
178 | 276 | int *BytesRemoved) const {
|
179 | 277 | assert(!BytesRemoved && "code size not handled");
|
180 | 278 |
|
181 |
| - MachineBasicBlock::iterator I = MBB.end(); |
182 |
| - unsigned Count = 0; |
183 |
| - |
184 |
| - while (I != MBB.begin()) { |
185 |
| - --I; |
186 |
| - if (I->isDebugInstr()) |
187 |
| - continue; |
188 |
| - if (I->getOpcode() != SBF::JMP) |
189 |
| - break; |
190 |
| - // Remove the branch. |
191 |
| - I->eraseFromParent(); |
192 |
| - I = MBB.end(); |
193 |
| - ++Count; |
| 279 | + MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); |
| 280 | + if (I == MBB.end()) |
| 281 | + return 0; |
| 282 | + |
| 283 | + if (!isUncondBranchOpcode(I->getOpcode()) && |
| 284 | + !isCondBranchOpcode(I->getOpcode())) |
| 285 | + return 0; |
| 286 | + |
| 287 | + // Remove the branch. |
| 288 | + I->eraseFromParent(); |
| 289 | + |
| 290 | + I = MBB.end(); |
| 291 | + |
| 292 | + if (I == MBB.begin()) { |
| 293 | + if (BytesRemoved) |
| 294 | + *BytesRemoved = 8; |
| 295 | + return 1; |
| 296 | + } |
| 297 | + |
| 298 | + --I; |
| 299 | + if (!isCondBranchOpcode(I->getOpcode())) { |
| 300 | + if (BytesRemoved) |
| 301 | + *BytesRemoved = 8; |
| 302 | + return 1; |
| 303 | + } |
| 304 | + |
| 305 | + // Remove the branch. |
| 306 | + I->eraseFromParent(); |
| 307 | + if (BytesRemoved) |
| 308 | + *BytesRemoved = 16; |
| 309 | + |
| 310 | + return 2; |
| 311 | +} |
| 312 | + |
| 313 | +bool SBFInstrInfo::reverseBranchCondition( |
| 314 | + SmallVectorImpl<MachineOperand> &Cond) const { |
| 315 | + switch (Cond[0].getImm()) { |
| 316 | + default: |
| 317 | + llvm_unreachable("Unknown conditional branch!"); |
| 318 | + case SBF::JEQ_ri: |
| 319 | + Cond[0].setImm(SBF::JNE_ri); |
| 320 | + break; |
| 321 | + case SBF::JEQ_rr: |
| 322 | + Cond[0].setImm(SBF::JNE_rr); |
| 323 | + break; |
| 324 | + case SBF::JUGT_ri: |
| 325 | + Cond[0].setImm(SBF::JULE_ri); |
| 326 | + break; |
| 327 | + case SBF::JUGT_rr: |
| 328 | + Cond[0].setImm(SBF::JULE_rr); |
| 329 | + break; |
| 330 | + case SBF::JUGE_ri: |
| 331 | + Cond[0].setImm(SBF::JULT_ri); |
| 332 | + break; |
| 333 | + case SBF::JUGE_rr: |
| 334 | + Cond[0].setImm(SBF::JULT_rr); |
| 335 | + break; |
| 336 | + case SBF::JNE_ri: |
| 337 | + Cond[0].setImm(SBF::JEQ_ri); |
| 338 | + break; |
| 339 | + case SBF::JNE_rr: |
| 340 | + Cond[0].setImm(SBF::JEQ_rr); |
| 341 | + break; |
| 342 | + case SBF::JSGT_ri: |
| 343 | + Cond[0].setImm(SBF::JSLE_ri); |
| 344 | + break; |
| 345 | + case SBF::JSGT_rr: |
| 346 | + Cond[0].setImm(SBF::JSLE_rr); |
| 347 | + break; |
| 348 | + case SBF::JSGE_ri: |
| 349 | + Cond[0].setImm(SBF::JSLT_ri); |
| 350 | + break; |
| 351 | + case SBF::JSGE_rr: |
| 352 | + Cond[0].setImm(SBF::JSLT_rr); |
| 353 | + break; |
| 354 | + case SBF::JULT_ri: |
| 355 | + Cond[0].setImm(SBF::JUGE_ri); |
| 356 | + break; |
| 357 | + case SBF::JULT_rr: |
| 358 | + Cond[0].setImm(SBF::JUGE_rr); |
| 359 | + break; |
| 360 | + case SBF::JULE_ri: |
| 361 | + Cond[0].setImm(SBF::JUGT_ri); |
| 362 | + break; |
| 363 | + case SBF::JULE_rr: |
| 364 | + Cond[0].setImm(SBF::JUGT_rr); |
| 365 | + break; |
| 366 | + case SBF::JSLT_ri: |
| 367 | + Cond[0].setImm(SBF::JSGE_ri); |
| 368 | + break; |
| 369 | + case SBF::JSLT_rr: |
| 370 | + Cond[0].setImm(SBF::JSGE_rr); |
| 371 | + break; |
| 372 | + case SBF::JSLE_ri: |
| 373 | + Cond[0].setImm(SBF::JSGT_ri); |
| 374 | + break; |
| 375 | + case SBF::JSLE_rr: |
| 376 | + Cond[0].setImm(SBF::JSGT_rr); |
| 377 | + break; |
194 | 378 | }
|
195 | 379 |
|
196 |
| - return Count; |
| 380 | + return false; |
| 381 | +} |
| 382 | + |
| 383 | +MachineBasicBlock * |
| 384 | +SBFInstrInfo::getBranchDestBlock(const MachineInstr &MI) const { |
| 385 | + unsigned Opcode = MI.getOpcode(); |
| 386 | + if (Opcode == SBF::JMP) { |
| 387 | + return MI.getOperand(0).getMBB(); |
| 388 | + } |
| 389 | + |
| 390 | + if (isCondBranchOpcode(Opcode)) { |
| 391 | + return MI.getOperand(2).getMBB(); |
| 392 | + } |
| 393 | + |
| 394 | + llvm_unreachable("unexpected opcode!"); |
| 395 | +} |
| 396 | + |
| 397 | +unsigned SBFInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { |
| 398 | + if (MI.getOpcode() == SBF::LD_imm64) |
| 399 | + return 16; |
| 400 | + |
| 401 | + return 8; |
197 | 402 | }
|
0 commit comments