[PPC] Refactor PPCBranchSelector.cpp

This patch splits the huge function PPCBranchSelector.cpp:runOnMachineFunction into several smaller functions.

No functional change.

Differential Revision: https://reviews.llvm.org/D59623

llvm-svn: 357033
This commit is contained in:
Guozhi Wei 2019-03-26 21:27:38 +00:00
parent c74271c537
commit 330dcd9dab
1 changed files with 174 additions and 133 deletions

View File

@ -48,6 +48,17 @@ namespace {
// size that is due to potential padding.
std::vector<std::pair<unsigned, unsigned>> BlockSizes;
// The first block number which has imprecise instruction address.
int FirstImpreciseBlock = -1;
unsigned GetAlignmentAdjustment(MachineBasicBlock &MBB, unsigned Offset);
unsigned ComputeBlockSizes(MachineFunction &Fn);
void modifyAdjustment(MachineFunction &Fn);
int computeBranchSize(MachineFunction &Fn,
const MachineBasicBlock *Src,
const MachineBasicBlock *Dest,
unsigned BrOffset);
bool runOnMachineFunction(MachineFunction &Fn) override;
MachineFunctionProperties getRequiredProperties() const override {
@ -70,47 +81,47 @@ FunctionPass *llvm::createPPCBranchSelectionPass() {
return new PPCBSel();
}
bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) {
const PPCInstrInfo *TII =
static_cast<const PPCInstrInfo *>(Fn.getSubtarget().getInstrInfo());
// Give the blocks of the function a dense, in-order, numbering.
Fn.RenumberBlocks();
BlockSizes.resize(Fn.getNumBlockIDs());
// The first block number which has imprecise instruction address.
int FirstImpreciseBlock = -1;
/// In order to make MBB aligned, we need to add an adjustment value to the
/// original Offset.
unsigned PPCBSel::GetAlignmentAdjustment(MachineBasicBlock &MBB,
unsigned Offset) {
unsigned Align = MBB.getAlignment();
if (!Align)
return 0;
auto GetAlignmentAdjustment = [&FirstImpreciseBlock]
(MachineBasicBlock &MBB, unsigned Offset) -> unsigned {
unsigned Align = MBB.getAlignment();
if (!Align)
return 0;
unsigned AlignAmt = 1 << Align;
unsigned ParentAlign = MBB.getParent()->getAlignment();
unsigned AlignAmt = 1 << Align;
unsigned ParentAlign = MBB.getParent()->getAlignment();
if (Align <= ParentAlign)
return OffsetToAlignment(Offset, AlignAmt);
if (Align <= ParentAlign)
return OffsetToAlignment(Offset, AlignAmt);
// The alignment of this MBB is larger than the function's alignment, so we
// can't tell whether or not it will insert nops. Assume that it will.
if (FirstImpreciseBlock < 0)
FirstImpreciseBlock = MBB.getNumber();
return AlignAmt + OffsetToAlignment(Offset, AlignAmt);
}
// The alignment of this MBB is larger than the function's alignment, so we
// can't tell whether or not it will insert nops. Assume that it will.
if (FirstImpreciseBlock < 0)
FirstImpreciseBlock = MBB.getNumber();
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.
/// 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.
static inline unsigned GetInitialOffset(MachineFunction &Fn) {
unsigned InitialOffset = 0;
if (Fn.getSubtarget<PPCSubtarget>().isELFv2ABI() &&
!Fn.getRegInfo().use_empty(PPC::X2))
InitialOffset = 8;
return InitialOffset;
}
/// Measure each MBB and compute a size for the entire function.
unsigned PPCBSel::ComputeBlockSizes(MachineFunction &Fn) {
const PPCInstrInfo *TII =
static_cast<const PPCInstrInfo *>(Fn.getSubtarget().getInstrInfo());
unsigned FuncSize = GetInitialOffset(Fn);
// Measure each MBB and compute a size for the entire function.
unsigned FuncSize = InitialOffset;
for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
++MFI) {
MachineBasicBlock *MBB = &*MFI;
@ -138,6 +149,135 @@ bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) {
FuncSize += BlockSize;
}
return FuncSize;
}
/// Modify the basic block align adjustment.
void PPCBSel::modifyAdjustment(MachineFunction &Fn) {
unsigned Offset = GetInitialOffset(Fn);
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;
}
}
/// Determine the offset from the branch in Src block to the Dest block.
/// BrOffset is the offset of the branch instruction inside Src block.
int PPCBSel::computeBranchSize(MachineFunction &Fn,
const MachineBasicBlock *Src,
const MachineBasicBlock *Dest,
unsigned BrOffset) {
int BranchSize;
unsigned MaxAlign = 2;
bool NeedExtraAdjustment = false;
if (Dest->getNumber() <= Src->getNumber()) {
// If this is a backwards branch, the delta is the offset from the
// start of this block to this branch, plus the sizes of all blocks
// from this block to the dest.
BranchSize = BrOffset;
MaxAlign = std::max(MaxAlign, Src->getAlignment());
int DestBlock = Dest->getNumber();
BranchSize += BlockSizes[DestBlock].first;
for (unsigned i = DestBlock+1, e = Src->getNumber(); i < e; ++i) {
BranchSize += BlockSizes[i].first;
MaxAlign = std::max(MaxAlign,
Fn.getBlockNumbered(i)->getAlignment());
}
NeedExtraAdjustment = (FirstImpreciseBlock >= 0) &&
(DestBlock >= FirstImpreciseBlock);
} else {
// Otherwise, add the size of the blocks between this block and the
// dest to the number of bytes left in this block.
unsigned StartBlock = Src->getNumber();
BranchSize = BlockSizes[StartBlock].first - BrOffset;
MaxAlign = std::max(MaxAlign, Dest->getAlignment());
for (unsigned i = StartBlock+1, e = Dest->getNumber(); i != e; ++i) {
BranchSize += BlockSizes[i].first;
MaxAlign = std::max(MaxAlign,
Fn.getBlockNumbered(i)->getAlignment());
}
NeedExtraAdjustment = (FirstImpreciseBlock >= 0) &&
(Src->getNumber() >= FirstImpreciseBlock);
}
// We tend to over estimate code size due to large alignment and
// inline assembly. Usually it causes larger computed branch offset.
// But sometimes it may also causes smaller computed branch offset
// than actual branch offset. If the offset is close to the limit of
// encoding, it may cause problem at run time.
// Following is a simplified example.
//
// actual estimated
// address address
// ...
// bne Far 100 10c
// .p2align 4
// Near: 110 110
// ...
// Far: 8108 8108
//
// Actual offset: 0x8108 - 0x100 = 0x8008
// Computed offset: 0x8108 - 0x10c = 0x7ffc
//
// This example also shows when we can get the largest gap between
// estimated offset and actual offset. If there is an aligned block
// ABB between branch and target, assume its alignment is <align>
// bits. Now consider the accumulated function size FSIZE till the end
// of previous block PBB. If the estimated FSIZE is multiple of
// 2^<align>, we don't need any padding for the estimated address of
// ABB. If actual FSIZE at the end of PBB is 4 bytes more than
// multiple of 2^<align>, then we need (2^<align> - 4) bytes of
// padding. It also means the actual branch offset is (2^<align> - 4)
// larger than computed offset. Other actual FSIZE needs less padding
// bytes, so causes smaller gap between actual and computed offset.
//
// On the other hand, if the inline asm or large alignment occurs
// between the branch block and destination block, the estimated address
// can be <delta> larger than actual address. If padding bytes are
// needed for a later aligned block, the actual number of padding bytes
// is at most <delta> more than estimated padding bytes. So the actual
// aligned block address is less than or equal to the estimated aligned
// block address. So the actual branch offset is less than or equal to
// computed branch offset.
//
// The computed offset is at most ((1 << alignment) - 4) bytes smaller
// than actual offset. So we add this number to the offset for safety.
if (NeedExtraAdjustment)
BranchSize += (1 << MaxAlign) - 4;
return BranchSize;
}
bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) {
const PPCInstrInfo *TII =
static_cast<const PPCInstrInfo *>(Fn.getSubtarget().getInstrInfo());
// Give the blocks of the function a dense, in-order, numbering.
Fn.RenumberBlocks();
BlockSizes.resize(Fn.getNumBlockIDs());
FirstImpreciseBlock = -1;
// Measure each MBB and compute a size for the entire function.
unsigned FuncSize = ComputeBlockSizes(Fn);
// If the entire function is smaller than the displacement of a branch field,
// we know we don't need to shrink any branches in this function. This is a
// common case.
@ -185,87 +325,7 @@ bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) {
// Determine the offset from the current branch to the destination
// block.
int BranchSize;
unsigned MaxAlign = 2;
bool NeedExtraAdjustment = false;
if (Dest->getNumber() <= MBB.getNumber()) {
// If this is a backwards branch, the delta is the offset from the
// start of this block to this branch, plus the sizes of all blocks
// from this block to the dest.
BranchSize = MBBStartOffset;
MaxAlign = std::max(MaxAlign, MBB.getAlignment());
int DestBlock = Dest->getNumber();
BranchSize += BlockSizes[DestBlock].first;
for (unsigned i = DestBlock+1, e = MBB.getNumber(); i < e; ++i) {
BranchSize += BlockSizes[i].first;
MaxAlign = std::max(MaxAlign,
Fn.getBlockNumbered(i)->getAlignment());
}
NeedExtraAdjustment = (FirstImpreciseBlock >= 0) &&
(DestBlock >= FirstImpreciseBlock);
} else {
// Otherwise, add the size of the blocks between this block and the
// dest to the number of bytes left in this block.
unsigned StartBlock = MBB.getNumber();
BranchSize = BlockSizes[StartBlock].first - MBBStartOffset;
MaxAlign = std::max(MaxAlign, Dest->getAlignment());
for (unsigned i = StartBlock+1, e = Dest->getNumber(); i != e; ++i) {
BranchSize += BlockSizes[i].first;
MaxAlign = std::max(MaxAlign,
Fn.getBlockNumbered(i)->getAlignment());
}
NeedExtraAdjustment = (FirstImpreciseBlock >= 0) &&
(MBB.getNumber() >= FirstImpreciseBlock);
}
// We tend to over estimate code size due to large alignment and
// inline assembly. Usually it causes larger computed branch offset.
// But sometimes it may also causes smaller computed branch offset
// than actual branch offset. If the offset is close to the limit of
// encoding, it may cause problem at run time.
// Following is a simplified example.
//
// actual estimated
// address address
// ...
// bne Far 100 10c
// .p2align 4
// Near: 110 110
// ...
// Far: 8108 8108
//
// Actual offset: 0x8108 - 0x100 = 0x8008
// Computed offset: 0x8108 - 0x10c = 0x7ffc
//
// This example also shows when we can get the largest gap between
// estimated offset and actual offset. If there is an aligned block
// ABB between branch and target, assume its alignment is <align>
// bits. Now consider the accumulated function size FSIZE till the end
// of previous block PBB. If the estimated FSIZE is multiple of
// 2^<align>, we don't need any padding for the estimated address of
// ABB. If actual FSIZE at the end of PBB is 4 bytes more than
// multiple of 2^<align>, then we need (2^<align> - 4) bytes of
// padding. It also means the actual branch offset is (2^<align> - 4)
// larger than computed offset. Other actual FSIZE needs less padding
// bytes, so causes smaller gap between actual and computed offset.
//
// On the other hand, if the inline asm or large alignment occurs
// between the branch block and destination block, the estimated address
// can be <delta> larger than actual address. If padding bytes are
// needed for a later aligned block, the actual number of padding bytes
// is at most <delta> more than estimated padding bytes. So the actual
// aligned block address is less than or equal to the estimated aligned
// block address. So the actual branch offset is less than or equal to
// computed branch offset.
//
// The computed offset is at most ((1 << alignment) - 4) bytes smaller
// than actual offset. So we add this number to the offset for safety.
if (NeedExtraAdjustment)
BranchSize += (1 << MaxAlign) - 4;
int BranchSize = computeBranchSize(Fn, &MBB, Dest, MBBStartOffset);
// If this branch is in range, ignore it.
if (isInt<16>(BranchSize)) {
@ -324,26 +384,7 @@ bool PPCBSel::runOnMachineFunction(MachineFunction &Fn) {
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;
}
modifyAdjustment(Fn);
}
EverMadeChange |= MadeChange;