From 697cbbfb00c318f98d6eb51945f077e2bfe8781e Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Fri, 20 Mar 2009 18:03:34 +0000 Subject: [PATCH] For inline asm output operand that matches an input. Encode the input operand index in the high bits. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@67387 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/InlineAsm.h | 18 ++++++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 2 +- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 3 +- .../SelectionDAG/ScheduleDAGRRList.cpp | 2 +- .../SelectionDAG/ScheduleDAGSDNodesEmit.cpp | 2 +- .../SelectionDAG/SelectionDAGBuild.cpp | 56 +++++++++++-------- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 8 ++- 7 files changed, 62 insertions(+), 29 deletions(-) diff --git a/include/llvm/InlineAsm.h b/include/llvm/InlineAsm.h index 879b2e847f9..6347cae51f4 100644 --- a/include/llvm/InlineAsm.h +++ b/include/llvm/InlineAsm.h @@ -128,6 +128,24 @@ public: static inline bool classof(const Value *V) { return V->getValueID() == Value::InlineAsmVal; } + + /// getNumOperandRegisters - Extract the number of registers field from the + /// inline asm operand flag. + static unsigned getNumOperandRegisters(unsigned Flag) { + return (Flag & 0xffff) >> 3; + } + + /// isOutputOperandTiedToUse - Return true if the flag of the inline asm + /// operand indicates it is an output that's matched to an input operand. + static bool isOutputOperandTiedToUse(unsigned Flag, unsigned &UseIdx) { + if (Flag & 0x80000000) { + UseIdx = Flag >> 16; + return true; + } + return false; + } + + }; } // End llvm namespace diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index b25776abb94..2a64524860e 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1401,7 +1401,7 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { for (; Val; --Val) { if (OpNo >= MI->getNumOperands()) break; unsigned OpFlags = MI->getOperand(OpNo).getImm(); - OpNo += (OpFlags >> 3) + 1; + OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1; } if (OpNo >= MI->getNumOperands()) { diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index fd08ee688df..888eeda2652 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -1974,7 +1974,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { bool HasInFlag = Ops.back().getValueType() == MVT::Flag; for (unsigned i = 2, e = Ops.size()-HasInFlag; i < e; ) { - unsigned NumVals = cast(Ops[i])->getZExtValue() >> 3; + unsigned NumVals = InlineAsm:: + getNumOperandRegisters(cast(Ops[i])->getZExtValue()); for (++i; NumVals; ++i, --NumVals) { SDValue Op = LegalizeOp(Ops[i]); if (Op != Ops[i]) { diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp index b2f6ddf835a..7ae56d78499 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp @@ -632,7 +632,7 @@ bool ScheduleDAGRRList::DelayForLiveRegsBottomUp(SUnit *SU, for (unsigned i = 2; i != NumOps;) { unsigned Flags = cast(Node->getOperand(i))->getZExtValue(); - unsigned NumVals = Flags >> 3; + unsigned NumVals = (Flags & 0xffff) >> 3; ++i; // Skip the ID value. if ((Flags & 7) == 2 || (Flags & 7) == 6) { diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp index 5dfd5c3fb21..4ad36dac79a 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp @@ -561,7 +561,7 @@ void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone, bool IsCloned, for (unsigned i = 2; i != NumOps;) { unsigned Flags = cast(Node->getOperand(i))->getZExtValue(); - unsigned NumVals = Flags >> 3; + unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); MI->addOperand(MachineOperand::CreateImm(Flags)); ++i; // Skip the ID value. diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index 0e8d9bee5ed..cbfdb793ede 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -228,10 +228,11 @@ namespace llvm { SDValue &Chain, SDValue *Flag) const; /// AddInlineAsmOperands - Add this value to the specified inlineasm node - /// operand list. This adds the code marker and includes the number of - /// values added into it. - void AddInlineAsmOperands(unsigned Code, SelectionDAG &DAG, - std::vector &Ops) const; + /// operand list. This adds the code marker, matching input operand index + /// (if applicable), and includes the number of values added into it. + void AddInlineAsmOperands(unsigned Code, + bool HasMatching, unsigned MatchingIdx, + SelectionDAG &DAG, std::vector &Ops) const; }; } @@ -4659,10 +4660,16 @@ void RegsForValue::getCopyToRegs(SDValue Val, SelectionDAG &DAG, DebugLoc dl, /// AddInlineAsmOperands - Add this value to the specified inlineasm node /// operand list. This adds the code marker and includes the number of /// values added into it. -void RegsForValue::AddInlineAsmOperands(unsigned Code, SelectionDAG &DAG, +void RegsForValue::AddInlineAsmOperands(unsigned Code, + bool HasMatching,unsigned MatchingIdx, + SelectionDAG &DAG, std::vector &Ops) const { MVT IntPtrTy = DAG.getTargetLoweringInfo().getPointerTy(); - Ops.push_back(DAG.getTargetConstant(Code | (Regs.size() << 3), IntPtrTy)); + assert(Regs.size() < (1 << 13) && "Too many inline asm outputs!"); + unsigned Flag = Code | (Regs.size() << 3); + if (HasMatching) + Flag |= 0x80000000 | (MatchingIdx << 16); + Ops.push_back(DAG.getTargetConstant(Flag, IntPtrTy)); for (unsigned Value = 0, Reg = 0, e = ValueVTs.size(); Value != e; ++Value) { unsigned NumRegs = TLI->getNumRegisters(ValueVTs[Value]); MVT RegisterVT = RegVTs[Value]; @@ -5230,6 +5237,8 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { OpInfo.AssignedRegs.AddInlineAsmOperands(OpInfo.isEarlyClobber ? 6 /* EARLYCLOBBER REGDEF */ : 2 /* REGDEF */ , + OpInfo.hasMatchingInput(), + OpInfo.MatchingInput, DAG, AsmNodeOperands); break; } @@ -5246,25 +5255,26 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { unsigned CurOp = 2; // The first operand. for (; OperandNo; --OperandNo) { // Advance to the next operand. - unsigned NumOps = + unsigned OpFlag = cast(AsmNodeOperands[CurOp])->getZExtValue(); - assert(((NumOps & 7) == 2 /*REGDEF*/ || - (NumOps & 7) == 6 /*EARLYCLOBBER REGDEF*/ || - (NumOps & 7) == 4 /*MEM*/) && + assert(((OpFlag & 7) == 2 /*REGDEF*/ || + (OpFlag & 7) == 6 /*EARLYCLOBBER REGDEF*/ || + (OpFlag & 7) == 4 /*MEM*/) && "Skipped past definitions?"); - CurOp += (NumOps>>3)+1; + CurOp += InlineAsm::getNumOperandRegisters(OpFlag)+1; } - unsigned NumOps = + unsigned OpFlag = cast(AsmNodeOperands[CurOp])->getZExtValue(); - if ((NumOps & 7) == 2 /*REGDEF*/ - || (NumOps & 7) == 6 /* EARLYCLOBBER REGDEF */) { - // Add NumOps>>3 registers to MatchedRegs. + if ((OpFlag & 7) == 2 /*REGDEF*/ + || (OpFlag & 7) == 6 /* EARLYCLOBBER REGDEF */) { + // Add (OpFlag&0xffff)>>3 registers to MatchedRegs. RegsForValue MatchedRegs; MatchedRegs.TLI = &TLI; MatchedRegs.ValueVTs.push_back(InOperandVal.getValueType()); MatchedRegs.RegVTs.push_back(AsmNodeOperands[CurOp+1].getValueType()); - for (unsigned i = 0, e = NumOps>>3; i != e; ++i) { + for (unsigned i = 0, e = InlineAsm::getNumOperandRegisters(OpFlag); + i != e; ++i) { unsigned Reg = cast(AsmNodeOperands[++CurOp])->getReg(); MatchedRegs.Regs.push_back(Reg); @@ -5273,13 +5283,15 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { // Use the produced MatchedRegs object to MatchedRegs.getCopyToRegs(InOperandVal, DAG, getCurDebugLoc(), Chain, &Flag); - MatchedRegs.AddInlineAsmOperands(1 /*REGUSE*/, DAG, AsmNodeOperands); + MatchedRegs.AddInlineAsmOperands(1 /*REGUSE*/, false, 0, + DAG, AsmNodeOperands); break; } else { - assert(((NumOps & 7) == 4) && "Unknown matching constraint!"); - assert((NumOps >> 3) == 1 && "Unexpected number of operands"); + assert(((OpFlag & 7) == 4) && "Unknown matching constraint!"); + assert((InlineAsm::getNumOperandRegisters(OpFlag)) == 1 && + "Unexpected number of operands"); // Add information to the INLINEASM node to know about this input. - AsmNodeOperands.push_back(DAG.getTargetConstant(NumOps, + AsmNodeOperands.push_back(DAG.getTargetConstant(OpFlag, TLI.getPointerTy())); AsmNodeOperands.push_back(AsmNodeOperands[CurOp+1]); break; @@ -5334,7 +5346,7 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { OpInfo.AssignedRegs.getCopyToRegs(InOperandVal, DAG, getCurDebugLoc(), Chain, &Flag); - OpInfo.AssignedRegs.AddInlineAsmOperands(1/*REGUSE*/, + OpInfo.AssignedRegs.AddInlineAsmOperands(1/*REGUSE*/, false, 0, DAG, AsmNodeOperands); break; } @@ -5343,7 +5355,7 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { // allocator is aware that the physreg got clobbered. if (!OpInfo.AssignedRegs.Regs.empty()) OpInfo.AssignedRegs.AddInlineAsmOperands(6 /* EARLYCLOBBER REGDEF */, - DAG, AsmNodeOperands); + false, 0, DAG,AsmNodeOperands); break; } } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index fd2eb0655b2..fdabd4cb25e 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -1168,10 +1168,12 @@ SelectInlineAsmMemoryOperands(std::vector &Ops) { unsigned Flags = cast(InOps[i])->getZExtValue(); if ((Flags & 7) != 4 /*MEM*/) { // Just skip over this operand, copying the operands verbatim. - Ops.insert(Ops.end(), InOps.begin()+i, InOps.begin()+i+(Flags >> 3) + 1); - i += (Flags >> 3) + 1; + Ops.insert(Ops.end(), InOps.begin()+i, + InOps.begin()+i+InlineAsm::getNumOperandRegisters(Flags) + 1); + i += InlineAsm::getNumOperandRegisters(Flags) + 1; } else { - assert((Flags >> 3) == 1 && "Memory operand with multiple values?"); + assert(InlineAsm::getNumOperandRegisters(Flags) == 1 && + "Memory operand with multiple values?"); // Otherwise, this is a memory operand. Ask the target to select it. std::vector SelOps; if (SelectInlineAsmMemoryOperand(InOps[i+1], 'm', SelOps)) { -- 2.34.1