forked from OSchip/llvm-project
Distinguish early clobber output operands from clobbered registers.
Both become <earlyclobber> defs on the INLINEASM MachineInstr, but we now use two different asm operand kinds. The new Kind_Clobber is treated identically to the old Kind_RegDefEarlyClobber for now, but x87 floating point stack inline assembly does care about the difference. This will pop a register off the stack: asm("fstp %st" : : "t"(x) : "st"); While this will pop the input and push an output: asm("fst %st" : "=&t"(r) : "t"(x)); We need to know if ST0 was a clobber or an output operand, and we can't depend on <dead> flags for that. llvm-svn: 133902
This commit is contained in:
parent
6b356b18b4
commit
537a302d1a
|
@ -188,24 +188,31 @@ public:
|
|||
// in the backend.
|
||||
|
||||
enum {
|
||||
// Fixed operands on an INLINEASM SDNode.
|
||||
Op_InputChain = 0,
|
||||
Op_AsmString = 1,
|
||||
Op_MDNode = 2,
|
||||
Op_ExtraInfo = 3, // HasSideEffects, IsAlignStack
|
||||
Op_FirstOperand = 4,
|
||||
|
||||
// Fixed operands on an INLINEASM MachineInstr.
|
||||
MIOp_AsmString = 0,
|
||||
MIOp_ExtraInfo = 1, // HasSideEffects, IsAlignStack
|
||||
MIOp_FirstOperand = 2,
|
||||
|
||||
// Interpretation of the MIOp_ExtraInfo bit field.
|
||||
Extra_HasSideEffects = 1,
|
||||
Extra_IsAlignStack = 2,
|
||||
|
||||
Kind_RegUse = 1,
|
||||
Kind_RegDef = 2,
|
||||
Kind_Imm = 3,
|
||||
Kind_Mem = 4,
|
||||
Kind_RegDefEarlyClobber = 6,
|
||||
// Inline asm operands map to multiple SDNode / MachineInstr operands.
|
||||
// The first operand is an immediate describing the asm operand, the low
|
||||
// bits is the kind:
|
||||
Kind_RegUse = 1, // Input register, "r".
|
||||
Kind_RegDef = 2, // Output register, "=r".
|
||||
Kind_RegDefEarlyClobber = 3, // Early-clobber output register, "=&r".
|
||||
Kind_Clobber = 4, // Clobbered register, "~r".
|
||||
Kind_Imm = 5, // Immediate.
|
||||
Kind_Mem = 6, // Memory operand, "m".
|
||||
|
||||
Flag_MatchingOperand = 0x80000000
|
||||
};
|
||||
|
@ -233,6 +240,9 @@ public:
|
|||
static bool isRegDefEarlyClobberKind(unsigned Flag) {
|
||||
return getKind(Flag) == Kind_RegDefEarlyClobber;
|
||||
}
|
||||
static bool isClobberKind(unsigned Flag) {
|
||||
return getKind(Flag) == Kind_Clobber;
|
||||
}
|
||||
|
||||
/// getNumOperandRegisters - Extract the number of registers field from the
|
||||
/// inline asm operand flag.
|
||||
|
|
|
@ -1443,9 +1443,10 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const {
|
|||
switch (InlineAsm::getKind(Flag)) {
|
||||
case InlineAsm::Kind_RegUse: OS << ":[reguse]"; break;
|
||||
case InlineAsm::Kind_RegDef: OS << ":[regdef]"; break;
|
||||
case InlineAsm::Kind_RegDefEarlyClobber: OS << ":[regdef-ec]"; break;
|
||||
case InlineAsm::Kind_Clobber: OS << ":[clobber]"; break;
|
||||
case InlineAsm::Kind_Imm: OS << ":[imm]"; break;
|
||||
case InlineAsm::Kind_Mem: OS << ":[mem]"; break;
|
||||
case InlineAsm::Kind_RegDefEarlyClobber: OS << ":[regdef-ec]"; break;
|
||||
default: OS << ":[??" << InlineAsm::getKind(Flag) << ']'; break;
|
||||
}
|
||||
|
||||
|
|
|
@ -851,6 +851,7 @@ EmitSpecialNode(SDNode *Node, bool IsClone, bool IsCloned,
|
|||
}
|
||||
break;
|
||||
case InlineAsm::Kind_RegDefEarlyClobber:
|
||||
case InlineAsm::Kind_Clobber:
|
||||
for (; NumVals; --NumVals, ++i) {
|
||||
unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
|
||||
MI->addOperand(MachineOperand::CreateReg(Reg, /*isDef=*/ true,
|
||||
|
|
|
@ -490,7 +490,8 @@ bool ScheduleDAGFast::DelayForLiveRegsBottomUp(SUnit *SU,
|
|||
|
||||
++i; // Skip the ID value.
|
||||
if (InlineAsm::isRegDefKind(Flags) ||
|
||||
InlineAsm::isRegDefEarlyClobberKind(Flags)) {
|
||||
InlineAsm::isRegDefEarlyClobberKind(Flags) ||
|
||||
InlineAsm::isClobberKind(Flags)) {
|
||||
// Check for def of register or earlyclobber register.
|
||||
for (; NumVals; --NumVals, ++i) {
|
||||
unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
|
||||
|
|
|
@ -1092,7 +1092,8 @@ DelayForLiveRegsBottomUp(SUnit *SU, SmallVector<unsigned, 4> &LRegs) {
|
|||
|
||||
++i; // Skip the ID value.
|
||||
if (InlineAsm::isRegDefKind(Flags) ||
|
||||
InlineAsm::isRegDefEarlyClobberKind(Flags)) {
|
||||
InlineAsm::isRegDefEarlyClobberKind(Flags) ||
|
||||
InlineAsm::isClobberKind(Flags)) {
|
||||
// Check for def of register or earlyclobber register.
|
||||
for (; NumVals; --NumVals, ++i) {
|
||||
unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
|
||||
|
|
|
@ -6051,8 +6051,7 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
|
|||
// Add the clobbered value to the operand list, so that the register
|
||||
// allocator is aware that the physreg got clobbered.
|
||||
if (!OpInfo.AssignedRegs.Regs.empty())
|
||||
OpInfo.AssignedRegs.AddInlineAsmOperands(
|
||||
InlineAsm::Kind_RegDefEarlyClobber,
|
||||
OpInfo.AssignedRegs.AddInlineAsmOperands(InlineAsm::Kind_Clobber,
|
||||
false, 0, DAG,
|
||||
AsmNodeOperands);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue