summaryrefslogtreecommitdiff
path: root/lib/Target/PowerPC/PPCBranchSelector.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/PowerPC/PPCBranchSelector.cpp')
-rw-r--r--lib/Target/PowerPC/PPCBranchSelector.cpp81
1 files changed, 62 insertions, 19 deletions
diff --git a/lib/Target/PowerPC/PPCBranchSelector.cpp b/lib/Target/PowerPC/PPCBranchSelector.cpp
index 4d63c5b5703c..ae76386fdfb6 100644
--- a/lib/Target/PowerPC/PPCBranchSelector.cpp
+++ b/lib/Target/PowerPC/PPCBranchSelector.cpp
@@ -19,8 +19,10 @@
#include "MCTargetDesc/PPCPredicates.h"
#include "PPCInstrBuilder.h"
#include "PPCInstrInfo.h"
+#include "PPCSubtarget.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetSubtargetInfo.h"
@@ -41,19 +43,19 @@ namespace {
initializePPCBSelPass(*PassRegistry::getPassRegistry());
}
- /// BlockSizes - The sizes of the basic blocks in the function.
- std::vector<unsigned> BlockSizes;
+ // The sizes of the basic blocks in the function (the first
+ // element of the pair); the second element of the pair is the amount of the
+ // size that is due to potential padding.
+ std::vector<std::pair<unsigned, unsigned>> BlockSizes;
bool runOnMachineFunction(MachineFunction &Fn) override;
MachineFunctionProperties getRequiredProperties() const override {
return MachineFunctionProperties().set(
- MachineFunctionProperties::Property::AllVRegsAllocated);
+ MachineFunctionProperties::Property::NoVRegs);
}
- const char *getPassName() const override {
- return "PowerPC Branch Selector";
- }
+ StringRef getPassName() const override { return "PowerPC Branch Selector"; }
};
char PPCBSel::ID = 0;
}
@@ -92,8 +94,19 @@ bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) {
return AlignAmt + OffsetToAlignment(Offset, AlignAmt);
};
+ // We need to be careful about the offset of the first block in the function
+ // because it might not have the function's alignment. This happens because,
+ // under the ELFv2 ABI, for functions which require a TOC pointer, we add a
+ // two-instruction sequence to the start of the function.
+ // Note: This needs to be synchronized with the check in
+ // PPCLinuxAsmPrinter::EmitFunctionBodyStart.
+ unsigned InitialOffset = 0;
+ if (Fn.getSubtarget<PPCSubtarget>().isELFv2ABI() &&
+ !Fn.getRegInfo().use_empty(PPC::X2))
+ InitialOffset = 8;
+
// Measure each MBB and compute a size for the entire function.
- unsigned FuncSize = 0;
+ unsigned FuncSize = InitialOffset;
for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
++MFI) {
MachineBasicBlock *MBB = &*MFI;
@@ -102,15 +115,19 @@ bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) {
// alignment requirement.
if (MBB->getNumber() > 0) {
unsigned AlignExtra = GetAlignmentAdjustment(*MBB, FuncSize);
- BlockSizes[MBB->getNumber()-1] += AlignExtra;
+
+ auto &BS = BlockSizes[MBB->getNumber()-1];
+ BS.first += AlignExtra;
+ BS.second = AlignExtra;
+
FuncSize += AlignExtra;
}
unsigned BlockSize = 0;
for (MachineInstr &MI : *MBB)
- BlockSize += TII->GetInstSizeInBytes(MI);
+ BlockSize += TII->getInstSizeInBytes(MI);
- BlockSizes[MBB->getNumber()] = BlockSize;
+ BlockSizes[MBB->getNumber()].first = BlockSize;
FuncSize += BlockSize;
}
@@ -155,7 +172,7 @@ bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) {
Dest = I->getOperand(0).getMBB();
if (!Dest) {
- MBBStartOffset += TII->GetInstSizeInBytes(*I);
+ MBBStartOffset += TII->getInstSizeInBytes(*I);
continue;
}
@@ -169,14 +186,14 @@ bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) {
BranchSize = MBBStartOffset;
for (unsigned i = Dest->getNumber(), e = MBB.getNumber(); i != e; ++i)
- BranchSize += BlockSizes[i];
+ BranchSize += BlockSizes[i].first;
} else {
// Otherwise, add the size of the blocks between this block and the
// dest to the number of bytes left in this block.
BranchSize = -MBBStartOffset;
for (unsigned i = MBB.getNumber(), e = Dest->getNumber(); i != e; ++i)
- BranchSize += BlockSizes[i];
+ BranchSize += BlockSizes[i].first;
}
// If this branch is in range, ignore it.
@@ -186,9 +203,9 @@ bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) {
}
// Otherwise, we have to expand it to a long branch.
- MachineInstr *OldBranch = I;
- DebugLoc dl = OldBranch->getDebugLoc();
-
+ MachineInstr &OldBranch = *I;
+ DebugLoc dl = OldBranch.getDebugLoc();
+
if (I->getOpcode() == PPC::BCC) {
// The BCC operands are:
// 0. PPC branch predicate
@@ -222,16 +239,42 @@ bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) {
I = BuildMI(MBB, I, dl, TII->get(PPC::B)).addMBB(Dest);
// Remove the old branch from the function.
- OldBranch->eraseFromParent();
-
+ OldBranch.eraseFromParent();
+
// Remember that this instruction is 8-bytes, increase the size of the
// block by 4, remember to iterate.
- BlockSizes[MBB.getNumber()] += 4;
+ BlockSizes[MBB.getNumber()].first += 4;
MBBStartOffset += 8;
++NumExpanded;
MadeChange = true;
}
}
+
+ if (MadeChange) {
+ // If we're going to iterate again, make sure we've updated our
+ // padding-based contributions to the block sizes.
+ unsigned Offset = InitialOffset;
+ for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
+ ++MFI) {
+ MachineBasicBlock *MBB = &*MFI;
+
+ if (MBB->getNumber() > 0) {
+ auto &BS = BlockSizes[MBB->getNumber()-1];
+ BS.first -= BS.second;
+ Offset -= BS.second;
+
+ unsigned AlignExtra = GetAlignmentAdjustment(*MBB, Offset);
+
+ BS.first += AlignExtra;
+ BS.second = AlignExtra;
+
+ Offset += AlignExtra;
+ }
+
+ Offset += BlockSizes[MBB->getNumber()].first;
+ }
+ }
+
EverMadeChange |= MadeChange;
}