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;
|
const DIExpression *Expr = Properties.DIExpr;
|
||||||
if (!MLoc) {
|
if (!MLoc) {
|
||||||
// No location -> DBG_VALUE $noreg
|
// No location -> DBG_VALUE $noreg
|
||||||
MIB.addReg(0, RegState::Debug);
|
MIB.addReg(0);
|
||||||
MIB.addReg(0, RegState::Debug);
|
MIB.addReg(0);
|
||||||
} else if (LocIdxToLocID[*MLoc] >= NumRegs) {
|
} else if (LocIdxToLocID[*MLoc] >= NumRegs) {
|
||||||
unsigned LocID = LocIdxToLocID[*MLoc];
|
unsigned LocID = LocIdxToLocID[*MLoc];
|
||||||
const SpillLoc &Spill = SpillLocs[LocID - NumRegs + 1];
|
const SpillLoc &Spill = SpillLocs[LocID - NumRegs + 1];
|
||||||
|
@ -774,15 +774,15 @@ public:
|
||||||
Expr = TRI->prependOffsetExpression(Expr, DIExpression::ApplyOffset,
|
Expr = TRI->prependOffsetExpression(Expr, DIExpression::ApplyOffset,
|
||||||
Spill.SpillOffset);
|
Spill.SpillOffset);
|
||||||
unsigned Base = Spill.SpillBase;
|
unsigned Base = Spill.SpillBase;
|
||||||
MIB.addReg(Base, RegState::Debug);
|
MIB.addReg(Base);
|
||||||
MIB.addImm(0);
|
MIB.addImm(0);
|
||||||
} else {
|
} else {
|
||||||
unsigned LocID = LocIdxToLocID[*MLoc];
|
unsigned LocID = LocIdxToLocID[*MLoc];
|
||||||
MIB.addReg(LocID, RegState::Debug);
|
MIB.addReg(LocID);
|
||||||
if (Properties.Indirect)
|
if (Properties.Indirect)
|
||||||
MIB.addImm(0);
|
MIB.addImm(0);
|
||||||
else
|
else
|
||||||
MIB.addReg(0, RegState::Debug);
|
MIB.addReg(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
MIB.addMetadata(Var.getVariable());
|
MIB.addMetadata(Var.getVariable());
|
||||||
|
@ -1220,7 +1220,6 @@ public:
|
||||||
DIExpression::prepend(Prop.DIExpr, DIExpression::EntryValue);
|
DIExpression::prepend(Prop.DIExpr, DIExpression::EntryValue);
|
||||||
Register Reg = MTracker->LocIdxToLocID[Num.getLoc()];
|
Register Reg = MTracker->LocIdxToLocID[Num.getLoc()];
|
||||||
MachineOperand MO = MachineOperand::CreateReg(Reg, false);
|
MachineOperand MO = MachineOperand::CreateReg(Reg, false);
|
||||||
MO.setIsDebug(true);
|
|
||||||
|
|
||||||
PendingDbgValues.push_back(emitMOLoc(MO, Var, {NewExpr, Prop.Indirect}));
|
PendingDbgValues.push_back(emitMOLoc(MO, Var, {NewExpr, Prop.Indirect}));
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -546,7 +546,6 @@ private:
|
||||||
EVKind == EntryValueLocKind::EntryValueKind ? Orig.getReg()
|
EVKind == EntryValueLocKind::EntryValueKind ? Orig.getReg()
|
||||||
: Register(Loc.RegNo),
|
: Register(Loc.RegNo),
|
||||||
false));
|
false));
|
||||||
MOs.back().setIsDebug();
|
|
||||||
break;
|
break;
|
||||||
case MachineLocKind::SpillLocKind: {
|
case MachineLocKind::SpillLocKind: {
|
||||||
// Spills are indirect DBG_VALUEs, with a base register and offset.
|
// Spills are indirect DBG_VALUEs, with a base register and offset.
|
||||||
|
@ -568,7 +567,6 @@ private:
|
||||||
DIExpr = DIExpression::appendOpsToArg(DIExpr, Ops, I);
|
DIExpr = DIExpression::appendOpsToArg(DIExpr, Ops, I);
|
||||||
}
|
}
|
||||||
MOs.push_back(MachineOperand::CreateReg(Base, false));
|
MOs.push_back(MachineOperand::CreateReg(Base, false));
|
||||||
MOs.back().setIsDebug();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MachineLocKind::ImmediateKind: {
|
case MachineLocKind::ImmediateKind: {
|
||||||
|
|
|
@ -1011,10 +1011,6 @@ bool MIParser::parse(MachineInstr *&MI) {
|
||||||
Optional<unsigned> TiedDefIdx;
|
Optional<unsigned> TiedDefIdx;
|
||||||
if (parseMachineOperandAndTargetFlags(OpCode, Operands.size(), MO, TiedDefIdx))
|
if (parseMachineOperandAndTargetFlags(OpCode, Operands.size(), MO, TiedDefIdx))
|
||||||
return true;
|
return true;
|
||||||
if ((OpCode == TargetOpcode::DBG_VALUE ||
|
|
||||||
OpCode == TargetOpcode::DBG_VALUE_LIST) &&
|
|
||||||
MO.isReg())
|
|
||||||
MO.setIsDebug();
|
|
||||||
Operands.push_back(
|
Operands.push_back(
|
||||||
ParsedMachineOperand(MO, Loc, Token.location(), TiedDefIdx));
|
ParsedMachineOperand(MO, Loc, Token.location(), TiedDefIdx));
|
||||||
if (Token.isNewlineOrEOF() || Token.is(MIToken::coloncolon) ||
|
if (Token.isNewlineOrEOF() || Token.is(MIToken::coloncolon) ||
|
||||||
|
|
|
@ -1158,7 +1158,7 @@ auto MachineFunction::salvageCopySSA(MachineInstr &MI)
|
||||||
// Create DBG_PHI for specified physreg.
|
// Create DBG_PHI for specified physreg.
|
||||||
auto Builder = BuildMI(InsertBB, InsertBB.getFirstNonPHI(), DebugLoc(),
|
auto Builder = BuildMI(InsertBB, InsertBB.getFirstNonPHI(), DebugLoc(),
|
||||||
TII.get(TargetOpcode::DBG_PHI));
|
TII.get(TargetOpcode::DBG_PHI));
|
||||||
Builder.addReg(State.first, RegState::Debug);
|
Builder.addReg(State.first);
|
||||||
unsigned NewNum = getNewDebugInstrNum();
|
unsigned NewNum = getNewDebugInstrNum();
|
||||||
Builder.addImm(NewNum);
|
Builder.addImm(NewNum);
|
||||||
return ApplySubregisters({NewNum, 0u});
|
return ApplySubregisters({NewNum, 0u});
|
||||||
|
@ -1171,7 +1171,6 @@ void MachineFunction::finalizeDebugInstrRefs() {
|
||||||
const MCInstrDesc &RefII = TII->get(TargetOpcode::DBG_VALUE);
|
const MCInstrDesc &RefII = TII->get(TargetOpcode::DBG_VALUE);
|
||||||
MI.setDesc(RefII);
|
MI.setDesc(RefII);
|
||||||
MI.getOperand(1).ChangeToRegister(0, false);
|
MI.getOperand(1).ChangeToRegister(0, false);
|
||||||
MI.getOperand(0).setIsDebug();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!useDebugInstrRef())
|
if (!useDebugInstrRef())
|
||||||
|
|
|
@ -294,6 +294,9 @@ void MachineInstr::addOperand(MachineFunction &MF, const MachineOperand &Op) {
|
||||||
if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1)
|
if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1)
|
||||||
NewMO->setIsEarlyClobber(true);
|
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<DIExpression>(Expr)->isValid() && "not an expression");
|
||||||
assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
|
assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
|
||||||
"Expected inlined-at fields to agree");
|
"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)
|
if (IsIndirect)
|
||||||
MIB.addImm(0U);
|
MIB.addImm(0U);
|
||||||
else
|
else
|
||||||
MIB.addReg(0U, RegState::Debug);
|
MIB.addReg(0U);
|
||||||
return MIB.addMetadata(Variable).addMetadata(Expr);
|
return MIB.addMetadata(Variable).addMetadata(Expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2134,7 +2137,7 @@ MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
|
||||||
if (IsIndirect)
|
if (IsIndirect)
|
||||||
MIB.addImm(0U);
|
MIB.addImm(0U);
|
||||||
else
|
else
|
||||||
MIB.addReg(0U, RegState::Debug);
|
MIB.addReg(0U);
|
||||||
return MIB.addMetadata(Variable).addMetadata(Expr);
|
return MIB.addMetadata(Variable).addMetadata(Expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2153,7 +2156,7 @@ MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
|
||||||
MIB.addMetadata(Variable).addMetadata(Expr);
|
MIB.addMetadata(Variable).addMetadata(Expr);
|
||||||
for (const MachineOperand &MO : MOs)
|
for (const MachineOperand &MO : MOs)
|
||||||
if (MO.isReg())
|
if (MO.isReg())
|
||||||
MIB.addReg(MO.getReg(), RegState::Debug);
|
MIB.addReg(MO.getReg());
|
||||||
else
|
else
|
||||||
MIB.add(MO);
|
MIB.add(MO);
|
||||||
return MIB;
|
return MIB;
|
||||||
|
|
|
@ -250,6 +250,11 @@ void MachineOperand::ChangeToRegister(Register Reg, bool isDef, bool isImp,
|
||||||
if (RegInfo && WasReg)
|
if (RegInfo && WasReg)
|
||||||
RegInfo->removeRegOperandFromUseList(this);
|
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#.
|
// Change this to a register and set the reg#.
|
||||||
assert(!(isDead && !isDef) && "Dead flag on non-def");
|
assert(!(isDead && !isDef) && "Dead flag on non-def");
|
||||||
assert(!(isKill && isDef) && "Kill flag on def");
|
assert(!(isKill && isDef) && "Kill flag on def");
|
||||||
|
|
|
@ -1889,6 +1889,15 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
|
||||||
|
|
||||||
switch (MO->getType()) {
|
switch (MO->getType()) {
|
||||||
case MachineOperand::MO_Register: {
|
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();
|
const Register Reg = MO->getReg();
|
||||||
if (!Reg)
|
if (!Reg)
|
||||||
return;
|
return;
|
||||||
|
@ -1955,10 +1964,6 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (MI->isDebugValue() && MO->isUse() && !MO->isDebug()) {
|
|
||||||
report("Use-reg is not IsDebug in a DBG_VALUE", MO, MONum);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Virtual register.
|
// Virtual register.
|
||||||
const TargetRegisterClass *RC = MRI->getRegClassOrNull(Reg);
|
const TargetRegisterClass *RC = MRI->getRegClassOrNull(Reg);
|
||||||
|
|
|
@ -1253,7 +1253,6 @@ void PEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &MF,
|
||||||
StackOffset Offset =
|
StackOffset Offset =
|
||||||
TFI->getFrameIndexReference(MF, FrameIdx, Reg);
|
TFI->getFrameIndexReference(MF, FrameIdx, Reg);
|
||||||
Op.ChangeToRegister(Reg, false /*isDef*/);
|
Op.ChangeToRegister(Reg, false /*isDef*/);
|
||||||
Op.setIsDebug();
|
|
||||||
|
|
||||||
const DIExpression *DIExpr = MI.getDebugExpression();
|
const DIExpression *DIExpr = MI.getDebugExpression();
|
||||||
|
|
||||||
|
|
|
@ -722,7 +722,7 @@ void InstrEmitter::AddDbgValueLocationOps(
|
||||||
MIB.addFrameIndex(Op.getFrameIx());
|
MIB.addFrameIndex(Op.getFrameIx());
|
||||||
break;
|
break;
|
||||||
case SDDbgOperand::VREG:
|
case SDDbgOperand::VREG:
|
||||||
MIB.addReg(Op.getVReg(), RegState::Debug);
|
MIB.addReg(Op.getVReg());
|
||||||
break;
|
break;
|
||||||
case SDDbgOperand::SDNODE: {
|
case SDDbgOperand::SDNODE: {
|
||||||
SDValue V = SDValue(Op.getSDNode(), Op.getResNo());
|
SDValue V = SDValue(Op.getSDNode(), Op.getResNo());
|
||||||
|
@ -862,7 +862,7 @@ MachineInstr *InstrEmitter::EmitDbgNoLocation(SDDbgValue *SD) {
|
||||||
DebugLoc DL = SD->getDebugLoc();
|
DebugLoc DL = SD->getDebugLoc();
|
||||||
auto MIB = BuildMI(*MF, DL, TII->get(TargetOpcode::DBG_VALUE));
|
auto MIB = BuildMI(*MF, DL, TII->get(TargetOpcode::DBG_VALUE));
|
||||||
MIB.addReg(0U);
|
MIB.addReg(0U);
|
||||||
MIB.addReg(0U, RegState::Debug);
|
MIB.addReg(0U);
|
||||||
MIB.addMetadata(Var);
|
MIB.addMetadata(Var);
|
||||||
MIB.addMetadata(Expr);
|
MIB.addMetadata(Expr);
|
||||||
return &*MIB;
|
return &*MIB;
|
||||||
|
@ -898,7 +898,7 @@ InstrEmitter::EmitDbgValueFromSingleOp(SDDbgValue *SD,
|
||||||
if (SD->isIndirect())
|
if (SD->isIndirect())
|
||||||
MIB.addImm(0U);
|
MIB.addImm(0U);
|
||||||
else
|
else
|
||||||
MIB.addReg(0U, RegState::Debug);
|
MIB.addReg(0U);
|
||||||
|
|
||||||
return MIB.addMetadata(Var).addMetadata(Expr);
|
return MIB.addMetadata(Var).addMetadata(Expr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5518,7 +5518,7 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
|
||||||
// pointing at the VReg, which will be patched up later.
|
// pointing at the VReg, which will be patched up later.
|
||||||
auto &Inst = TII->get(TargetOpcode::DBG_INSTR_REF);
|
auto &Inst = TII->get(TargetOpcode::DBG_INSTR_REF);
|
||||||
auto MIB = BuildMI(MF, DL, Inst);
|
auto MIB = BuildMI(MF, DL, Inst);
|
||||||
MIB.addReg(Reg, RegState::Debug);
|
MIB.addReg(Reg);
|
||||||
MIB.addImm(0);
|
MIB.addImm(0);
|
||||||
MIB.addMetadata(Variable);
|
MIB.addMetadata(Variable);
|
||||||
auto *NewDIExpr = FragExpr;
|
auto *NewDIExpr = FragExpr;
|
||||||
|
|
|
@ -1202,7 +1202,6 @@ void SIFrameLowering::processFunctionBeforeFrameFinalized(
|
||||||
if (MI.isDebugValue() && MI.getOperand(0).isFI() &&
|
if (MI.isDebugValue() && MI.getOperand(0).isFI() &&
|
||||||
SpillFIs[MI.getOperand(0).getIndex()]) {
|
SpillFIs[MI.getOperand(0).getIndex()]) {
|
||||||
MI.getOperand(0).ChangeToRegister(Register(), false /*isDef*/);
|
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() &&
|
if (MI.isDebugValue() && MI.getOperand(0).isFI() &&
|
||||||
SpillFIs[MI.getOperand(0).getIndex()]) {
|
SpillFIs[MI.getOperand(0).getIndex()]) {
|
||||||
MI.getOperand(0).ChangeToRegister(Register(), false /*isDef*/);
|
MI.getOperand(0).ChangeToRegister(Register(), false /*isDef*/);
|
||||||
MI.getOperand(0).setIsDebug();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,6 @@ bool NVPTXPrologEpilogPass::runOnMachineFunction(MachineFunction &MF) {
|
||||||
auto Offset =
|
auto Offset =
|
||||||
TFI.getFrameIndexReference(MF, Op.getIndex(), Reg);
|
TFI.getFrameIndexReference(MF, Op.getIndex(), Reg);
|
||||||
Op.ChangeToRegister(Reg, /*isDef=*/false);
|
Op.ChangeToRegister(Reg, /*isDef=*/false);
|
||||||
Op.setIsDebug();
|
|
||||||
const DIExpression *DIExpr = MI.getDebugExpression();
|
const DIExpression *DIExpr = MI.getDebugExpression();
|
||||||
if (MI.isNonListDebugValue()) {
|
if (MI.isNonListDebugValue()) {
|
||||||
DIExpr = TRI.prependOffsetExpression(MI.getDebugExpression(), DIExpression::ApplyOffset, Offset);
|
DIExpr = TRI.prependOffsetExpression(MI.getDebugExpression(), DIExpression::ApplyOffset, Offset);
|
||||||
|
|
|
@ -101,8 +101,6 @@ bool WebAssemblyReplacePhysRegs::runOnMachineFunction(MachineFunction &MF) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MO.setReg(VReg);
|
MO.setReg(VReg);
|
||||||
if (MO.getParent()->isDebugValue())
|
|
||||||
MO.setIsDebug();
|
|
||||||
Changed = true;
|
Changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2784,8 +2784,6 @@ bool X86FastISel::fastLowerIntrinsicCall(const IntrinsicInst *II) {
|
||||||
if (!X86SelectAddress(DI->getAddress(), AM))
|
if (!X86SelectAddress(DI->getAddress(), AM))
|
||||||
return false;
|
return false;
|
||||||
const MCInstrDesc &II = TII.get(TargetOpcode::DBG_VALUE);
|
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) &&
|
assert(DI->getVariable()->isValidLocationForIntrinsic(DbgLoc) &&
|
||||||
"Expected inlined-at fields to agree");
|
"Expected inlined-at fields to agree");
|
||||||
addFullAddress(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II), AM)
|
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()))));
|
EXPECT_TRUE(mi_match(Reg, *MRI, m_OneNonDBGUse(m_GAdd(m_Reg(), m_Reg()))));
|
||||||
|
|
||||||
// Add multiple debug uses of Reg.
|
// Add multiple debug uses of Reg.
|
||||||
B.buildInstr(TargetOpcode::DBG_VALUE, {}, {Reg})->getOperand(0).setIsDebug();
|
B.buildInstr(TargetOpcode::DBG_VALUE, {}, {Reg});
|
||||||
B.buildInstr(TargetOpcode::DBG_VALUE, {}, {Reg})->getOperand(0).setIsDebug();
|
B.buildInstr(TargetOpcode::DBG_VALUE, {}, {Reg});
|
||||||
|
|
||||||
EXPECT_FALSE(mi_match(Reg, *MRI, m_OneUse(m_GAdd(m_Reg(), m_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()))));
|
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());
|
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,
|
static_assert(std::is_trivially_copyable<MCOperand>::value,
|
||||||
"trivially copyable");
|
"trivially copyable");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue