forked from OSchip/llvm-project
[MachineInstr] Move MIParser's DBG_VALUE RegState::Debug invariant into MachineInstr::addOperand
Based on the reasoning of D53903, register operands of DBG_VALUE are invariably treated as RegState::Debug operands. This change enforces this invariant as part of MachineInstr::addOperand so that all passes emit this flag consistently. RegState::Debug is inconsistently set on DBG_VALUE registers throughout LLVM. This runs the risk of a filtering iterator like MachineRegisterInfo::reg_nodbg_iterator to process these operands erroneously when not parsed from MIR sources. This issue was observed in the development of the llvm-mos fork which adds a backend that relies on physical register operands much more than existing targets. Physical RegUnit 0 has the same numeric encoding as $noreg (indicating an undef for DBG_VALUE). Allowing debug operands into the machine scheduler correlates $noreg with RegUnit 0 (i.e. a collision of register numbers with different zero semantics). Eventually, this causes an assert where DBG_VALUE instructions are prohibited from participating in live register ranges. Reviewed By: MatzeB, StephenTozer Differential Revision: https://reviews.llvm.org/D110105
This commit is contained in:
parent
3e9689d72c
commit
bd4dad87f4
|
@ -764,8 +764,8 @@ public:
|
|||
const DIExpression *Expr = Properties.DIExpr;
|
||||
if (!MLoc) {
|
||||
// No location -> DBG_VALUE $noreg
|
||||
MIB.addReg(0, RegState::Debug);
|
||||
MIB.addReg(0, RegState::Debug);
|
||||
MIB.addReg(0);
|
||||
MIB.addReg(0);
|
||||
} else if (LocIdxToLocID[*MLoc] >= NumRegs) {
|
||||
unsigned LocID = LocIdxToLocID[*MLoc];
|
||||
const SpillLoc &Spill = SpillLocs[LocID - NumRegs + 1];
|
||||
|
@ -774,15 +774,15 @@ public:
|
|||
Expr = TRI->prependOffsetExpression(Expr, DIExpression::ApplyOffset,
|
||||
Spill.SpillOffset);
|
||||
unsigned Base = Spill.SpillBase;
|
||||
MIB.addReg(Base, RegState::Debug);
|
||||
MIB.addReg(Base);
|
||||
MIB.addImm(0);
|
||||
} else {
|
||||
unsigned LocID = LocIdxToLocID[*MLoc];
|
||||
MIB.addReg(LocID, RegState::Debug);
|
||||
MIB.addReg(LocID);
|
||||
if (Properties.Indirect)
|
||||
MIB.addImm(0);
|
||||
else
|
||||
MIB.addReg(0, RegState::Debug);
|
||||
MIB.addReg(0);
|
||||
}
|
||||
|
||||
MIB.addMetadata(Var.getVariable());
|
||||
|
@ -1220,7 +1220,6 @@ public:
|
|||
DIExpression::prepend(Prop.DIExpr, DIExpression::EntryValue);
|
||||
Register Reg = MTracker->LocIdxToLocID[Num.getLoc()];
|
||||
MachineOperand MO = MachineOperand::CreateReg(Reg, false);
|
||||
MO.setIsDebug(true);
|
||||
|
||||
PendingDbgValues.push_back(emitMOLoc(MO, Var, {NewExpr, Prop.Indirect}));
|
||||
return true;
|
||||
|
|
|
@ -546,7 +546,6 @@ private:
|
|||
EVKind == EntryValueLocKind::EntryValueKind ? Orig.getReg()
|
||||
: Register(Loc.RegNo),
|
||||
false));
|
||||
MOs.back().setIsDebug();
|
||||
break;
|
||||
case MachineLocKind::SpillLocKind: {
|
||||
// Spills are indirect DBG_VALUEs, with a base register and offset.
|
||||
|
@ -568,7 +567,6 @@ private:
|
|||
DIExpr = DIExpression::appendOpsToArg(DIExpr, Ops, I);
|
||||
}
|
||||
MOs.push_back(MachineOperand::CreateReg(Base, false));
|
||||
MOs.back().setIsDebug();
|
||||
break;
|
||||
}
|
||||
case MachineLocKind::ImmediateKind: {
|
||||
|
|
|
@ -1011,10 +1011,6 @@ bool MIParser::parse(MachineInstr *&MI) {
|
|||
Optional<unsigned> TiedDefIdx;
|
||||
if (parseMachineOperandAndTargetFlags(OpCode, Operands.size(), MO, TiedDefIdx))
|
||||
return true;
|
||||
if ((OpCode == TargetOpcode::DBG_VALUE ||
|
||||
OpCode == TargetOpcode::DBG_VALUE_LIST) &&
|
||||
MO.isReg())
|
||||
MO.setIsDebug();
|
||||
Operands.push_back(
|
||||
ParsedMachineOperand(MO, Loc, Token.location(), TiedDefIdx));
|
||||
if (Token.isNewlineOrEOF() || Token.is(MIToken::coloncolon) ||
|
||||
|
|
|
@ -1158,7 +1158,7 @@ auto MachineFunction::salvageCopySSA(MachineInstr &MI)
|
|||
// Create DBG_PHI for specified physreg.
|
||||
auto Builder = BuildMI(InsertBB, InsertBB.getFirstNonPHI(), DebugLoc(),
|
||||
TII.get(TargetOpcode::DBG_PHI));
|
||||
Builder.addReg(State.first, RegState::Debug);
|
||||
Builder.addReg(State.first);
|
||||
unsigned NewNum = getNewDebugInstrNum();
|
||||
Builder.addImm(NewNum);
|
||||
return ApplySubregisters({NewNum, 0u});
|
||||
|
@ -1171,7 +1171,6 @@ void MachineFunction::finalizeDebugInstrRefs() {
|
|||
const MCInstrDesc &RefII = TII->get(TargetOpcode::DBG_VALUE);
|
||||
MI.setDesc(RefII);
|
||||
MI.getOperand(1).ChangeToRegister(0, false);
|
||||
MI.getOperand(0).setIsDebug();
|
||||
};
|
||||
|
||||
if (!useDebugInstrRef())
|
||||
|
|
|
@ -294,6 +294,9 @@ void MachineInstr::addOperand(MachineFunction &MF, const MachineOperand &Op) {
|
|||
if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1)
|
||||
NewMO->setIsEarlyClobber(true);
|
||||
}
|
||||
// Ensure debug instructions set debug flag on register uses.
|
||||
if (NewMO->isUse() && isDebugInstr())
|
||||
NewMO->setIsDebug();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2111,11 +2114,11 @@ MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
|
|||
assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
|
||||
assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
|
||||
"Expected inlined-at fields to agree");
|
||||
auto MIB = BuildMI(MF, DL, MCID).addReg(Reg, RegState::Debug);
|
||||
auto MIB = BuildMI(MF, DL, MCID).addReg(Reg);
|
||||
if (IsIndirect)
|
||||
MIB.addImm(0U);
|
||||
else
|
||||
MIB.addReg(0U, RegState::Debug);
|
||||
MIB.addReg(0U);
|
||||
return MIB.addMetadata(Variable).addMetadata(Expr);
|
||||
}
|
||||
|
||||
|
@ -2134,7 +2137,7 @@ MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
|
|||
if (IsIndirect)
|
||||
MIB.addImm(0U);
|
||||
else
|
||||
MIB.addReg(0U, RegState::Debug);
|
||||
MIB.addReg(0U);
|
||||
return MIB.addMetadata(Variable).addMetadata(Expr);
|
||||
}
|
||||
|
||||
|
@ -2153,7 +2156,7 @@ MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
|
|||
MIB.addMetadata(Variable).addMetadata(Expr);
|
||||
for (const MachineOperand &MO : MOs)
|
||||
if (MO.isReg())
|
||||
MIB.addReg(MO.getReg(), RegState::Debug);
|
||||
MIB.addReg(MO.getReg());
|
||||
else
|
||||
MIB.add(MO);
|
||||
return MIB;
|
||||
|
|
|
@ -250,6 +250,11 @@ void MachineOperand::ChangeToRegister(Register Reg, bool isDef, bool isImp,
|
|||
if (RegInfo && WasReg)
|
||||
RegInfo->removeRegOperandFromUseList(this);
|
||||
|
||||
// Ensure debug instructions set debug flag on register uses.
|
||||
const MachineInstr *MI = getParent();
|
||||
if (!isDef && MI && MI->isDebugInstr())
|
||||
isDebug = true;
|
||||
|
||||
// Change this to a register and set the reg#.
|
||||
assert(!(isDead && !isDef) && "Dead flag on non-def");
|
||||
assert(!(isKill && isDef) && "Kill flag on def");
|
||||
|
|
|
@ -1889,6 +1889,15 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
|
|||
|
||||
switch (MO->getType()) {
|
||||
case MachineOperand::MO_Register: {
|
||||
// Verify debug flag on debug instructions. Check this first because reg0
|
||||
// indicates an undefined debug value.
|
||||
if (MI->isDebugInstr() && MO->isUse()) {
|
||||
if (!MO->isDebug())
|
||||
report("Register operand must be marked debug", MO, MONum);
|
||||
} else if (MO->isDebug()) {
|
||||
report("Register operand must not be marked debug", MO, MONum);
|
||||
}
|
||||
|
||||
const Register Reg = MO->getReg();
|
||||
if (!Reg)
|
||||
return;
|
||||
|
@ -1955,10 +1964,6 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (MI->isDebugValue() && MO->isUse() && !MO->isDebug()) {
|
||||
report("Use-reg is not IsDebug in a DBG_VALUE", MO, MONum);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Virtual register.
|
||||
const TargetRegisterClass *RC = MRI->getRegClassOrNull(Reg);
|
||||
|
|
|
@ -1253,7 +1253,6 @@ void PEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &MF,
|
|||
StackOffset Offset =
|
||||
TFI->getFrameIndexReference(MF, FrameIdx, Reg);
|
||||
Op.ChangeToRegister(Reg, false /*isDef*/);
|
||||
Op.setIsDebug();
|
||||
|
||||
const DIExpression *DIExpr = MI.getDebugExpression();
|
||||
|
||||
|
|
|
@ -722,7 +722,7 @@ void InstrEmitter::AddDbgValueLocationOps(
|
|||
MIB.addFrameIndex(Op.getFrameIx());
|
||||
break;
|
||||
case SDDbgOperand::VREG:
|
||||
MIB.addReg(Op.getVReg(), RegState::Debug);
|
||||
MIB.addReg(Op.getVReg());
|
||||
break;
|
||||
case SDDbgOperand::SDNODE: {
|
||||
SDValue V = SDValue(Op.getSDNode(), Op.getResNo());
|
||||
|
@ -862,7 +862,7 @@ MachineInstr *InstrEmitter::EmitDbgNoLocation(SDDbgValue *SD) {
|
|||
DebugLoc DL = SD->getDebugLoc();
|
||||
auto MIB = BuildMI(*MF, DL, TII->get(TargetOpcode::DBG_VALUE));
|
||||
MIB.addReg(0U);
|
||||
MIB.addReg(0U, RegState::Debug);
|
||||
MIB.addReg(0U);
|
||||
MIB.addMetadata(Var);
|
||||
MIB.addMetadata(Expr);
|
||||
return &*MIB;
|
||||
|
@ -898,7 +898,7 @@ InstrEmitter::EmitDbgValueFromSingleOp(SDDbgValue *SD,
|
|||
if (SD->isIndirect())
|
||||
MIB.addImm(0U);
|
||||
else
|
||||
MIB.addReg(0U, RegState::Debug);
|
||||
MIB.addReg(0U);
|
||||
|
||||
return MIB.addMetadata(Var).addMetadata(Expr);
|
||||
}
|
||||
|
|
|
@ -5518,7 +5518,7 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
|
|||
// pointing at the VReg, which will be patched up later.
|
||||
auto &Inst = TII->get(TargetOpcode::DBG_INSTR_REF);
|
||||
auto MIB = BuildMI(MF, DL, Inst);
|
||||
MIB.addReg(Reg, RegState::Debug);
|
||||
MIB.addReg(Reg);
|
||||
MIB.addImm(0);
|
||||
MIB.addMetadata(Variable);
|
||||
auto *NewDIExpr = FragExpr;
|
||||
|
|
|
@ -1202,7 +1202,6 @@ void SIFrameLowering::processFunctionBeforeFrameFinalized(
|
|||
if (MI.isDebugValue() && MI.getOperand(0).isFI() &&
|
||||
SpillFIs[MI.getOperand(0).getIndex()]) {
|
||||
MI.getOperand(0).ChangeToRegister(Register(), false /*isDef*/);
|
||||
MI.getOperand(0).setIsDebug();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -369,7 +369,6 @@ bool SILowerSGPRSpills::runOnMachineFunction(MachineFunction &MF) {
|
|||
if (MI.isDebugValue() && MI.getOperand(0).isFI() &&
|
||||
SpillFIs[MI.getOperand(0).getIndex()]) {
|
||||
MI.getOperand(0).ChangeToRegister(Register(), false /*isDef*/);
|
||||
MI.getOperand(0).setIsDebug();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,7 +74,6 @@ bool NVPTXPrologEpilogPass::runOnMachineFunction(MachineFunction &MF) {
|
|||
auto Offset =
|
||||
TFI.getFrameIndexReference(MF, Op.getIndex(), Reg);
|
||||
Op.ChangeToRegister(Reg, /*isDef=*/false);
|
||||
Op.setIsDebug();
|
||||
const DIExpression *DIExpr = MI.getDebugExpression();
|
||||
if (MI.isNonListDebugValue()) {
|
||||
DIExpr = TRI.prependOffsetExpression(MI.getDebugExpression(), DIExpression::ApplyOffset, Offset);
|
||||
|
|
|
@ -101,8 +101,6 @@ bool WebAssemblyReplacePhysRegs::runOnMachineFunction(MachineFunction &MF) {
|
|||
}
|
||||
}
|
||||
MO.setReg(VReg);
|
||||
if (MO.getParent()->isDebugValue())
|
||||
MO.setIsDebug();
|
||||
Changed = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2784,8 +2784,6 @@ bool X86FastISel::fastLowerIntrinsicCall(const IntrinsicInst *II) {
|
|||
if (!X86SelectAddress(DI->getAddress(), AM))
|
||||
return false;
|
||||
const MCInstrDesc &II = TII.get(TargetOpcode::DBG_VALUE);
|
||||
// FIXME may need to add RegState::Debug to any registers produced,
|
||||
// although ESP/EBP should be the only ones at the moment.
|
||||
assert(DI->getVariable()->isValidLocationForIntrinsic(DbgLoc) &&
|
||||
"Expected inlined-at fields to agree");
|
||||
addFullAddress(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II), AM)
|
||||
|
|
|
@ -499,8 +499,8 @@ TEST_F(AArch64GISelMITest, MatchMiscellaneous) {
|
|||
EXPECT_TRUE(mi_match(Reg, *MRI, m_OneNonDBGUse(m_GAdd(m_Reg(), m_Reg()))));
|
||||
|
||||
// Add multiple debug uses of Reg.
|
||||
B.buildInstr(TargetOpcode::DBG_VALUE, {}, {Reg})->getOperand(0).setIsDebug();
|
||||
B.buildInstr(TargetOpcode::DBG_VALUE, {}, {Reg})->getOperand(0).setIsDebug();
|
||||
B.buildInstr(TargetOpcode::DBG_VALUE, {}, {Reg});
|
||||
B.buildInstr(TargetOpcode::DBG_VALUE, {}, {Reg});
|
||||
|
||||
EXPECT_FALSE(mi_match(Reg, *MRI, m_OneUse(m_GAdd(m_Reg(), m_Reg()))));
|
||||
EXPECT_TRUE(mi_match(Reg, *MRI, m_OneNonDBGUse(m_GAdd(m_Reg(), m_Reg()))));
|
||||
|
|
|
@ -386,6 +386,32 @@ TEST(MachineInstrExtraInfo, RemoveExtraInfo) {
|
|||
ASSERT_FALSE(MI->getHeapAllocMarker());
|
||||
}
|
||||
|
||||
TEST(MachineInstrDebugValue, AddDebugValueOperand) {
|
||||
LLVMContext Ctx;
|
||||
Module Mod("Module", Ctx);
|
||||
auto MF = createMachineFunction(Ctx, Mod);
|
||||
|
||||
for (const unsigned short Opcode :
|
||||
{TargetOpcode::DBG_VALUE, TargetOpcode::DBG_VALUE_LIST,
|
||||
TargetOpcode::DBG_INSTR_REF, TargetOpcode::DBG_PHI,
|
||||
TargetOpcode::DBG_LABEL}) {
|
||||
const MCInstrDesc MCID = {
|
||||
Opcode, 0, 0,
|
||||
0, 0, (1ULL << MCID::Pseudo) | (1ULL << MCID::Variadic),
|
||||
0, nullptr, nullptr,
|
||||
nullptr};
|
||||
|
||||
auto *MI = MF->CreateMachineInstr(MCID, DebugLoc());
|
||||
MI->addOperand(*MF, MachineOperand::CreateReg(0, /*isDef*/ false));
|
||||
|
||||
MI->addOperand(*MF, MachineOperand::CreateImm(0));
|
||||
MI->getOperand(1).ChangeToRegister(0, false);
|
||||
|
||||
ASSERT_TRUE(MI->getOperand(0).isDebug());
|
||||
ASSERT_TRUE(MI->getOperand(1).isDebug());
|
||||
}
|
||||
}
|
||||
|
||||
static_assert(std::is_trivially_copyable<MCOperand>::value,
|
||||
"trivially copyable");
|
||||
|
||||
|
|
Loading…
Reference in New Issue