Line data Source code
1 : //===-- AArch64BranchRelaxation.cpp - AArch64 branch relaxation -----------===//
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 : #include "AArch64.h"
11 : #include "AArch64InstrInfo.h"
12 : #include "AArch64MachineFunctionInfo.h"
13 : #include "AArch64Subtarget.h"
14 : #include "llvm/ADT/SmallVector.h"
15 : #include "llvm/ADT/Statistic.h"
16 : #include "llvm/CodeGen/MachineFunctionPass.h"
17 : #include "llvm/CodeGen/MachineInstrBuilder.h"
18 : #include "llvm/Support/CommandLine.h"
19 : #include "llvm/Support/Debug.h"
20 : #include "llvm/Support/ErrorHandling.h"
21 : #include "llvm/Support/Format.h"
22 : #include "llvm/Support/raw_ostream.h"
23 : using namespace llvm;
24 :
25 : #define DEBUG_TYPE "aarch64-branch-relax"
26 :
27 : STATISTIC(NumSplit, "Number of basic blocks split");
28 : STATISTIC(NumConditionalRelaxed, "Number of conditional branches relaxed");
29 :
30 : namespace llvm {
31 : void initializeAArch64BranchRelaxationPass(PassRegistry &);
32 : }
33 :
34 : #define AARCH64_BR_RELAX_NAME "AArch64 branch relaxation pass"
35 :
36 : namespace {
37 2445 : class AArch64BranchRelaxation : public MachineFunctionPass {
38 : /// BasicBlockInfo - Information about the offset and size of a single
39 : /// basic block.
40 : struct BasicBlockInfo {
41 : /// Offset - Distance from the beginning of the function to the beginning
42 : /// of this basic block.
43 : ///
44 : /// The offset is always aligned as required by the basic block.
45 : unsigned Offset;
46 :
47 : /// Size - Size of the basic block in bytes. If the block contains
48 : /// inline assembly, this is a worst case estimate.
49 : ///
50 : /// The size does not include any alignment padding whether from the
51 : /// beginning of the block, or from an aligned jump table at the end.
52 : unsigned Size;
53 :
54 11508 : BasicBlockInfo() : Offset(0), Size(0) {}
55 :
56 : /// Compute the offset immediately following this block. If LogAlign is
57 : /// specified, return the offset the successor block will get if it has
58 : /// this alignment.
59 : unsigned postOffset(unsigned LogAlign = 0) const {
60 1778 : unsigned PO = Offset + Size;
61 1778 : unsigned Align = 1 << LogAlign;
62 1778 : return (PO + Align - 1) / Align * Align;
63 : }
64 : };
65 :
66 : SmallVector<BasicBlockInfo, 16> BlockInfo;
67 :
68 : MachineFunction *MF;
69 : const AArch64InstrInfo *TII;
70 :
71 : bool relaxBranchInstructions();
72 : void scanFunction();
73 : MachineBasicBlock *splitBlockBeforeInstr(MachineInstr &MI);
74 : void adjustBlockOffsets(MachineBasicBlock &MBB);
75 : bool isBlockInRange(const MachineInstr &MI, const MachineBasicBlock &BB) const;
76 :
77 : unsigned insertInvertedConditionalBranch(MachineBasicBlock &SrcBB,
78 : MachineBasicBlock::iterator InsPt,
79 : const DebugLoc &DL,
80 : const MachineInstr &OldBr,
81 : MachineBasicBlock &NewDestBB) const;
82 : unsigned insertUnconditionalBranch(MachineBasicBlock &MBB,
83 : MachineBasicBlock &NewDestBB,
84 : const DebugLoc &DL) const;
85 :
86 : bool fixupConditionalBranch(MachineInstr &MI);
87 : void computeBlockSize(const MachineBasicBlock &MBB);
88 : unsigned getInstrOffset(const MachineInstr &MI) const;
89 : void dumpBBs();
90 : void verify();
91 :
92 : public:
93 : static char ID;
94 1644 : AArch64BranchRelaxation() : MachineFunctionPass(ID) {
95 822 : initializeAArch64BranchRelaxationPass(*PassRegistry::getPassRegistry());
96 822 : }
97 :
98 : bool runOnMachineFunction(MachineFunction &MF) override;
99 :
100 819 : const char *getPassName() const override {
101 819 : return AARCH64_BR_RELAX_NAME;
102 : }
103 : };
104 : char AArch64BranchRelaxation::ID = 0;
105 : }
106 :
107 240270 : INITIALIZE_PASS(AArch64BranchRelaxation, "aarch64-branch-relax",
108 : AARCH64_BR_RELAX_NAME, false, false)
109 :
110 : /// verify - check BBOffsets, BBSizes, alignment of islands
111 : void AArch64BranchRelaxation::verify() {
112 : #ifndef NDEBUG
113 : unsigned PrevNum = MF->begin()->getNumber();
114 : for (MachineBasicBlock &MBB : *MF) {
115 : unsigned Align = MBB.getAlignment();
116 : unsigned Num = MBB.getNumber();
117 : assert(BlockInfo[Num].Offset % (1u << Align) == 0);
118 : assert(!Num || BlockInfo[PrevNum].postOffset() <= BlockInfo[Num].Offset);
119 : PrevNum = Num;
120 : }
121 : #endif
122 : }
123 :
124 : /// print block size and offset information - debugging
125 : void AArch64BranchRelaxation::dumpBBs() {
126 : for (auto &MBB : *MF) {
127 : const BasicBlockInfo &BBI = BlockInfo[MBB.getNumber()];
128 : dbgs() << format("BB#%u\toffset=%08x\t", MBB.getNumber(), BBI.Offset)
129 : << format("size=%#x\n", BBI.Size);
130 : }
131 : }
132 :
133 : // FIXME: This is a less precise version of MachineBasicBlock::canFallThrough?
134 :
135 : /// \returns true if the specified basic block can fallthrough
136 : /// into the block immediately after it.
137 6 : static bool hasFallthrough(const MachineBasicBlock &MBB) {
138 : // Get the next machine basic block in the function.
139 6 : MachineFunction::const_iterator MBBI(MBB);
140 :
141 : // Can't fall off end of function.
142 6 : auto NextBB = std::next(MBBI);
143 12 : if (NextBB == MBB.getParent()->end())
144 : return false;
145 :
146 6 : return MBB.isSuccessor(&*NextBB);
147 : }
148 :
149 : /// scanFunction - Do the initial scan of the function, building up
150 : /// information about each block.
151 9771 : void AArch64BranchRelaxation::scanFunction() {
152 19542 : BlockInfo.clear();
153 19542 : BlockInfo.resize(MF->getNumBlockIDs());
154 :
155 : // First thing, compute the size of all basic blocks, and see if the function
156 : // has any inline assembly in it. If so, we have to be conservative about
157 : // alignment assumptions, as we don't know for sure the size of any
158 : // instructions in the inline assembly.
159 40817 : for (MachineBasicBlock &MBB : *MF)
160 11504 : computeBlockSize(MBB);
161 :
162 : // Compute block offsets and known bits.
163 29313 : adjustBlockOffsets(*MF->begin());
164 9771 : }
165 :
166 : /// computeBlockSize - Compute the size for MBB.
167 : /// This function updates BlockInfo directly.
168 11512 : void AArch64BranchRelaxation::computeBlockSize(const MachineBasicBlock &MBB) {
169 11512 : unsigned Size = 0;
170 158664 : for (const MachineInstr &MI : MBB)
171 56308 : Size += TII->getInstSizeInBytes(MI);
172 23024 : BlockInfo[MBB.getNumber()].Size = Size;
173 11512 : }
174 :
175 : /// getInstrOffset - Return the current offset of the specified machine
176 : /// instruction from the start of the function. This offset changes as stuff is
177 : /// moved around inside the function.
178 891 : unsigned AArch64BranchRelaxation::getInstrOffset(const MachineInstr &MI) const {
179 891 : const MachineBasicBlock *MBB = MI.getParent();
180 :
181 : // The offset is composed of two things: the sum of the sizes of all MBB's
182 : // before this instruction's block, and the offset from the start of the block
183 : // it is in.
184 1782 : unsigned Offset = BlockInfo[MBB->getNumber()].Offset;
185 :
186 : // Sum instructions before MI in MBB.
187 4690 : for (MachineBasicBlock::const_iterator I = MBB->begin(); &*I != &MI; ++I) {
188 : assert(I != MBB->end() && "Didn't find MI in its own basic block?");
189 2908 : Offset += TII->getInstSizeInBytes(*I);
190 : }
191 :
192 891 : return Offset;
193 : }
194 :
195 9784 : void AArch64BranchRelaxation::adjustBlockOffsets(MachineBasicBlock &Start) {
196 9784 : unsigned PrevNum = Start.getNumber();
197 50694 : for (auto &MBB : make_range(MachineFunction::iterator(Start), MF->end())) {
198 11558 : unsigned Num = MBB.getNumber();
199 11558 : if (!Num) // block zero is never changed from offset zero.
200 : continue;
201 : // Get the offset and known bits at the end of the layout predecessor.
202 : // Include the alignment of the current block.
203 1778 : unsigned LogAlign = MBB.getAlignment();
204 7112 : BlockInfo[Num].Offset = BlockInfo[PrevNum].postOffset(LogAlign);
205 1778 : PrevNum = Num;
206 : }
207 9784 : }
208 :
209 : /// Split the basic block containing MI into two blocks, which are joined by
210 : /// an unconditional branch. Update data structures and renumber blocks to
211 : /// account for this change and returns the newly created block.
212 : /// NOTE: Successor list of the original BB is out of date after this function,
213 : /// and must be updated by the caller! Other transforms follow using this
214 : /// utility function, so no point updating now rather than waiting.
215 : MachineBasicBlock *
216 4 : AArch64BranchRelaxation::splitBlockBeforeInstr(MachineInstr &MI) {
217 4 : MachineBasicBlock *OrigBB = MI.getParent();
218 :
219 : // Create a new MBB for the code after the OrigBB.
220 : MachineBasicBlock *NewBB =
221 4 : MF->CreateMachineBasicBlock(OrigBB->getBasicBlock());
222 16 : MF->insert(++OrigBB->getIterator(), NewBB);
223 :
224 : // Splice the instructions starting with MI over to NewBB.
225 20 : NewBB->splice(NewBB->end(), OrigBB, MI.getIterator(), OrigBB->end());
226 :
227 : // Add an unconditional branch from OrigBB to NewBB.
228 : // Note the new unconditional branch is not being recorded.
229 : // There doesn't seem to be meaningful DebugInfo available; this doesn't
230 : // correspond to anything in the source.
231 8 : insertUnconditionalBranch(*OrigBB, *NewBB, DebugLoc());
232 :
233 : // Insert an entry into BlockInfo to align it properly with the block numbers.
234 8 : BlockInfo.insert(BlockInfo.begin() + NewBB->getNumber(), BasicBlockInfo());
235 :
236 : // Figure out how large the OrigBB is. As the first half of the original
237 : // block, it cannot contain a tablejump. The size includes
238 : // the new jump we added. (It should be possible to do this without
239 : // recounting everything, but it's very confusing, and this is rarely
240 : // executed.)
241 4 : computeBlockSize(*OrigBB);
242 :
243 : // Figure out how large the NewMBB is. As the second half of the original
244 : // block, it may contain a tablejump.
245 4 : computeBlockSize(*NewBB);
246 :
247 : // All BBOffsets following these blocks must be modified.
248 4 : adjustBlockOffsets(*OrigBB);
249 :
250 4 : ++NumSplit;
251 :
252 4 : return NewBB;
253 : }
254 :
255 : /// isBlockInRange - Returns true if the distance between specific MI and
256 : /// specific BB can fit in MI's displacement field.
257 891 : bool AArch64BranchRelaxation::isBlockInRange(
258 : const MachineInstr &MI, const MachineBasicBlock &DestBB) const {
259 891 : unsigned BrOffset = getInstrOffset(MI);
260 1782 : unsigned DestOffset = BlockInfo[DestBB.getNumber()].Offset;
261 :
262 1782 : if (TII->isBranchInRange(MI.getOpcode(), BrOffset, DestOffset))
263 : return true;
264 :
265 : DEBUG(
266 : dbgs() << "Out of range branch to destination BB#" << DestBB.getNumber()
267 : << " from BB#" << MI.getParent()->getNumber()
268 : << " to " << DestOffset
269 : << " offset " << static_cast<int>(DestOffset - BrOffset)
270 : << '\t' << MI
271 : );
272 :
273 10 : return false;
274 : }
275 :
276 900 : static MachineBasicBlock *getDestBlock(const MachineInstr &MI) {
277 1800 : switch (MI.getOpcode()) {
278 : default:
279 0 : llvm_unreachable("unexpected opcode!");
280 : case AArch64::B:
281 0 : return MI.getOperand(0).getMBB();
282 : case AArch64::TBZW:
283 : case AArch64::TBNZW:
284 : case AArch64::TBZX:
285 : case AArch64::TBNZX:
286 161 : return MI.getOperand(2).getMBB();
287 : case AArch64::CBZW:
288 : case AArch64::CBNZW:
289 : case AArch64::CBZX:
290 : case AArch64::CBNZX:
291 : case AArch64::Bcc:
292 739 : return MI.getOperand(1).getMBB();
293 : }
294 : }
295 :
296 9 : static unsigned getOppositeConditionOpcode(unsigned Opc) {
297 9 : switch (Opc) {
298 : default:
299 0 : llvm_unreachable("unexpected opcode!");
300 : case AArch64::TBNZW: return AArch64::TBZW;
301 0 : case AArch64::TBNZX: return AArch64::TBZX;
302 0 : case AArch64::TBZW: return AArch64::TBNZW;
303 0 : case AArch64::TBZX: return AArch64::TBNZX;
304 1 : case AArch64::CBNZW: return AArch64::CBZW;
305 0 : case AArch64::CBNZX: return AArch64::CBZX;
306 0 : case AArch64::CBZW: return AArch64::CBNZW;
307 0 : case AArch64::CBZX: return AArch64::CBNZX;
308 6 : case AArch64::Bcc: return AArch64::Bcc; // Condition is an operand for Bcc.
309 : }
310 : }
311 :
312 : static inline void invertBccCondition(MachineInstr &MI) {
313 : assert(MI.getOpcode() == AArch64::Bcc && "Unexpected opcode!");
314 6 : MachineOperand &CCOp = MI.getOperand(0);
315 :
316 6 : AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(CCOp.getImm());
317 12 : CCOp.setImm(AArch64CC::getInvertedCondCode(CC));
318 : }
319 :
320 : /// Insert a conditional branch at the end of \p MBB to \p NewDestBB, using the
321 : /// inverse condition of branch \p OldBr.
322 : /// \returns The number of bytes added to the block.
323 9 : unsigned AArch64BranchRelaxation::insertInvertedConditionalBranch(
324 : MachineBasicBlock &SrcMBB,
325 : MachineBasicBlock::iterator InsPt,
326 : const DebugLoc &DL,
327 : const MachineInstr &OldBr,
328 : MachineBasicBlock &NewDestBB) const {
329 18 : unsigned OppositeCondOpc = getOppositeConditionOpcode(OldBr.getOpcode());
330 :
331 : MachineInstrBuilder MIB =
332 18 : BuildMI(SrcMBB, InsPt, DL, TII->get(OppositeCondOpc))
333 18 : .addOperand(OldBr.getOperand(0));
334 :
335 18 : unsigned Opc = OldBr.getOpcode();
336 :
337 9 : if (Opc == AArch64::TBZW || Opc == AArch64::TBNZW ||
338 7 : Opc == AArch64::TBZX || Opc == AArch64::TBNZX)
339 4 : MIB.addOperand(OldBr.getOperand(1));
340 :
341 18 : if (OldBr.getOpcode() == AArch64::Bcc)
342 6 : invertBccCondition(*MIB);
343 :
344 9 : MIB.addMBB(&NewDestBB);
345 :
346 9 : return TII->getInstSizeInBytes(*MIB);
347 : }
348 :
349 : /// Insert an unconditional branch at the end of \p MBB to \p DestBB.
350 : /// \returns the number of bytes emitted.
351 13 : unsigned AArch64BranchRelaxation::insertUnconditionalBranch(
352 : MachineBasicBlock &MBB,
353 : MachineBasicBlock &DestBB,
354 : const DebugLoc &DL) const {
355 39 : MachineInstr *MI = BuildMI(&MBB, DL, TII->get(AArch64::B))
356 13 : .addMBB(&DestBB);
357 :
358 13 : return TII->getInstSizeInBytes(*MI);
359 : }
360 :
361 : static void changeBranchDestBlock(MachineInstr &MI,
362 : MachineBasicBlock &NewDestBB) {
363 0 : unsigned OpNum = 0;
364 0 : unsigned Opc = MI.getOpcode();
365 :
366 0 : if (Opc != AArch64::B) {
367 0 : OpNum = (Opc == AArch64::TBZW ||
368 0 : Opc == AArch64::TBNZW ||
369 0 : Opc == AArch64::TBZX ||
370 0 : Opc == AArch64::TBNZX) ? 2 : 1;
371 : }
372 :
373 0 : MI.getOperand(OpNum).setMBB(&NewDestBB);
374 : }
375 :
376 : /// fixupConditionalBranch - Fix up a conditional branch whose destination is
377 : /// too far away to fit in its displacement field. It is converted to an inverse
378 : /// conditional branch + an unconditional branch to the destination.
379 9 : bool AArch64BranchRelaxation::fixupConditionalBranch(MachineInstr &MI) {
380 9 : MachineBasicBlock *DestBB = getDestBlock(MI);
381 :
382 : // Add an unconditional branch to the destination and invert the branch
383 : // condition to jump over it:
384 : // tbz L1
385 : // =>
386 : // tbnz L2
387 : // b L1
388 : // L2:
389 :
390 : // If the branch is at the end of its MBB and that has a fall-through block,
391 : // direct the updated conditional branch to the fall-through block. Otherwise,
392 : // split the MBB before the next instruction.
393 9 : MachineBasicBlock *MBB = MI.getParent();
394 9 : MachineInstr *BMI = &MBB->back();
395 9 : bool NeedSplit = (BMI != &MI) || !hasFallthrough(*MBB);
396 :
397 9 : if (BMI != &MI) {
398 12 : if (std::next(MachineBasicBlock::iterator(MI)) ==
399 12 : std::prev(MBB->getLastNonDebugInstr()) &&
400 0 : BMI->isUnconditionalBranch()) {
401 : // Last MI in the BB is an unconditional branch. We can simply invert the
402 : // condition and swap destinations:
403 : // beq L1
404 : // b L2
405 : // =>
406 : // bne L2
407 : // b L1
408 0 : MachineBasicBlock *NewDest = getDestBlock(*BMI);
409 0 : if (isBlockInRange(MI, *NewDest)) {
410 : DEBUG(dbgs() << " Invert condition and swap its destination with "
411 : << *BMI);
412 0 : changeBranchDestBlock(*BMI, *DestBB);
413 :
414 : int NewSize =
415 0 : insertInvertedConditionalBranch(*MBB, MI.getIterator(),
416 0 : MI.getDebugLoc(), MI, *NewDest);
417 0 : int OldSize = TII->getInstSizeInBytes(MI);
418 0 : BlockInfo[MBB->getNumber()].Size += (NewSize - OldSize);
419 0 : MI.eraseFromParent();
420 0 : return true;
421 : }
422 : }
423 : }
424 :
425 9 : if (NeedSplit) {
426 : // Analyze the branch so we know how to update the successor lists.
427 3 : MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
428 6 : SmallVector<MachineOperand, 2> Cond;
429 3 : bool Fail = TII->analyzeBranch(*MBB, TBB, FBB, Cond, false);
430 : assert(!Fail && "branches to relax should be analyzable");
431 : (void)Fail;
432 :
433 3 : MachineBasicBlock *NewBB = splitBlockBeforeInstr(MI);
434 : // No need for the branch to the next block. We're adding an unconditional
435 : // branch to the destination.
436 3 : int delta = TII->getInstSizeInBytes(MBB->back());
437 6 : BlockInfo[MBB->getNumber()].Size -= delta;
438 3 : MBB->back().eraseFromParent();
439 : // BlockInfo[SplitBB].Offset is wrong temporarily, fixed below
440 :
441 : // Update the successor lists according to the transformation to follow.
442 : // Do it here since if there's no split, no update is needed.
443 3 : MBB->replaceSuccessor(FBB, NewBB);
444 3 : NewBB->addSuccessor(FBB);
445 : }
446 :
447 27 : MachineBasicBlock &NextBB = *std::next(MachineFunction::iterator(MBB));
448 :
449 : DEBUG(dbgs() << " Insert B to BB#" << DestBB->getNumber()
450 : << ", invert condition and change dest. to BB#"
451 : << NextBB.getNumber() << '\n');
452 :
453 18 : unsigned &MBBSize = BlockInfo[MBB->getNumber()].Size;
454 :
455 : // Insert a new conditional branch and a new unconditional branch.
456 27 : MBBSize += insertInvertedConditionalBranch(*MBB, MBB->end(),
457 9 : MI.getDebugLoc(), MI, NextBB);
458 :
459 9 : MBBSize += insertUnconditionalBranch(*MBB, *DestBB, MI.getDebugLoc());
460 :
461 : // Remove the old conditional branch. It may or may not still be in MBB.
462 9 : MBBSize -= TII->getInstSizeInBytes(MI);
463 9 : MI.eraseFromParent();
464 :
465 : // Finally, keep the block offsets up to date.
466 9 : adjustBlockOffsets(*MBB);
467 9 : return true;
468 : }
469 :
470 9778 : bool AArch64BranchRelaxation::relaxBranchInstructions() {
471 9778 : bool Changed = false;
472 : // Relaxing branches involves creating new basic blocks, so re-eval
473 : // end() for termination.
474 40872 : for (MachineFunction::iterator I = MF->begin(); I != MF->end(); ++I) {
475 11538 : MachineBasicBlock &MBB = *I;
476 11538 : MachineBasicBlock::iterator J = MBB.getFirstTerminator();
477 23076 : if (J == MBB.end())
478 523 : continue;
479 :
480 11015 : MachineBasicBlock::iterator Next;
481 44234 : for (MachineBasicBlock::iterator J = MBB.getFirstTerminator();
482 33219 : J != MBB.end(); J = Next) {
483 11102 : Next = std::next(J);
484 11102 : MachineInstr &MI = *J;
485 :
486 11102 : if (MI.isConditionalBranch()) {
487 891 : MachineBasicBlock *DestBB = getDestBlock(MI);
488 891 : if (!isBlockInRange(MI, *DestBB)) {
489 34 : if (Next != MBB.end() && Next->isConditionalBranch()) {
490 : // If there are multiple conditional branches, this isn't an
491 : // analyzable block. Split later terminators into a new block so
492 : // each one will be analyzable.
493 :
494 1 : MachineBasicBlock *NewBB = splitBlockBeforeInstr(*Next);
495 1 : NewBB->transferSuccessors(&MBB);
496 1 : MBB.addSuccessor(NewBB);
497 1 : MBB.addSuccessor(DestBB);
498 :
499 : // Cleanup potential unconditional branch to successor block.
500 1 : NewBB->updateTerminator();
501 1 : MBB.updateTerminator();
502 : } else {
503 9 : fixupConditionalBranch(MI);
504 : ++NumConditionalRelaxed;
505 : }
506 :
507 10 : Changed = true;
508 :
509 : // This may have modified all of the terminators, so start over.
510 10 : Next = MBB.getFirstTerminator();
511 : }
512 :
513 : }
514 : }
515 : }
516 :
517 9778 : return Changed;
518 : }
519 :
520 9771 : bool AArch64BranchRelaxation::runOnMachineFunction(MachineFunction &mf) {
521 9771 : MF = &mf;
522 :
523 : DEBUG(dbgs() << "***** AArch64BranchRelaxation *****\n");
524 :
525 19542 : TII = MF->getSubtarget<AArch64Subtarget>().getInstrInfo();
526 :
527 : // Renumber all of the machine basic blocks in the function, guaranteeing that
528 : // the numbers agree with the position of the block in the function.
529 9771 : MF->RenumberBlocks();
530 :
531 : // Do the initial scan of the function, building up information about the
532 : // sizes of each block.
533 9771 : scanFunction();
534 :
535 : DEBUG(dbgs() << " Basic blocks before relaxation\n"; dumpBBs(););
536 :
537 9771 : bool MadeChange = false;
538 9778 : while (relaxBranchInstructions())
539 : MadeChange = true;
540 :
541 : // After a while, this might be made debug-only, but it is not expensive.
542 9771 : verify();
543 :
544 : DEBUG(dbgs() << " Basic blocks after relaxation\n\n"; dumpBBs());
545 :
546 19542 : BlockInfo.clear();
547 :
548 9771 : return MadeChange;
549 : }
550 :
551 : /// Returns an instance of the AArch64 Branch Relaxation pass.
552 821 : FunctionPass *llvm::createAArch64BranchRelaxation() {
553 821 : return new AArch64BranchRelaxation();
554 : }
|