[ARM][MC] Move information about variadic register defs into tablegen

Currently, variadic operands on an MCInst are assumed to be uses,
because they come after the defs. However, this is not always the case,
for example the Arm/Thumb LDM instructions write to a variable number of
registers.

This adds a property of instruction definitions which can be used to
mark variadic operands as defs. This only affects MCInst, because
MachineInstruction already tracks use/def per operand in each instance
of the instruction, so can already represent this.

This property can then be checked in MCInstrDesc, allowing us to remove
some special cases in ARMAsmParser::isITBlockTerminator.

Differential revision: https://reviews.llvm.org/D54853

llvm-svn: 348114
This commit is contained in:
Oliver Stannard
2018-12-03 10:32:42 +00:00
parent c588110f13
commit 4cf35b4ab0
11 changed files with 23 additions and 39 deletions

View File

@@ -151,7 +151,8 @@ enum Flag {
InsertSubreg,
Convergent,
Add,
Trap
Trap,
VariadicOpsAreDefs,
};
}
@@ -383,6 +384,11 @@ public:
/// additional values.
bool isConvergent() const { return Flags & (1ULL << MCID::Convergent); }
/// Return true if variadic operands of this instruction are definitions.
bool variadicOpsAreDefs() const {
return Flags & (1ULL << MCID::VariadicOpsAreDefs);
}
//===--------------------------------------------------------------------===//
// Side Effect Analysis
//===--------------------------------------------------------------------===//

View File

@@ -479,6 +479,7 @@ class Instruction {
bit isInsertSubreg = 0; // Is this instruction a kind of insert subreg?
// If so, make sure to override
// TargetInstrInfo::getInsertSubregLikeInputs.
bit variadicOpsAreDefs = 0; // Are variadic operands definitions?
// Does the instruction have side effects that are not captured by any
// operands of the instruction or other flags?

View File

@@ -39,15 +39,6 @@ bool MCInstrDesc::mayAffectControlFlow(const MCInst &MI,
return false;
if (hasDefOfPhysReg(MI, PC, RI))
return true;
// A variadic instruction may define PC in the variable operand list.
// There's currently no indication of which entries in a variable
// list are defs and which are uses. While that's the case, this function
// needs to assume they're defs in order to be conservatively correct.
for (int i = NumOperands, e = MI.getNumOperands(); i != e; ++i) {
if (MI.getOperand(i).isReg() &&
RI.isSubRegisterEq(PC, MI.getOperand(i).getReg()))
return true;
}
return false;
}
@@ -66,5 +57,10 @@ bool MCInstrDesc::hasDefOfPhysReg(const MCInst &MI, unsigned Reg,
if (MI.getOperand(i).isReg() &&
RI.isSubRegisterEq(Reg, MI.getOperand(i).getReg()))
return true;
if (variadicOpsAreDefs())
for (int i = NumOperands - 1, e = MI.getNumOperands(); i != e; ++i)
if (MI.getOperand(i).isReg() &&
RI.isSubRegisterEq(Reg, MI.getOperand(i).getReg()))
return true;
return hasImplicitDefOfPhysReg(Reg, &RI);
}

View File

@@ -3334,7 +3334,7 @@ multiclass arm_ldst_mult<string asm, string sfx, bit L_bit, bit P_bit, Format f,
let hasSideEffects = 0 in {
let mayLoad = 1, hasExtraDefRegAllocReq = 1 in
let mayLoad = 1, hasExtraDefRegAllocReq = 1, variadicOpsAreDefs = 1 in
defm LDM : arm_ldst_mult<"ldm", "", 1, 0, LdStMulFrm, IIC_iLoad_m,
IIC_iLoad_mu>, ComplexDeprecationPredicate<"ARMLoad">;

View File

@@ -781,7 +781,7 @@ defm tSTRH : thumb_st_rr_ri_enc<0b001, 0b1000, t_addrmode_rr,
// These require base address to be written back or one of the loaded regs.
let hasSideEffects = 0 in {
let mayLoad = 1, hasExtraDefRegAllocReq = 1 in
let mayLoad = 1, hasExtraDefRegAllocReq = 1, variadicOpsAreDefs = 1 in
def tLDMIA : T1I<(outs), (ins tGPR:$Rn, pred:$p, reglist:$regs, variable_ops),
IIC_iLoad_m, "ldm${p}\t$Rn, $regs", []>, T1Encoding<{1,1,0,0,1,?}> {
bits<3> Rn;
@@ -826,7 +826,8 @@ def : InstAlias<"ldm${p} $Rn!, $regs",
(tLDMIA tGPR:$Rn, pred:$p, reglist:$regs), 0>,
Requires<[IsThumb, IsThumb1Only]>;
let mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1 in
let mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1,
variadicOpsAreDefs = 1 in
def tPOP : T1I<(outs), (ins pred:$p, reglist:$regs, variable_ops),
IIC_iPop,
"pop${p}\t$regs", []>,

View File

@@ -1775,7 +1775,7 @@ multiclass thumb2_ld_mult<string asm, InstrItinClass itin,
let hasSideEffects = 0 in {
let mayLoad = 1, hasExtraDefRegAllocReq = 1 in
let mayLoad = 1, hasExtraDefRegAllocReq = 1, variadicOpsAreDefs = 1 in
defm t2LDM : thumb2_ld_mult<"ldm", IIC_iLoad_m, IIC_iLoad_mu, 1>;
multiclass thumb2_st_mult<string asm, InstrItinClass itin,

View File

@@ -9177,33 +9177,9 @@ bool ARMAsmParser::isITBlockTerminator(MCInst &Inst) const {
// Any arithmetic instruction which writes to the PC also terminates the IT
// block.
for (unsigned OpIdx = 0; OpIdx < MCID.getNumDefs(); ++OpIdx) {
MCOperand &Op = Inst.getOperand(OpIdx);
if (Op.isReg() && Op.getReg() == ARM::PC)
return true;
}
if (MCID.hasImplicitDefOfPhysReg(ARM::PC, MRI))
if (MCID.hasDefOfPhysReg(Inst, ARM::PC, *MRI))
return true;
// Instructions with variable operand lists, which write to the variable
// operands. We only care about Thumb instructions here, as ARM instructions
// obviously can't be in an IT block.
switch (Inst.getOpcode()) {
case ARM::tLDMIA:
case ARM::t2LDMIA:
case ARM::t2LDMIA_UPD:
case ARM::t2LDMDB:
case ARM::t2LDMDB_UPD:
if (listContainsReg(Inst, 3, ARM::PC))
return true;
break;
case ARM::tPOP:
if (listContainsReg(Inst, 2, ARM::PC))
return true;
break;
}
return false;
}

View File

@@ -370,6 +370,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R)
isConvergent = R->getValueAsBit("isConvergent");
hasNoSchedulingInfo = R->getValueAsBit("hasNoSchedulingInfo");
FastISelShouldIgnore = R->getValueAsBit("FastISelShouldIgnore");
variadicOpsAreDefs = R->getValueAsBit("variadicOpsAreDefs");
bool Unset;
mayLoad = R->getValueAsBitOrUnset("mayLoad", Unset);

View File

@@ -275,6 +275,7 @@ template <typename T> class ArrayRef;
bool FastISelShouldIgnore : 1;
bool hasChain : 1;
bool hasChain_Inferred : 1;
bool variadicOpsAreDefs : 1;
std::string DeprecatedReason;
bool HasComplexDeprecationPredicate;

View File

@@ -138,6 +138,7 @@ void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS) {
FLAG(isInsertSubreg)
FLAG(isConvergent)
FLAG(hasNoSchedulingInfo)
FLAG(variadicOpsAreDefs)
if (!FlagStrings.empty()) {
OS << "Flags: ";
bool IsFirst = true;

View File

@@ -625,6 +625,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
if (Inst.isExtractSubreg) OS << "|(1ULL<<MCID::ExtractSubreg)";
if (Inst.isInsertSubreg) OS << "|(1ULL<<MCID::InsertSubreg)";
if (Inst.isConvergent) OS << "|(1ULL<<MCID::Convergent)";
if (Inst.variadicOpsAreDefs) OS << "|(1ULL<<MCID::VariadicOpsAreDefs)";
// Emit all of the target-specific flags...
BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags");