Tighten up the erase/remove API for bundled instructions.

Most code is oblivious to bundles and uses the MBB::iterator which only
visits whole bundles. MBB::erase() operates on whole bundles at a time
as before.

MBB::remove() now refuses to remove bundled instructions. It is not safe
to remove all instructions in a bundle without deleting them since there
is no way of returning pointers to all the removed instructions.

MBB::remove_instr() and MBB::erase_instr() will now update bundle flags
correctly, lifting individual instructions out of bundles while leaving
the remaining bundle intact.

The MachineInstr convenience functions are updated so

  eraseFromParent() erases a whole bundle as before
  eraseFromBundle() erases a single instruction, leaving the rest of its bundle.
  removeFromParent() refuses to operate on bundled instructions, and
  removeFromBundle() lifts a single instruction out of its bundle.

These functions will no longer accidentally split or coalesce bundles -
bundle flags are updated to preserve the existing bundling, and explicit
bundleWith* / unbundleFrom* functions should be used to change the
instruction bundling.

This API update is still a work in progress. I am going to update APIs
first so they maintain bundle flags automatically when possible. Then
I'll add stricter verification of the bundle flags.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@170384 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen
2012-12-17 23:55:38 +00:00
parent 082b7e6d36
commit 9f4692d295
4 changed files with 96 additions and 75 deletions

View File

@ -788,27 +788,30 @@ MachineBasicBlock::SplitCriticalEdge(MachineBasicBlock *Succ, Pass *P) {
return NMBB;
}
MachineBasicBlock::iterator
MachineBasicBlock::erase(MachineBasicBlock::iterator I) {
if (I->isBundle()) {
MachineBasicBlock::iterator E = llvm::next(I);
return Insts.erase(I.getInstrIterator(), E.getInstrIterator());
}
return Insts.erase(I.getInstrIterator());
/// Prepare MI to be removed from its bundle. This fixes bundle flags on MI's
/// neighboring instructions so the bundle won't be broken by removing MI.
static void unbundleSingleMI(MachineInstr *MI) {
// Removing the first instruction in a bundle.
if (MI->isBundledWithSucc() && !MI->isBundledWithPred())
MI->unbundleFromSucc();
// Removing the last instruction in a bundle.
if (MI->isBundledWithPred() && !MI->isBundledWithSucc())
MI->unbundleFromPred();
// If MI is not bundled, or if it is internal to a bundle, the neighbor flags
// are already fine.
}
MachineInstr *MachineBasicBlock::remove(MachineInstr *I) {
if (I->isBundle()) {
instr_iterator MII = llvm::next(I);
iterator E = end();
while (MII != E && MII->isInsideBundle()) {
MachineInstr *MI = &*MII++;
Insts.remove(MI);
}
}
MachineBasicBlock::instr_iterator
MachineBasicBlock::erase(MachineBasicBlock::instr_iterator I) {
unbundleSingleMI(I);
return Insts.erase(I);
}
return Insts.remove(I);
MachineInstr *MachineBasicBlock::remove_instr(MachineInstr *MI) {
unbundleSingleMI(MI);
MI->clearFlag(MachineInstr::BundledPred);
MI->clearFlag(MachineInstr::BundledSucc);
return Insts.remove(MI);
}
void MachineBasicBlock::splice(MachineBasicBlock::iterator where,