From 557793fb60a42eb8ba64fcf75d14e463fe1679c3 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Mon, 27 Jun 2011 04:08:33 +0000 Subject: [PATCH] Distinguish early clobber output operands from clobbered registers. Both become 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 flags for that. llvm-svn: 133902 --- include/llvm/InlineAsm.h | 26 +++++++++++++------ lib/CodeGen/MachineInstr.cpp | 3 ++- lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 1 + lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp | 3 ++- .../SelectionDAG/ScheduleDAGRRList.cpp | 3 ++- .../SelectionDAG/SelectionDAGBuilder.cpp | 3 +-- 6 files changed, 26 insertions(+), 13 deletions(-) diff --git a/include/llvm/InlineAsm.h b/include/llvm/InlineAsm.h index 0d8608605d1..ed5bf8b38af 100644 --- a/include/llvm/InlineAsm.h +++ b/include/llvm/InlineAsm.h @@ -188,25 +188,32 @@ 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,7 +240,10 @@ 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. static unsigned getNumOperandRegisters(unsigned Flag) { diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index d4d82024755..938b83dd0e0 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -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; } diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp index 3c6a46ecab8..e8c9c5180c2 100644 --- a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -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(Node->getOperand(i))->getReg(); MI->addOperand(MachineOperand::CreateReg(Reg, /*isDef=*/ true, diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp index 7b560d173ed..6bed1dbc471 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp @@ -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(Node->getOperand(i))->getReg(); diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp index a827187e357..1053b888a0d 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp @@ -1092,7 +1092,8 @@ DelayForLiveRegsBottomUp(SUnit *SU, SmallVector &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(Node->getOperand(i))->getReg(); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 19bfa337c68..30012065c76 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -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;