mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
[LiveIntervals] Replace handleMoveIntoBundle
Summary: The current handleMoveIntoBundle implementation is unusable, it attempts to access the slot indexes of bundled instructions. It also leaves bundled instructions with slot indexes assigned. Replace handleMoveIntoBundle this with a more explicit handleMoveIntoNewBundle function which recalculates the live intervals for all instructions moved into a newly formed bundle, and removes slot indexes from these instructions. Reviewers: arsenm, MaskRay, kariddi, tpr, qcolombet Reviewed By: qcolombet Subscribers: MatzeB, wdng, hiraditya, arphaman, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D77969
This commit is contained in:
parent
e8df66d65f
commit
3aeca434d7
@ -310,16 +310,16 @@ class VirtRegMap;
|
||||
/// \param UpdateFlags Update live intervals for nonallocatable physregs.
|
||||
void handleMove(MachineInstr &MI, bool UpdateFlags = false);
|
||||
|
||||
/// Update intervals for operands of \p MI so that they begin/end on the
|
||||
/// SlotIndex for \p BundleStart.
|
||||
/// Update intervals of operands of all instructions in the newly
|
||||
/// created bundle specified by \p BundleStart.
|
||||
///
|
||||
/// \param UpdateFlags Update live intervals for nonallocatable physregs.
|
||||
///
|
||||
/// Requires MI and BundleStart to have SlotIndexes, and assumes
|
||||
/// existing liveness is accurate. BundleStart should be the first
|
||||
/// instruction in the Bundle.
|
||||
void handleMoveIntoBundle(MachineInstr &MI, MachineInstr &BundleStart,
|
||||
bool UpdateFlags = false);
|
||||
/// Assumes existing liveness is accurate.
|
||||
/// \pre BundleStart should be the first instruction in the Bundle.
|
||||
/// \pre BundleStart should not have a have SlotIndex as one will be assigned.
|
||||
void handleMoveIntoNewBundle(MachineInstr &BundleStart,
|
||||
bool UpdateFlags = false);
|
||||
|
||||
/// Update live intervals for instructions in a range of iterators. It is
|
||||
/// intended for use after target hooks that may insert or remove
|
||||
|
@ -382,13 +382,15 @@ class raw_ostream;
|
||||
}
|
||||
|
||||
/// Returns the base index for the given instruction.
|
||||
SlotIndex getInstructionIndex(const MachineInstr &MI) const {
|
||||
SlotIndex getInstructionIndex(const MachineInstr &MI,
|
||||
bool IgnoreBundle = false) const {
|
||||
// Instructions inside a bundle have the same number as the bundle itself.
|
||||
auto BundleStart = getBundleStart(MI.getIterator());
|
||||
auto BundleEnd = getBundleEnd(MI.getIterator());
|
||||
// Use the first non-debug instruction in the bundle to get SlotIndex.
|
||||
const MachineInstr &BundleNonDebug =
|
||||
*skipDebugInstructionsForward(BundleStart, BundleEnd);
|
||||
IgnoreBundle ? MI
|
||||
: *skipDebugInstructionsForward(BundleStart, BundleEnd);
|
||||
assert(!BundleNonDebug.isDebugInstr() &&
|
||||
"Could not use a debug instruction to query mi2iMap.");
|
||||
Mi2IndexMap::const_iterator itr = mi2iMap.find(&BundleNonDebug);
|
||||
@ -573,7 +575,11 @@ class raw_ostream;
|
||||
/// Removes machine instruction (bundle) \p MI from the mapping.
|
||||
/// This should be called before MachineInstr::eraseFromParent() is used to
|
||||
/// remove a whole bundle or an unbundled instruction.
|
||||
void removeMachineInstrFromMaps(MachineInstr &MI);
|
||||
/// If \p AllowBundled is set then this can be used on a bundled
|
||||
/// instruction; however, this exists to support handleMoveIntoBundle,
|
||||
/// and in general removeSingleMachineInstrFromMaps should be used instead.
|
||||
void removeMachineInstrFromMaps(MachineInstr &MI,
|
||||
bool AllowBundled = false);
|
||||
|
||||
/// Removes a single machine instruction \p MI from the mapping.
|
||||
/// This should be called before MachineInstr::eraseFromBundle() is used to
|
||||
|
@ -1478,13 +1478,43 @@ void LiveIntervals::handleMove(MachineInstr &MI, bool UpdateFlags) {
|
||||
HME.updateAllRanges(&MI);
|
||||
}
|
||||
|
||||
void LiveIntervals::handleMoveIntoBundle(MachineInstr &MI,
|
||||
MachineInstr &BundleStart,
|
||||
bool UpdateFlags) {
|
||||
SlotIndex OldIndex = Indexes->getInstructionIndex(MI);
|
||||
SlotIndex NewIndex = Indexes->getInstructionIndex(BundleStart);
|
||||
HMEditor HME(*this, *MRI, *TRI, OldIndex, NewIndex, UpdateFlags);
|
||||
HME.updateAllRanges(&MI);
|
||||
void LiveIntervals::handleMoveIntoNewBundle(MachineInstr &BundleStart,
|
||||
bool UpdateFlags) {
|
||||
assert((BundleStart.getOpcode() == TargetOpcode::BUNDLE) &&
|
||||
"Bundle start is not a bundle");
|
||||
SmallVector<SlotIndex, 16> ToProcess;
|
||||
const SlotIndex NewIndex = Indexes->insertMachineInstrInMaps(BundleStart);
|
||||
auto BundleEnd = getBundleEnd(BundleStart.getIterator());
|
||||
|
||||
auto I = BundleStart.getIterator();
|
||||
I++;
|
||||
while (I != BundleEnd) {
|
||||
if (!Indexes->hasIndex(*I))
|
||||
continue;
|
||||
SlotIndex OldIndex = Indexes->getInstructionIndex(*I, true);
|
||||
ToProcess.push_back(OldIndex);
|
||||
Indexes->removeMachineInstrFromMaps(*I, true);
|
||||
I++;
|
||||
}
|
||||
for (SlotIndex OldIndex : ToProcess) {
|
||||
HMEditor HME(*this, *MRI, *TRI, OldIndex, NewIndex, UpdateFlags);
|
||||
HME.updateAllRanges(&BundleStart);
|
||||
}
|
||||
|
||||
// Fix up dead defs
|
||||
const SlotIndex Index = getInstructionIndex(BundleStart);
|
||||
for (unsigned Idx = 0, E = BundleStart.getNumOperands(); Idx != E; ++Idx) {
|
||||
MachineOperand &MO = BundleStart.getOperand(Idx);
|
||||
if (!MO.isReg())
|
||||
continue;
|
||||
Register Reg = MO.getReg();
|
||||
if (Reg.isVirtual() && hasInterval(Reg) && !MO.isUndef()) {
|
||||
LiveInterval &LI = getInterval(Reg);
|
||||
LiveQueryResult LRQ = LI.Query(Index);
|
||||
if (LRQ.isDeadDef())
|
||||
MO.setIsDead();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LiveIntervals::repairOldRegInRange(const MachineBasicBlock::iterator Begin,
|
||||
|
@ -112,9 +112,10 @@ bool SlotIndexes::runOnMachineFunction(MachineFunction &fn) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void SlotIndexes::removeMachineInstrFromMaps(MachineInstr &MI) {
|
||||
assert(!MI.isBundledWithPred() &&
|
||||
"Use removeSingleMachineInstrFromMaps() instread");
|
||||
void SlotIndexes::removeMachineInstrFromMaps(MachineInstr &MI,
|
||||
bool AllowBundled) {
|
||||
assert((AllowBundled || !MI.isBundledWithPred()) &&
|
||||
"Use removeSingleMachineInstrFromMaps() instead");
|
||||
Mi2IndexMap::iterator mi2iItr = mi2iMap.find(&MI);
|
||||
if (mi2iItr == mi2iMap.end())
|
||||
return;
|
||||
@ -141,7 +142,7 @@ void SlotIndexes::removeSingleMachineInstrFromMaps(MachineInstr &MI) {
|
||||
// instruction.
|
||||
if (MI.isBundledWithSucc()) {
|
||||
// Only the first instruction of a bundle should have an index assigned.
|
||||
assert(!MI.isBundledWithPred() && "Should have first bundle isntruction");
|
||||
assert(!MI.isBundledWithPred() && "Should be first bundle instruction");
|
||||
|
||||
MachineBasicBlock::instr_iterator Next = std::next(MI.getIterator());
|
||||
MachineInstr &NextMI = *Next;
|
||||
|
@ -128,6 +128,27 @@ static void testHandleMove(MachineFunction &MF, LiveIntervals &LIS,
|
||||
LIS.handleMove(FromInstr, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move instructions numbered \p From inclusive through instruction number
|
||||
* \p To into a newly formed bundle and update affected liveness intervals
|
||||
* with LiveIntervalAnalysis::handleMoveIntoNewBundle().
|
||||
*/
|
||||
static void testHandleMoveIntoNewBundle(MachineFunction &MF, LiveIntervals &LIS,
|
||||
unsigned From, unsigned To,
|
||||
unsigned BlockNum = 0) {
|
||||
MachineInstr &FromInstr = getMI(MF, From, BlockNum);
|
||||
MachineInstr &ToInstr = getMI(MF, To, BlockNum);
|
||||
MachineBasicBlock &MBB = *FromInstr.getParent();
|
||||
MachineBasicBlock::instr_iterator I = FromInstr.getIterator();
|
||||
|
||||
// Build bundle
|
||||
finalizeBundle(MBB, I, std::next(ToInstr.getIterator()));
|
||||
|
||||
// Update LiveIntervals
|
||||
MachineBasicBlock::instr_iterator BundleStart = std::prev(I);
|
||||
LIS.handleMoveIntoNewBundle(*BundleStart, true);
|
||||
}
|
||||
|
||||
static void liveIntervalTest(StringRef MIRFunc, LiveIntervalTest T) {
|
||||
LLVMContext Context;
|
||||
std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
|
||||
@ -462,6 +483,96 @@ TEST(LiveIntervalTest, TestMoveSubRegDefAcrossUseDefMulti) {
|
||||
testHandleMove(MF, LIS, 4, 1, 1);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(LiveIntervalTest, BundleUse) {
|
||||
liveIntervalTest(R"MIR(
|
||||
%0 = IMPLICIT_DEF
|
||||
S_NOP 0
|
||||
S_NOP 0, implicit %0
|
||||
S_NOP 0
|
||||
)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
|
||||
testHandleMoveIntoNewBundle(MF, LIS, 1, 2);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(LiveIntervalTest, BundleDef) {
|
||||
liveIntervalTest(R"MIR(
|
||||
%0 = IMPLICIT_DEF
|
||||
S_NOP 0
|
||||
S_NOP 0, implicit %0
|
||||
S_NOP 0
|
||||
)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
|
||||
testHandleMoveIntoNewBundle(MF, LIS, 0, 1);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(LiveIntervalTest, BundleRedef) {
|
||||
liveIntervalTest(R"MIR(
|
||||
%0 = IMPLICIT_DEF
|
||||
S_NOP 0
|
||||
%0 = IMPLICIT_DEF implicit %0(tied-def 0)
|
||||
S_NOP 0, implicit %0
|
||||
)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
|
||||
testHandleMoveIntoNewBundle(MF, LIS, 1, 2);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(LiveIntervalTest, BundleInternalUse) {
|
||||
liveIntervalTest(R"MIR(
|
||||
%0 = IMPLICIT_DEF
|
||||
S_NOP 0
|
||||
S_NOP 0, implicit %0
|
||||
S_NOP 0
|
||||
)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
|
||||
testHandleMoveIntoNewBundle(MF, LIS, 0, 2);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(LiveIntervalTest, BundleUndefUse) {
|
||||
liveIntervalTest(R"MIR(
|
||||
%0 = IMPLICIT_DEF
|
||||
S_NOP 0
|
||||
S_NOP 0, implicit undef %0
|
||||
S_NOP 0
|
||||
)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
|
||||
testHandleMoveIntoNewBundle(MF, LIS, 1, 2);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(LiveIntervalTest, BundleSubRegUse) {
|
||||
liveIntervalTest(R"MIR(
|
||||
successors: %bb.1, %bb.2
|
||||
undef %0.sub0 = IMPLICIT_DEF
|
||||
%0.sub1 = IMPLICIT_DEF
|
||||
S_CBRANCH_VCCNZ %bb.2, implicit undef $vcc
|
||||
S_BRANCH %bb.1
|
||||
bb.1:
|
||||
S_NOP 0
|
||||
S_NOP 0, implicit %0.sub1
|
||||
bb.2:
|
||||
S_NOP 0, implicit %0.sub1
|
||||
)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
|
||||
testHandleMoveIntoNewBundle(MF, LIS, 0, 1, 1);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(LiveIntervalTest, BundleSubRegDef) {
|
||||
liveIntervalTest(R"MIR(
|
||||
successors: %bb.1, %bb.2
|
||||
undef %0.sub0 = IMPLICIT_DEF
|
||||
%0.sub1 = IMPLICIT_DEF
|
||||
S_CBRANCH_VCCNZ %bb.2, implicit undef $vcc
|
||||
S_BRANCH %bb.1
|
||||
bb.1:
|
||||
S_NOP 0
|
||||
S_NOP 0, implicit %0.sub1
|
||||
bb.2:
|
||||
S_NOP 0, implicit %0.sub1
|
||||
)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
|
||||
testHandleMoveIntoNewBundle(MF, LIS, 0, 1, 0);
|
||||
});
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
initLLVM();
|
||||
|
Loading…
Reference in New Issue
Block a user