[GlobalISel] Preserve IR block layout.

It makes the output function layout more predictable;  the layout has
an effect on performance, we don't want it to be at the mercy of the
translator's visitation order and such.
The predictable output is also easier to digest.

getOrCreateBB isn't appropriately named anymore, as it never needs to
create anything.  Rename it and extract the MBB creation logic out of it.

A couple tests were sensitive to the order. Update them.

llvm-svn: 297868
This commit is contained in:
Ahmed Bougacha 2017-03-15 18:22:33 +00:00
parent d8319e99d8
commit a61c214f51
3 changed files with 55 additions and 48 deletions

View File

@ -388,8 +388,8 @@ private:
/// Get the MachineBasicBlock that represents \p BB. Specifically, the block
/// returned will be the head of the translated block (suitable for branch
/// destinations). If such basic block does not exist, it is created.
MachineBasicBlock &getOrCreateBB(const BasicBlock &BB);
/// destinations).
MachineBasicBlock &getMBB(const BasicBlock &BB);
/// Record \p NewPred as a Machine predecessor to `Edge.second`, corresponding
/// to `Edge.first` at the IR level. This is used when IRTranslation creates
@ -405,7 +405,7 @@ private:
auto RemappedEdge = MachinePreds.find(Edge);
if (RemappedEdge != MachinePreds.end())
return RemappedEdge->second;
return SmallVector<MachineBasicBlock *, 4>(1, &getOrCreateBB(*Edge.first));
return SmallVector<MachineBasicBlock *, 4>(1, &getMBB(*Edge.first));
}
public:
@ -420,10 +420,10 @@ public:
// CallLowering = MF.subtarget.getCallLowering()
// F = MF.getParent()
// MIRBuilder.reset(MF)
// MIRBuilder.getOrCreateBB(F.getEntryBB())
// getMBB(F.getEntryBB())
// CallLowering->translateArguments(MIRBuilder, F, ValToVReg)
// for each bb in F
// MIRBuilder.getOrCreateBB(bb)
// getMBB(bb)
// for each inst in bb
// if (!translate(MIRBuilder, inst, ValToVReg, ConstantToSequence))
// report_fatal_error("Don't know how to translate input");

View File

@ -140,15 +140,9 @@ unsigned IRTranslator::getMemOpAlignment(const Instruction &I) {
return Alignment ? Alignment : DL->getABITypeAlignment(ValTy);
}
MachineBasicBlock &IRTranslator::getOrCreateBB(const BasicBlock &BB) {
MachineBasicBlock &IRTranslator::getMBB(const BasicBlock &BB) {
MachineBasicBlock *&MBB = BBToMBB[&BB];
if (!MBB) {
MBB = MF->CreateMachineBasicBlock(&BB);
MF->push_back(MBB);
if (BB.hasAddressTaken())
MBB->setHasAddressTaken();
}
assert(MBB && "BasicBlock was not encountered before");
return *MBB;
}
@ -221,18 +215,18 @@ bool IRTranslator::translateBr(const User &U, MachineIRBuilder &MIRBuilder) {
// We want a G_BRCOND to the true BB followed by an unconditional branch.
unsigned Tst = getOrCreateVReg(*BrInst.getCondition());
const BasicBlock &TrueTgt = *cast<BasicBlock>(BrInst.getSuccessor(Succ++));
MachineBasicBlock &TrueBB = getOrCreateBB(TrueTgt);
MachineBasicBlock &TrueBB = getMBB(TrueTgt);
MIRBuilder.buildBrCond(Tst, TrueBB);
}
const BasicBlock &BrTgt = *cast<BasicBlock>(BrInst.getSuccessor(Succ));
MachineBasicBlock &TgtBB = getOrCreateBB(BrTgt);
MachineBasicBlock &TgtBB = getMBB(BrTgt);
MIRBuilder.buildBr(TgtBB);
// Link successors.
MachineBasicBlock &CurBB = MIRBuilder.getMBB();
for (const BasicBlock *Succ : BrInst.successors())
CurBB.addSuccessor(&getOrCreateBB(*Succ));
CurBB.addSuccessor(&getMBB(*Succ));
return true;
}
@ -256,7 +250,7 @@ bool IRTranslator::translateSwitch(const User &U,
MIRBuilder.buildICmp(CmpInst::ICMP_EQ, Tst, CaseValueReg, SwCondValue);
MachineBasicBlock &CurMBB = MIRBuilder.getMBB();
const BasicBlock *TrueBB = CaseIt.getCaseSuccessor();
MachineBasicBlock &TrueMBB = getOrCreateBB(*TrueBB);
MachineBasicBlock &TrueMBB = getMBB(*TrueBB);
MIRBuilder.buildBrCond(Tst, TrueMBB);
CurMBB.addSuccessor(&TrueMBB);
@ -272,7 +266,7 @@ bool IRTranslator::translateSwitch(const User &U,
}
// handle default case
const BasicBlock *DefaultBB = SwInst.getDefaultDest();
MachineBasicBlock &DefaultMBB = getOrCreateBB(*DefaultBB);
MachineBasicBlock &DefaultMBB = getMBB(*DefaultBB);
MIRBuilder.buildBr(DefaultMBB);
MachineBasicBlock &CurMBB = MIRBuilder.getMBB();
CurMBB.addSuccessor(&DefaultMBB);
@ -291,7 +285,7 @@ bool IRTranslator::translateIndirectBr(const User &U,
// Link successors.
MachineBasicBlock &CurBB = MIRBuilder.getMBB();
for (const BasicBlock *Succ : BrInst.successors())
CurBB.addSuccessor(&getOrCreateBB(*Succ));
CurBB.addSuccessor(&getMBB(*Succ));
return true;
}
@ -823,8 +817,8 @@ bool IRTranslator::translateInvoke(const User &U,
MIRBuilder.buildInstr(TargetOpcode::EH_LABEL).addSym(EndSymbol);
// FIXME: track probabilities.
MachineBasicBlock &EHPadMBB = getOrCreateBB(*EHPadBB),
&ReturnMBB = getOrCreateBB(*ReturnBB);
MachineBasicBlock &EHPadMBB = getMBB(*EHPadBB),
&ReturnMBB = getMBB(*ReturnBB);
MF->addInvoke(&EHPadMBB, BeginSymbol, EndSymbol);
MIRBuilder.getMBB().addSuccessor(&ReturnMBB);
MIRBuilder.getMBB().addSuccessor(&EHPadMBB);
@ -1128,13 +1122,25 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) {
// Release the per-function state when we return, whether we succeeded or not.
auto FinalizeOnReturn = make_scope_exit([this]() { finalizeFunction(); });
// Setup a separate basic-block for the arguments and constants, falling
// through to the IR-level Function's entry block.
// Setup a separate basic-block for the arguments and constants
MachineBasicBlock *EntryBB = MF->CreateMachineBasicBlock();
MF->push_back(EntryBB);
EntryBB->addSuccessor(&getOrCreateBB(F.front()));
EntryBuilder.setMBB(*EntryBB);
// Create all blocks, in IR order, to preserve the layout.
for (const BasicBlock &BB: F) {
auto *&MBB = BBToMBB[&BB];
MBB = MF->CreateMachineBasicBlock(&BB);
MF->push_back(MBB);
if (BB.hasAddressTaken())
MBB->setHasAddressTaken();
}
// Make our arguments/constants entry block fallthrough to the IR entry block.
EntryBB->addSuccessor(&getMBB(F.front()));
// Lower the actual args into this basic block.
SmallVector<unsigned, 8> VRegArgs;
for (const Argument &Arg: F.args())
@ -1150,7 +1156,7 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) {
// And translate the function!
for (const BasicBlock &BB: F) {
MachineBasicBlock &MBB = getOrCreateBB(BB);
MachineBasicBlock &MBB = getMBB(BB);
// Set the insertion point of all the following translations to
// the end of this basic block.
CurBuilder.setMBB(MBB);

View File

@ -117,33 +117,35 @@ false:
; CHECK: G_BRCOND %[[regicmp100]](s1), %[[BB_CASE100]]
; CHECK: G_BR %[[BB_NOTCASE100_CHECKNEXT]]
;
; CHECK: [[BB_DEFAULT:bb.[0-9]+.default]]:
; CHECK-NEXT: successors: %[[BB_RET:bb.[0-9]+.return]](0x80000000)
; CHECK: %[[regretdefault:[0-9]+]](s32) = G_ADD %0, %[[reg0]]
; CHECK: G_BR %[[BB_RET]]
;
; CHECK: [[BB_CASE100]]:
; CHECK-NEXT: successors: %[[BB_RET:bb.[0-9]+.return]](0x80000000)
; CHECK: %[[regretc100:[0-9]+]](s32) = G_ADD %0, %[[reg1]]
; CHECK: G_BR %[[BB_RET]]
; CHECK: [[BB_NOTCASE100_CHECKNEXT]]:
; CHECK-NEXT: successors: %[[BB_CASE200:bb.[0-9]+.case200]](0x40000000), %[[BB_NOTCASE200_CHECKNEXT:bb.[0-9]+.entry]](0x40000000)
; CHECK: %[[regicmp200:[0-9]+]](s1) = G_ICMP intpred(eq), %[[reg200]](s32), %0
; CHECK: G_BRCOND %[[regicmp200]](s1), %[[BB_CASE200]]
; CHECK: G_BR %[[BB_NOTCASE200_CHECKNEXT]]
;
; CHECK: [[BB_CASE200]]:
; CHECK-NEXT: successors: %[[BB_RET:bb.[0-9]+.return]](0x80000000)
; CHECK: %[[regretc200:[0-9]+]](s32) = G_ADD %0, %[[reg2]]
; CHECK: G_BR %[[BB_RET]]
; CHECK: [[BB_NOTCASE200_CHECKNEXT]]:
; CHECK-NEXT: successors: %[[BB_DEFAULT:bb.[0-9]+.default]](0x80000000)
; CHECK: G_BR %[[BB_DEFAULT]]
;
; CHECK: [[BB_DEFAULT]]:
; CHECK: [[BB_CASE200:bb.[0-9]+.case200]]:
; CHECK-NEXT: successors: %[[BB_RET]](0x80000000)
; CHECK: %[[regretdefault:[0-9]+]](s32) = G_ADD %0, %[[reg0]]
; CHECK: %[[regretc200:[0-9]+]](s32) = G_ADD %0, %[[reg2]]
; CHECK: G_BR %[[BB_RET]]
;
; CHECK: [[BB_RET]]:
; CHECK-NEXT: %[[regret:[0-9]+]](s32) = PHI %[[regretdefault]](s32), %[[BB_DEFAULT]], %[[regretc100]](s32), %[[BB_CASE100]]
; CHECK: %w0 = COPY %[[regret]](s32)
; CHECK: RET_ReallyLR implicit %w0
;
; CHECK: [[BB_NOTCASE100_CHECKNEXT]]:
; CHECK-NEXT: successors: %[[BB_CASE200]](0x40000000), %[[BB_NOTCASE200_CHECKNEXT:bb.[0-9]+.entry]](0x40000000)
; CHECK: %[[regicmp200:[0-9]+]](s1) = G_ICMP intpred(eq), %[[reg200]](s32), %0
; CHECK: G_BRCOND %[[regicmp200]](s1), %[[BB_CASE200]]
; CHECK: G_BR %[[BB_NOTCASE200_CHECKNEXT]]
;
; CHECK: [[BB_NOTCASE200_CHECKNEXT]]:
; CHECK-NEXT: successors: %[[BB_DEFAULT]](0x80000000)
; CHECK: G_BR %[[BB_DEFAULT]]
define i32 @switch(i32 %argc) {
entry:
switch i32 %argc, label %default [
@ -172,13 +174,12 @@ return:
; %entry block is no longer a predecessor for the phi instruction. We need to
; use the correct lowered MachineBasicBlock instead.
; CHECK-LABEL: name: test_cfg_remap
; CHECK: [[PHI_BLOCK:bb.[0-9]+.phi.block]]:
; CHECK-NEXT: PHI %{{.*}}(s32), %[[NOTCASE57_BLOCK:bb.[0-9]+.entry]], %{{.*}}(s32),
; CHECK: bb.5.entry:
; CHECK-NEXT: successors: %[[PHI_BLOCK:bb.[0-9]+.phi.block]]
; CHECK: [[NOTCASE57_BLOCK]]:
; CHECK-NEXT: successors: %[[PHI_BLOCK]]
; CHECK: G_BR %[[PHI_BLOCK]]
; CHECK: [[PHI_BLOCK]]:
; CHECK-NEXT: PHI %{{.*}}(s32), %bb.5.entry
define i32 @test_cfg_remap(i32 %in) {
entry:
switch i32 %in, label %phi.block [i32 1, label %next
@ -378,11 +379,11 @@ define i64* @trivial_bitcast(i8* %a) {
; CHECK: [[A:%[0-9]+]](p0) = COPY %x0
; CHECK: G_BR %[[CAST:bb\.[0-9]+.cast]]
; CHECK: [[END:bb\.[0-9]+.end]]:
; CHECK: [[CAST]]:
; CHECK: {{%[0-9]+}}(p0) = COPY [[A]]
; CHECK: G_BR %[[END:bb\.[0-9]+.end]]
; CHECK: [[END]]:
; CHECK: G_BR %[[END]]
define i64* @trivial_bitcast_with_copy(i8* %a) {
br label %cast