Pseudo probe are currently given a slot index like other regular instructions. This affects register pressure and lifetime weight computation because of enlarged lifetime length with pseudo probe instructions. As a consequence, program could get different code generated w/ and w/o pseudo probes. I'm closing the gap by excluding pseudo probes from stack index and downstream register allocation related passes.
Reviewed By: wmi
Differential Revision: https://reviews.llvm.org/D100334
const MachineInstr *PrevMI = nullptr;
const DILocation *PrevDL = nullptr;
for (const auto &MInsn : MBB) {
+ // Ignore DBG_VALUE and similar instruction that do not contribute to any
+ // instruction in the output.
+ if (MInsn.isMetaInstruction())
+ continue;
+
// Check if instruction has valid location information.
const DILocation *MIDL = MInsn.getDebugLoc();
if (!MIDL) {
continue;
}
- // Ignore DBG_VALUE and similar instruction that do not contribute to any
- // instruction in the output.
- if (MInsn.isMetaInstruction())
- continue;
-
if (RangeBeginMI) {
// If we have already seen a beginning of an instruction range and
// current instruction scope does not match scope of first instruction
MBBI != MBBE;) {
// Use the first debug instruction in the sequence to get a SlotIndex
// for following consecutive debug instructions.
- if (!MBBI->isDebugInstr()) {
+ if (!MBBI->isDebugOrPseudoInstr()) {
++MBBI;
continue;
}
Changed = true;
} else
++MBBI;
- } while (MBBI != MBBE && MBBI->isDebugInstr());
+ } while (MBBI != MBBE && MBBI->isDebugOrPseudoInstr());
}
}
return Changed;
MachineBasicBlock::iterator Begin = MBB->begin();
while (MII != Begin) {
- if ((--MII)->isDebugInstr())
+ if ((--MII)->isDebugOrPseudoInstr())
continue;
SlotIndex Idx = Indexes->getInstructionIndex(*MII);
for (MachineBasicBlock::iterator I = End; I != Begin;) {
--I;
MachineInstr &MI = *I;
- if (MI.isDebugInstr())
+ if (MI.isDebugOrPseudoInstr())
continue;
SlotIndex instrIdx = getInstructionIndex(MI);
for (MachineBasicBlock::iterator I = End; I != Begin;) {
--I;
MachineInstr &MI = *I;
- if (MI.isDebugInstr())
+ if (MI.isDebugOrPseudoInstr())
continue;
for (MachineInstr::const_mop_iterator MOI = MI.operands_begin(),
MOE = MI.operands_end();
for (MachineBasicBlock::iterator Next = MBB.begin(); Next != MBB.end();) {
MachineInstr &MI = *Next;
++Next;
- if (MI.isPHI() || MI.isDebugInstr())
+ if (MI.isPHI() || MI.isDebugOrPseudoInstr())
continue;
if (MI.mayStore())
SawStore = true;
if (DefMO && Insert && NumEligibleUse > 1 && Barrier <= IOM[Insert]) {
MachineBasicBlock::iterator I = std::next(Insert->getIterator());
// Skip all the PHI and debug instructions.
- while (I != MBB.end() && (I->isPHI() || I->isDebugInstr()))
+ while (I != MBB.end() && (I->isPHI() || I->isDebugOrPseudoInstr()))
I = std::next(I);
if (I == MI.getIterator())
continue;
void LiveVariables::runOnInstr(MachineInstr &MI,
SmallVectorImpl<unsigned> &Defs) {
- assert(!MI.isDebugInstr());
+ assert(!MI.isDebugOrPseudoInstr());
// Process all of the operands of the instruction...
unsigned NumOperandsToProcess = MI.getNumOperands();
DistanceMap.clear();
unsigned Dist = 0;
for (MachineInstr &MI : *MBB) {
- if (MI.isDebugInstr())
+ if (MI.isDebugOrPseudoInstr())
continue;
DistanceMap.insert(std::make_pair(&MI, Dist++));
// Try searching forwards from Before, looking for reads or defs.
const_iterator I(Before);
for (; I != end() && N > 0; ++I) {
- if (I->isDebugInstr())
+ if (I->isDebugOrPseudoInstr())
continue;
--N;
do {
--I;
- if (I->isDebugInstr())
+ if (I->isDebugOrPseudoInstr())
continue;
--N;
// If all the instructions before this in the block are debug instructions,
// skip over them.
- while (I != begin() && std::prev(I)->isDebugInstr())
+ while (I != begin() && std::prev(I)->isDebugOrPseudoInstr())
--I;
// Did we get to the start of the block?
MachineBasicBlock::const_iterator Beg) {
assert(I != Beg && "reached the top of the region, cannot decrement");
while (--I != Beg) {
- if (!I->isDebugInstr())
+ if (!I->isDebugOrPseudoInstr())
break;
}
return I;
nextIfDebug(MachineBasicBlock::const_iterator I,
MachineBasicBlock::const_iterator End) {
for(; I != End; ++I) {
- if (!I->isDebugInstr())
+ if (!I->isDebugOrPseudoInstr())
break;
}
return I;
MachineInstr &MI = *std::prev(I);
if (isSchedBoundary(&MI, &*MBB, MF, TII))
break;
- if (!MI.isDebugInstr()) {
+ if (!MI.isDebugOrPseudoInstr()) {
// MBB::size() uses instr_iterator to count. Here we need a bundle to
// count as a single instruction.
++NumRegionInstrs;
if (!ProcessedBegin)
--I;
- if (MI.isDebugInstr()) {
+ if (MI.isDebugOrPseudoInstr()) {
if (MI.isDebugValue())
ProcessDbgInst(MI);
continue;
MIE = MBB.instr_begin();
MII != MIE; --MII) {
MachineInstr &MI = *std::prev(MII);
- if (MI.isDebugValue() || MI.isDebugLabel())
+ if (MI.isDebugValue() || MI.isDebugLabel() || MI.isPseudoProbe())
continue;
RegisterOperands RegOpers;
RegOpers.collect(MI, *TRI, *MRI, false, false);
continue;
}
- if (MI->isDebugInstr())
+ if (MI->isDebugOrPseudoInstr())
continue;
// Do not move any instruction across function call.
// Abort if the spill cannot be inserted at the MBB' start
MachineBasicBlock *MBB = MF->getBlockNumbered(Number);
if (!MBB->empty() &&
- SlotIndex::isEarlierInstr(LIS->getInstructionIndex(MBB->instr_front()),
- SA->getFirstSplitPoint(Number)))
+ SlotIndex::isEarlierInstr(
+ LIS->getInstructionIndex(*MBB->getFirstNonDebugInstr()),
+ SA->getFirstSplitPoint(Number)))
return false;
// Interference for the live-in value.
if (Intf.first() <= Indexes->getMBBStartIdx(Number))
bool JoinVals::usesLanes(const MachineInstr &MI, Register Reg, unsigned SubIdx,
LaneBitmask Lanes) const {
- if (MI.isDebugInstr())
+ if (MI.isDebugOrPseudoInstr())
return false;
for (const MachineOperand &MO : MI.operands()) {
if (!MO.isReg() || MO.isDef() || MO.getReg() != Reg)
return MO.isReg() && MO.getReg().isVirtual();
}))
ToInsert.push_back(&MI);
- } else if (!MI.isDebugInstr()) {
+ } else if (!MI.isDebugOrPseudoInstr()) {
CurrentSlot = Slots.getInstructionIndex(MI);
CloseNewDVRange(CurrentSlot);
}
/// instruction independent of liveness.
void RegPressureTracker::recede(const RegisterOperands &RegOpers,
SmallVectorImpl<RegisterMaskPair> *LiveUses) {
- assert(!CurrPos->isDebugInstr());
+ assert(!CurrPos->isDebugOrPseudoInstr());
// Boost pressure for all dead defs together.
bumpDeadDefs(RegOpers.DeadDefs);
CurrPos = prev_nodbg(CurrPos, MBB->begin());
SlotIndex SlotIdx;
- if (RequireIntervals && !CurrPos->isDebugInstr())
+ if (RequireIntervals && !CurrPos->isDebugOrPseudoInstr())
SlotIdx = LIS->getInstructionIndex(*CurrPos).getRegSlot();
// Open the top of the region using slot indexes.
void RegPressureTracker::recede(SmallVectorImpl<RegisterMaskPair> *LiveUses) {
recedeSkipDebugValues();
- if (CurrPos->isDebugValue()) {
- // It's possible to only have debug_value instructions and hit the start of
- // the block.
+ if (CurrPos->isDebugValue() || CurrPos->isPseudoProbe()) {
+ // It's possible to only have debug_value and pseudo probe instructions and
+ // hit the start of the block.
assert(CurrPos == MBB->begin());
return;
}
/// This is intended for speculative queries. It leaves pressure inconsistent
/// with the current position, so must be restored by the caller.
void RegPressureTracker::bumpUpwardPressure(const MachineInstr *MI) {
- assert(!MI->isDebugInstr() && "Expect a nondebug instruction.");
+ assert(!MI->isDebugOrPseudoInstr() && "Expect a nondebug instruction.");
SlotIndex SlotIdx;
if (RequireIntervals)
/// This is intended for speculative queries. It leaves pressure inconsistent
/// with the current position, so must be restored by the caller.
void RegPressureTracker::bumpDownwardPressure(const MachineInstr *MI) {
- assert(!MI->isDebugInstr() && "Expect a nondebug instruction.");
+ assert(!MI->isDebugOrPseudoInstr() && "Expect a nondebug instruction.");
SlotIndex SlotIdx;
if (RequireIntervals)
I.Restore = nullptr;
}
- if (MI.isDebugInstr())
+ if (MI.isDebugOrPseudoInstr())
return;
determineKillsAndDefs();
bool inVirtLiveRange = false;
for (++MI; InstrLimit > 0 && MI != ME; ++MI, --InstrLimit) {
- if (MI->isDebugInstr()) {
+ if (MI->isDebugOrPseudoInstr()) {
++InstrLimit; // Don't count debug instructions
continue;
}
/// TODO: Handle ExitSU "uses" properly.
void ScheduleDAGInstrs::addVRegUseDeps(SUnit *SU, unsigned OperIdx) {
const MachineInstr *MI = SU->getInstr();
- assert(!MI->isDebugInstr());
+ assert(!MI->isDebugOrPseudoInstr());
const MachineOperand &MO = MI->getOperand(OperIdx);
Register Reg = MO.getReg();
SUnits.reserve(NumRegionInstrs);
for (MachineInstr &MI : make_range(RegionBegin, RegionEnd)) {
- if (MI.isDebugInstr())
+ if (MI.isDebugOrPseudoInstr())
continue;
SUnit *SU = newSUnit(&MI);
if (MI.isDebugLabel())
continue;
+ if (MI.isPseudoProbe())
+ continue;
+
SUnit *SU = MISUnitMap[&MI];
assert(SU && "No SUnit mapped to this MI");
// Examine block from end to start...
for (MachineInstr &MI : make_range(MBB.rbegin(), MBB.rend())) {
- if (MI.isDebugInstr())
+ if (MI.isDebugOrPseudoInstr())
continue;
// Update liveness. Registers that are defed but not used in this
while (I->isBundledWithSucc())
++I;
do {
- if (!I->isDebugInstr())
+ if (!I->isDebugOrPseudoInstr())
toggleKills(MRI, LiveRegs, *I, true);
--I;
} while (I != Bundle);
SlotIndex blockStartIndex(&indexList.back(), SlotIndex::Slot_Block);
for (MachineInstr &MI : MBB) {
- if (MI.isDebugInstr())
+ if (MI.isDebugOrPseudoInstr())
continue;
// Insert a store index for the instr.
for (MachineBasicBlock::iterator I = End; I != Begin;) {
--I;
MachineInstr &MI = *I;
- if (!MI.isDebugInstr() && mi2iMap.find(&MI) == mi2iMap.end())
+ if (!MI.isDebugOrPseudoInstr() && mi2iMap.find(&MI) == mi2iMap.end())
insertMachineInstrInMaps(MI);
}
}
MachineBasicBlock::iterator MBBI(MI);
bool AtBegin;
do AtBegin = MBBI == MBB->begin();
- while (!AtBegin && (--MBBI)->isDebugInstr());
+ while (!AtBegin && (--MBBI)->isDebugOrPseudoInstr());
LLVM_DEBUG(dbgs() << "Removing " << Def << '\t' << *MI);
LIS.removeVRegDefAt(*LI, Def);
--- /dev/null
+; REQUIRES: x86_64-linux
+; RUN: llc -print-after=slotindexes -stop-after=slotindexes -mtriple=x86_64-- %s -filetype=asm -o %t 2>&1 | FileCheck %s
+
+define void @foo(i32* %p) {
+ store i32 0, i32* %p
+ call void @llvm.pseudoprobe(i64 5116412291814990879, i64 1, i32 0, i64 -1)
+ store i32 0, i32* %p
+ ret void
+}
+
+;; Check the pseudo probe instruction isn't assigned a slot index.
+;CHECK: IR Dump {{.*}}
+;CHECK: # Machine code for function foo{{.*}}
+;CHECK: {{[0-9]+}}B bb.0 (%ir-block.0)
+;CHECK: {{[0-9]+}}B %0:gr64 = COPY killed $rdi
+;CHECK: {{^}} PSEUDO_PROBE 5116412291814990879
+;CHECK: {{[0-9]+}}B MOV32mi
+;CHECK: {{[0-9]+}}B RET 0
+
+declare void @llvm.pseudoprobe(i64, i64, i32, i64) #0
+
+attributes #0 = { inaccessiblememonly nounwind willreturn }
\ No newline at end of file