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.
|
// in the backend.
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
// Fixed operands on an INLINEASM SDNode.
|
||||||
Op_InputChain = 0,
|
Op_InputChain = 0,
|
||||||
Op_AsmString = 1,
|
Op_AsmString = 1,
|
||||||
Op_MDNode = 2,
|
Op_MDNode = 2,
|
||||||
Op_ExtraInfo = 3, // HasSideEffects, IsAlignStack
|
Op_ExtraInfo = 3, // HasSideEffects, IsAlignStack
|
||||||
Op_FirstOperand = 4,
|
Op_FirstOperand = 4,
|
||||||
|
|
||||||
|
// Fixed operands on an INLINEASM MachineInstr.
|
||||||
MIOp_AsmString = 0,
|
MIOp_AsmString = 0,
|
||||||
MIOp_ExtraInfo = 1, // HasSideEffects, IsAlignStack
|
MIOp_ExtraInfo = 1, // HasSideEffects, IsAlignStack
|
||||||
MIOp_FirstOperand = 2,
|
MIOp_FirstOperand = 2,
|
||||||
|
|
||||||
|
// Interpretation of the MIOp_ExtraInfo bit field.
|
||||||
Extra_HasSideEffects = 1,
|
Extra_HasSideEffects = 1,
|
||||||
Extra_IsAlignStack = 2,
|
Extra_IsAlignStack = 2,
|
||||||
|
|
||||||
Kind_RegUse = 1,
|
// Inline asm operands map to multiple SDNode / MachineInstr operands.
|
||||||
Kind_RegDef = 2,
|
// The first operand is an immediate describing the asm operand, the low
|
||||||
Kind_Imm = 3,
|
// bits is the kind:
|
||||||
Kind_Mem = 4,
|
Kind_RegUse = 1, // Input register, "r".
|
||||||
Kind_RegDefEarlyClobber = 6,
|
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
|
Flag_MatchingOperand = 0x80000000
|
||||||
};
|
};
|
||||||
|
@ -233,6 +240,9 @@ public:
|
||||||
static bool isRegDefEarlyClobberKind(unsigned Flag) {
|
static bool isRegDefEarlyClobberKind(unsigned Flag) {
|
||||||
return getKind(Flag) == Kind_RegDefEarlyClobber;
|
return getKind(Flag) == Kind_RegDefEarlyClobber;
|
||||||
}
|
}
|
||||||
|
static bool isClobberKind(unsigned Flag) {
|
||||||
|
return getKind(Flag) == Kind_Clobber;
|
||||||
|
}
|
||||||
|
|
||||||
/// getNumOperandRegisters - Extract the number of registers field from the
|
/// getNumOperandRegisters - Extract the number of registers field from the
|
||||||
/// inline asm operand flag.
|
/// inline asm operand flag.
|
||||||
|
|
|
@ -1443,9 +1443,10 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const {
|
||||||
switch (InlineAsm::getKind(Flag)) {
|
switch (InlineAsm::getKind(Flag)) {
|
||||||
case InlineAsm::Kind_RegUse: OS << ":[reguse]"; break;
|
case InlineAsm::Kind_RegUse: OS << ":[reguse]"; break;
|
||||||
case InlineAsm::Kind_RegDef: OS << ":[regdef]"; 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_Imm: OS << ":[imm]"; break;
|
||||||
case InlineAsm::Kind_Mem: OS << ":[mem]"; break;
|
case InlineAsm::Kind_Mem: OS << ":[mem]"; break;
|
||||||
case InlineAsm::Kind_RegDefEarlyClobber: OS << ":[regdef-ec]"; break;
|
|
||||||
default: OS << ":[??" << InlineAsm::getKind(Flag) << ']'; break;
|
default: OS << ":[??" << InlineAsm::getKind(Flag) << ']'; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -851,6 +851,7 @@ EmitSpecialNode(SDNode *Node, bool IsClone, bool IsCloned,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case InlineAsm::Kind_RegDefEarlyClobber:
|
case InlineAsm::Kind_RegDefEarlyClobber:
|
||||||
|
case InlineAsm::Kind_Clobber:
|
||||||
for (; NumVals; --NumVals, ++i) {
|
for (; NumVals; --NumVals, ++i) {
|
||||||
unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
|
unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
|
||||||
MI->addOperand(MachineOperand::CreateReg(Reg, /*isDef=*/ true,
|
MI->addOperand(MachineOperand::CreateReg(Reg, /*isDef=*/ true,
|
||||||
|
|
|
@ -490,7 +490,8 @@ bool ScheduleDAGFast::DelayForLiveRegsBottomUp(SUnit *SU,
|
||||||
|
|
||||||
++i; // Skip the ID value.
|
++i; // Skip the ID value.
|
||||||
if (InlineAsm::isRegDefKind(Flags) ||
|
if (InlineAsm::isRegDefKind(Flags) ||
|
||||||
InlineAsm::isRegDefEarlyClobberKind(Flags)) {
|
InlineAsm::isRegDefEarlyClobberKind(Flags) ||
|
||||||
|
InlineAsm::isClobberKind(Flags)) {
|
||||||
// Check for def of register or earlyclobber register.
|
// Check for def of register or earlyclobber register.
|
||||||
for (; NumVals; --NumVals, ++i) {
|
for (; NumVals; --NumVals, ++i) {
|
||||||
unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
|
unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
|
||||||
|
|
|
@ -1092,7 +1092,8 @@ DelayForLiveRegsBottomUp(SUnit *SU, SmallVector<unsigned, 4> &LRegs) {
|
||||||
|
|
||||||
++i; // Skip the ID value.
|
++i; // Skip the ID value.
|
||||||
if (InlineAsm::isRegDefKind(Flags) ||
|
if (InlineAsm::isRegDefKind(Flags) ||
|
||||||
InlineAsm::isRegDefEarlyClobberKind(Flags)) {
|
InlineAsm::isRegDefEarlyClobberKind(Flags) ||
|
||||||
|
InlineAsm::isClobberKind(Flags)) {
|
||||||
// Check for def of register or earlyclobber register.
|
// Check for def of register or earlyclobber register.
|
||||||
for (; NumVals; --NumVals, ++i) {
|
for (; NumVals; --NumVals, ++i) {
|
||||||
unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
|
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
|
// Add the clobbered value to the operand list, so that the register
|
||||||
// allocator is aware that the physreg got clobbered.
|
// allocator is aware that the physreg got clobbered.
|
||||||
if (!OpInfo.AssignedRegs.Regs.empty())
|
if (!OpInfo.AssignedRegs.Regs.empty())
|
||||||
OpInfo.AssignedRegs.AddInlineAsmOperands(
|
OpInfo.AssignedRegs.AddInlineAsmOperands(InlineAsm::Kind_Clobber,
|
||||||
InlineAsm::Kind_RegDefEarlyClobber,
|
|
||||||
false, 0, DAG,
|
false, 0, DAG,
|
||||||
AsmNodeOperands);
|
AsmNodeOperands);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue