llvm.org GIT mirror llvm / d1b2c1e
- In thumb mode, if size of MachineFunction is >= 2048, force LR to be spilled (if it is not already). - If LR is spilled, use BL to implement far jumps. LR is not used as a GPR in thumb mode so it can be clobbered if it is properly spilled / restored in prologue / epilogue. - If LR is force spilled but no far jump has been emitted, try undo'ing the spill by: push lr -> delete pop pc -> bx lr git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33650 91177308-0d34-0410-b5e6-96231b3b80d8 Evan Cheng 13 years ago
3 changed file(s) with 124 addition(s) and 42 deletion(s). Raw diff Collapse all Expand all
2828 #include
2929 using namespace llvm;
3030
31 STATISTIC(NumSplit, "Number of uncond branches inserted");
31 STATISTIC(NumSplit, "Number of uncond branches inserted");
32 STATISTIC(NumCBrFixed, "Number of cond branches fixed");
33 STATISTIC(NumUBrFixed, "Number of uncond branches fixed");
3234
3335 namespace {
3436 /// ARMConstantIslands - Due to limited pc-relative displacements, ARM
8789 ///
8890 std::vector ImmBranches;
8991
92 /// PushPopMIs - Keep track of all the Thumb push / pop instructions.
93 ///
94 std::vector PushPopMIs;
95
96 /// HasFarJump - True if any far jump instruction has been emitted during
97 /// the branch fix up pass.
98 bool HasFarJump;
99
90100 const TargetInstrInfo *TII;
101 const ARMFunctionInfo *AFI;
91102 public:
92103 virtual bool runOnMachineFunction(MachineFunction &Fn);
93104
104115 void UpdateForInsertedWaterBlock(MachineBasicBlock *NewBB);
105116 bool HandleConstantPoolUser(MachineFunction &Fn, CPUser &U);
106117 bool BBIsInBranchRange(MachineInstr *MI, MachineBasicBlock *BB, unsigned D);
107 bool FixUpImmediateBranch(MachineFunction &Fn, ImmBranch &Br);
118 bool FixUpImmediateBr(MachineFunction &Fn, ImmBranch &Br);
119 bool FixUpConditionalBr(MachineFunction &Fn, ImmBranch &Br);
120 bool FixUpUnconditionalBr(MachineFunction &Fn, ImmBranch &Br);
121 bool UndoLRSpillRestore();
108122
109123 unsigned GetOffsetOf(MachineInstr *MI) const;
110124 unsigned GetOffsetOf(MachineBasicBlock *MBB) const;
121135 MachineConstantPool &MCP = *Fn.getConstantPool();
122136
123137 TII = Fn.getTarget().getInstrInfo();
124
138 AFI = Fn.getInfo();
139
140 HasFarJump = false;
141
125142 // Renumber all of the machine basic blocks in the function, guaranteeing that
126143 // the numbers agree with the position of the block in the function.
127144 Fn.RenumberBlocks();
141158 InitialFunctionScan(Fn, CPEMIs);
142159 CPEMIs.clear();
143160
144 // Iteratively place constant pool entries until there is no change.
145 bool MadeChange;
146 do {
147 MadeChange = false;
161 // Iteratively place constant pool entries and fix up branches until there
162 // is no change.
163 bool MadeChange = false;
164 while (true) {
165 bool Change = false;
148166 for (unsigned i = 0, e = CPUsers.size(); i != e; ++i)
149 MadeChange |= HandleConstantPoolUser(Fn, CPUsers[i]);
167 Change |= HandleConstantPoolUser(Fn, CPUsers[i]);
150168 for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i)
151 MadeChange |= FixUpImmediateBranch(Fn, ImmBranches[i]);
152 } while (MadeChange);
153
169 Change |= FixUpImmediateBr(Fn, ImmBranches[i]);
170 if (!Change)
171 break;
172 MadeChange = true;
173 }
174
175 // If LR has been forced spilled and no far jumps (i.e. BL) has been issued.
176 // Undo the spill / restore of LR if possible.
177 if (!HasFarJump && AFI->isLRForceSpilled() && AFI->isThumbFunction())
178 MadeChange |= UndoLRSpillRestore();
179
154180 BBSizes.clear();
155181 WaterList.clear();
156182 CPUsers.clear();
157183 ImmBranches.clear();
158
159 return true;
184
185 return MadeChange;
160186 }
161187
162188 /// DoInitialPlacement - Perform the initial placement of the constant pool
257283 ImmBranches.push_back(ImmBranch(I, MaxDisp, isCond, UOpc));
258284 }
259285
286 if (Opc == ARM::tPUSH || Opc == ARM::tPOP_RET)
287 PushPopMIs.push_back(I);
288
260289 // Scan the instructions for constant pool operands.
261290 for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op)
262291 if (I->getOperand(op).isConstantPoolIndex()) {
379408 /// account for this change.
380409 void ARMConstantIslands::SplitBlockBeforeInstr(MachineInstr *MI) {
381410 MachineBasicBlock *OrigBB = MI->getParent();
382 const ARMFunctionInfo *AFI = OrigBB->getParent()->getInfo();
383411 bool isThumb = AFI->isThumbFunction();
384412
385413 // Create a new MBB for the code after the OrigBB.
523551 return false;
524552 }
525553
554 /// FixUpImmediateBr - Fix up an immediate branch whose destination is too far
555 /// away to fit in its displacement field.
556 bool ARMConstantIslands::FixUpImmediateBr(MachineFunction &Fn, ImmBranch &Br) {
557 MachineInstr *MI = Br.MI;
558 MachineBasicBlock *DestBB = MI->getOperand(0).getMachineBasicBlock();
559
560 if (BBIsInBranchRange(MI, DestBB, Br.MaxDisp))
561 return false;
562
563 if (!Br.isCond)
564 return FixUpUnconditionalBr(Fn, Br);
565 return FixUpConditionalBr(Fn, Br);
566 }
567
568 /// FixUpUnconditionalBr - Fix up an unconditional branches whose destination is
569 /// too far away to fit in its displacement field. If LR register has been
570 /// spilled in the epilogue, then we can use BL to implement a far jump.
571 /// Otherwise, add a intermediate branch instruction to to a branch.
572 bool
573 ARMConstantIslands::FixUpUnconditionalBr(MachineFunction &Fn, ImmBranch &Br) {
574 MachineInstr *MI = Br.MI;
575 MachineBasicBlock *MBB = MI->getParent();
576 assert(AFI->isThumbFunction() && "Expected a Thumb function!");
577
578 // Use BL to implement far jump.
579 Br.MaxDisp = (1 << 21) * 2;
580 MI->setInstrDescriptor(TII->get(ARM::tBfar));
581 BBSizes[MBB->getNumber()] += 2;
582 HasFarJump = true;
583 NumUBrFixed++;
584 return true;
585 }
586
526587 static inline unsigned getUncondBranchDisp(int Opc) {
527588 return (Opc == ARM::tB) ? (1<<10)*2 : (1<<23)*4;
528589 }
529590
530 /// FixUpImmediateBranch - Fix up immediate branches whose destination is too
531 /// far away to fit in its displacement field. If it is a conditional branch,
532 /// then it is converted to an inverse conditional branch + an unconditional
533 /// branch to the destination. If it is an unconditional branch, then it is
534 /// converted to a branch to a branch.
591 /// FixUpConditionalBr - Fix up a conditional branches whose destination is too
592 /// far away to fit in its displacement field. It is converted to an inverse
593 /// conditional branch + an unconditional branch to the destination.
535594 bool
536 ARMConstantIslands::FixUpImmediateBranch(MachineFunction &Fn, ImmBranch &Br) {
595 ARMConstantIslands::FixUpConditionalBr(MachineFunction &Fn, ImmBranch &Br) {
537596 MachineInstr *MI = Br.MI;
538597 MachineBasicBlock *DestBB = MI->getOperand(0).getMachineBasicBlock();
539598
540 if (BBIsInBranchRange(MI, DestBB, Br.MaxDisp))
541 return false;
542
543 if (!Br.isCond) {
544 // Unconditional branch. We have to insert a branch somewhere to perform
545 // a two level branch (branch to branch). FIXME: not yet implemented.
546 assert(false && "Can't handle unconditional branch yet!");
547 return false;
548 }
549
550 // Otherwise, add a unconditional branch to the destination and
551 // invert the branch condition to jump over it:
599 // Add a unconditional branch to the destination and invert the branch
600 // condition to jump over it:
552601 // blt L1
553602 // =>
554603 // bge L2
564613 MachineInstr *BackMI = &MBB->back();
565614 bool NeedSplit = (BackMI != MI) || !BBHasFallthrough(MBB);
566615
616 NumCBrFixed++;
567617 if (BackMI != MI) {
568618 if (next(MachineBasicBlock::iterator(MI)) == MBB->back() &&
569619 BackMI->getOpcode() == Br.UncondBr) {
605655 BBSizes[MBB->getNumber()] += ARM::GetInstSize(&MBB->back());
606656 return true;
607657 }
658
659
660 /// UndoLRSpillRestore - Remove Thumb push / pop instructions that only spills
661 /// LR / restores LR to pc.
662 bool ARMConstantIslands::UndoLRSpillRestore() {
663 bool MadeChange = false;
664 for (unsigned i = 0, e = PushPopMIs.size(); i != e; ++i) {
665 MachineInstr *MI = PushPopMIs[i];
666 if (MI->getNumOperands() == 1) {
667 if (MI->getOpcode() == ARM::tPOP_RET &&
668 MI->getOperand(0).getReg() == ARM::PC)
669 BuildMI(MI->getParent(), TII->get(ARM::tBX_RET));
670 MI->eraseFromParent();
671 MadeChange = true;
672 }
673 }
674 return MadeChange;
675 }
3535 /// processFunctionBeforeCalleeSavedScan().
3636 bool HasStackFrame;
3737
38 /// LRSpilled - True if the LR register has been spilled.
39 ///
40 bool LRSpilled;
38 /// LRSForceSpilled - True if the LR register has been for spilled to enable
39 /// far jump.
40 bool LRForceSpilled;
4141
4242 /// FramePtrSpillOffset - If HasStackFrame, this records the frame pointer
4343 /// spill stack offset.
7474 public:
7575 ARMFunctionInfo() :
7676 isThumb(false),
77 VarArgsRegSaveSize(0), HasStackFrame(false), LRSpilled(false),
77 VarArgsRegSaveSize(0), HasStackFrame(false), LRForceSpilled(false),
7878 FramePtrSpillOffset(0), GPRCS1Offset(0), GPRCS2Offset(0), DPRCSOffset(0),
7979 GPRCS1Size(0), GPRCS2Size(0), DPRCSSize(0), JumpTableUId(0) {}
8080
8181 ARMFunctionInfo(MachineFunction &MF) :
8282 isThumb(MF.getTarget().getSubtarget().isThumb()),
83 VarArgsRegSaveSize(0), HasStackFrame(false), LRSpilled(false),
83 VarArgsRegSaveSize(0), HasStackFrame(false), LRForceSpilled(false),
8484 FramePtrSpillOffset(0), GPRCS1Offset(0), GPRCS2Offset(0), DPRCSOffset(0),
8585 GPRCS1Size(0), GPRCS2Size(0), DPRCSSize(0), JumpTableUId(0) {}
8686
9292 bool hasStackFrame() const { return HasStackFrame; }
9393 void setHasStackFrame(bool s) { HasStackFrame = s; }
9494
95 bool isLRSpilled() const { return LRSpilled; }
96 void setLRIsSpilled(bool s) { LRSpilled = s; }
95 bool isLRForceSpilled() const { return LRForceSpilled; }
96 void setLRIsForceSpilled(bool s) { LRForceSpilled = s; }
9797
9898 unsigned getFramePtrSpillOffset() const { return FramePtrSpillOffset; }
9999 void setFramePtrSpillOffset(unsigned o) { FramePtrSpillOffset = o; }
769769 }
770770
771771 ARMFunctionInfo *AFI = MF.getInfo();
772 bool ForceLRSpill = false;
773 if (!LRSpilled && AFI->isThumbFunction()) {
774 unsigned FnSize = ARM::GetFunctionSize(MF);
775 // Force LR spill if the Thumb function size is > 2048. This enables the
776 // use of BL to implement far jump. If it turns out that it's not needed
777 // the branch fix up path will undo it.
778 if (FnSize >= (1 << 11)) {
779 CanEliminateFrame = false;
780 ForceLRSpill = true;
781 }
782 }
783
772784 if (!CanEliminateFrame) {
773785 AFI->setHasStackFrame(true);
774786
775787 // If LR is not spilled, but at least one of R4, R5, R6, and R7 is spilled.
776788 // Spill LR as well so we can fold BX_RET to the registers restore (LDM).
777789 if (!LRSpilled && CS1Spilled) {
778 LRSpilled = true;
779790 MF.changePhyRegUsed(ARM::LR, true);
780791 NumGPRSpills++;
781792 UnspilledCS1GPRs.erase(std::find(UnspilledCS1GPRs.begin(),
782793 UnspilledCS1GPRs.end(), (unsigned)ARM::LR));
794 ForceLRSpill = false;
783795 }
784796
785797 if (STI.isTargetDarwin()) {
799811 }
800812 }
801813
802 // Remembe if LR has been spilled.
803 AFI->setLRIsSpilled(LRSpilled);
814 if (ForceLRSpill) {
815 MF.changePhyRegUsed(ARM::LR, true);
816 AFI->setLRIsForceSpilled(true);
817 }
804818 }
805819
806820 /// Move iterator pass the next bunch of callee save load / store ops for