From c3a9f8d31ce93ba384bd2bbdd55c757b06600a15 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 23 Feb 2006 19:21:04 +0000 Subject: [PATCH] Record all of the expanded registers in the DAG and machine instr, fixing several bugs in inline asm expanded operands. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26332 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/AsmPrinter.cpp | 17 +- lib/CodeGen/SelectionDAG/ScheduleDAG.cpp | 31 ++-- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 168 +++++++++++------- 3 files changed, 137 insertions(+), 79 deletions(-) diff --git a/lib/CodeGen/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter.cpp index af5346cb533..9450576a9ad 100644 --- a/lib/CodeGen/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter.cpp @@ -569,19 +569,26 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { exit(1); } - char ExtraCode = 0; // FIXME: - - // Okay, we finally have an operand number. Ask the target to print this + // Okay, we finally have a value number. Ask the target to print this // operand! - if (CurVariant == -1 || CurVariant == AsmPrinterVariant) + if (CurVariant == -1 || CurVariant == AsmPrinterVariant) { + unsigned OpNo = 1; + + // Scan to find the machine operand number for the operand. + for (; Val; --Val) + OpNo += MI->getOperand(OpNo).getImmedValue()+1; + + ++OpNo; // Skip over the ID number. + if (const_cast(this)-> - PrintAsmOperand(MI, Val+1, AsmPrinterVariant, + PrintAsmOperand(MI, OpNo, AsmPrinterVariant, Modifier[0] ? Modifier : 0)) { std::cerr << "Invalid operand found in inline asm: '" << AsmStr << "'\n"; MI->dump(); exit(1); } + } break; } case '{': diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp index ff4ae335f2d..ef92e7a3689 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp @@ -309,23 +309,32 @@ void ScheduleDAG::EmitNode(NodeInfo *NI) { MI->addExternalSymbolOperand(AsmStr, false); // Add all of the operand registers to the instruction. - for (unsigned i = 2; i != NumOps; i += 2) { - unsigned Flags =cast(Node->getOperand(i+1))->getValue(); - switch (Flags) { + for (unsigned i = 2; i != NumOps;) { + unsigned Flags = cast(Node->getOperand(i))->getValue(); + unsigned NumOps = Flags >> 3; + + MI->addZeroExtImm64Operand(NumOps); + ++i; // Skip the ID value. + + switch (Flags & 7) { default: assert(0 && "Bad flags!"); - case 1: { // Use of register. - unsigned Reg = cast(Node->getOperand(i))->getReg(); - MI->addMachineRegOperand(Reg, MachineOperand::Use); + case 1: // Use of register. + for (; NumOps; --NumOps, ++i) { + unsigned Reg = cast(Node->getOperand(i))->getReg(); + MI->addMachineRegOperand(Reg, MachineOperand::Use); + } break; - } - case 2: { // Def of register. - unsigned Reg = cast(Node->getOperand(i))->getReg(); - MI->addMachineRegOperand(Reg, MachineOperand::Def); + case 2: // Def of register. + for (; NumOps; --NumOps, ++i) { + unsigned Reg = cast(Node->getOperand(i))->getReg(); + MI->addMachineRegOperand(Reg, MachineOperand::Def); + } break; - } case 3: { // Immediate. + assert(NumOps == 1 && "Unknown immediate value!"); uint64_t Val = cast(Node->getOperand(i))->getValue(); MI->addZeroExtImm64Operand(Val); + ++i; break; } } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 968fef2c852..4468b56ac71 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -113,6 +113,18 @@ namespace { /// Chain/Flag as the input and updates them for the output Chain/Flag. SDOperand getCopyFromRegs(SelectionDAG &DAG, SDOperand &Chain, SDOperand &Flag); + + /// getCopyToRegs - Emit a series of CopyToReg nodes that copies the + /// specified value into the registers specified by this object. This uses + /// Chain/Flag as the input and updates them for the output Chain/Flag. + void getCopyToRegs(SDOperand Val, SelectionDAG &DAG, + SDOperand &Chain, SDOperand &Flag); + + /// 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); }; } @@ -1195,7 +1207,41 @@ SDOperand RegsForValue::getCopyFromRegs(SelectionDAG &DAG, return DAG.getNode(ISD::FP_ROUND, ValueVT, Val); } +/// getCopyToRegs - Emit a series of CopyToReg nodes that copies the +/// specified value into the registers specified by this object. This uses +/// Chain/Flag as the input and updates them for the output Chain/Flag. +void RegsForValue::getCopyToRegs(SDOperand Val, SelectionDAG &DAG, + SDOperand &Chain, SDOperand &Flag) { + if (Regs.size() == 1) { + // If there is a single register and the types differ, this must be + // a promotion. + if (RegVT != ValueVT) { + if (MVT::isInteger(RegVT)) + Val = DAG.getNode(ISD::ANY_EXTEND, RegVT, Val); + else + Val = DAG.getNode(ISD::FP_EXTEND, RegVT, Val); + } + Chain = DAG.getCopyToReg(Chain, Regs[0], Val, Flag); + Flag = Chain.getValue(1); + } else { + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + SDOperand Part = DAG.getNode(ISD::EXTRACT_ELEMENT, RegVT, Val, + DAG.getConstant(i, MVT::i32)); + Chain = DAG.getCopyToReg(Chain, Regs[i], Part, Flag); + Flag = Chain.getValue(1); + } + } +} +/// 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, + std::vector &Ops) { + Ops.push_back(DAG.getConstant(Code | (Regs.size() << 3), MVT::i32)); + for (unsigned i = 0, e = Regs.size(); i != e; ++i) + Ops.push_back(DAG.getRegister(Regs[i], RegVT)); +} /// isAllocatableRegister - If the specified register is safe to allocate, /// i.e. it isn't a stack pointer or some other special register, return the @@ -1453,96 +1499,92 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) { // Add information to the INLINEASM node to know that this register is // set. - - // FIXME: - // FIXME: Handle multiple regs here. - // FIXME: - unsigned DestReg = Regs.Regs[0]; - AsmNodeOperands.push_back(DAG.getRegister(DestReg, Regs.RegVT)); - AsmNodeOperands.push_back(DAG.getConstant(2, MVT::i32)); // ISDEF + Regs.AddInlineAsmOperands(2 /*REGDEF*/, DAG, AsmNodeOperands); break; } case InlineAsm::isInput: { Value *CallOperand = I.getOperand(OpNum); OpNum++; // Consumes a call operand. - SDOperand ResOp; - unsigned ResOpType; SDOperand InOperandVal = getValue(CallOperand); if (isdigit(ConstraintCode[0])) { // Matching constraint? // If this is required to match an output register we have already set, // just use its register. unsigned OperandNo = atoi(ConstraintCode.c_str()); - unsigned SrcReg; - SrcReg = cast(AsmNodeOperands[OperandNo*2+2])->getReg(); - ResOp = DAG.getRegister(SrcReg, ConstraintVTs[i]); - ResOpType = 1; - Chain = DAG.getCopyToReg(Chain, SrcReg, InOperandVal, Flag); - Flag = Chain.getValue(1); + // Scan until we find the definition we already emitted of this operand. + // When we find it, create a RegsForValue operand. + unsigned CurOp = 2; // The first operand. + for (; OperandNo; --OperandNo) { + // Advance to the next operand. + unsigned NumOps = + cast(AsmNodeOperands[CurOp])->getValue(); + assert((NumOps & 7) == 2 /*REGDEF*/ && + "Skipped past definitions?"); + CurOp += (NumOps>>3)+1; + } + + unsigned NumOps = + cast(AsmNodeOperands[CurOp])->getValue(); + assert((NumOps & 7) == 2 /*REGDEF*/ && + "Skipped past definitions?"); + + // Add NumOps>>3 registers to MatchedRegs. + RegsForValue MatchedRegs; + MatchedRegs.ValueVT = InOperandVal.getValueType(); + MatchedRegs.RegVT = AsmNodeOperands[CurOp+1].getValueType(); + for (unsigned i = 0, e = NumOps>>3; i != e; ++i) { + unsigned Reg=cast(AsmNodeOperands[++CurOp])->getReg(); + MatchedRegs.Regs.push_back(Reg); + } + + // Use the produced MatchedRegs object to + MatchedRegs.getCopyToRegs(InOperandVal, DAG, Chain, Flag); + MatchedRegs.AddInlineAsmOperands(1 /*REGUSE*/, DAG, AsmNodeOperands); } else { TargetLowering::ConstraintType CTy = TargetLowering::C_RegisterClass; if (ConstraintCode.size() == 1) // not a physreg name. CTy = TLI.getConstraintType(ConstraintCode[0]); - switch (CTy) { - default: assert(0 && "Unknown constraint type! FAIL!"); - case TargetLowering::C_RegisterClass: { - // Copy the input into the appropriate registers. - RegsForValue InRegs = - GetRegistersForValue(ConstraintCode, ConstraintVTs[i], - false, true, OutputRegs, InputRegs); - // FIXME: should be match fail. - assert(!InRegs.Regs.empty() && "Couldn't allocate input reg!"); - - if (InRegs.Regs.size() == 1) { - // If there is a single register and the types differ, this must be - // a promotion. - if (InRegs.RegVT != InRegs.ValueVT) { - if (MVT::isInteger(InRegs.RegVT)) - InOperandVal = DAG.getNode(ISD::ANY_EXTEND, InRegs.RegVT, - InOperandVal); - else - InOperandVal = DAG.getNode(ISD::FP_EXTEND, InRegs.RegVT, - InOperandVal); - } - Chain = DAG.getCopyToReg(Chain, InRegs.Regs[0], InOperandVal, Flag); - Flag = Chain.getValue(1); - - ResOp = DAG.getRegister(InRegs.Regs[0], InRegs.RegVT); - } else { - for (unsigned i = 0, e = InRegs.Regs.size(); i != e; ++i) { - SDOperand Part = DAG.getNode(ISD::EXTRACT_ELEMENT, InRegs.RegVT, - InOperandVal, - DAG.getConstant(i, MVT::i32)); - Chain = DAG.getCopyToReg(Chain, InRegs.Regs[i], Part, Flag); - Flag = Chain.getValue(1); - } - ResOp = DAG.getRegister(InRegs.Regs[0], InRegs.RegVT); - } - - ResOpType = 1; - break; - } - case TargetLowering::C_Other: + if (CTy == TargetLowering::C_Other) { if (!TLI.isOperandValidForConstraint(InOperandVal, ConstraintCode[0])) assert(0 && "MATCH FAIL!"); - ResOp = InOperandVal; - ResOpType = 3; + + // Add information to the INLINEASM node to know about this input. + unsigned ResOpType = 3 /*imm*/ | (1 << 3); + AsmNodeOperands.push_back(DAG.getConstant(ResOpType, MVT::i32)); + AsmNodeOperands.push_back(InOperandVal); break; } + + assert(CTy == TargetLowering::C_RegisterClass && "Unknown op type!"); + + // Copy the input into the appropriate registers. + RegsForValue InRegs = + GetRegistersForValue(ConstraintCode, ConstraintVTs[i], + false, true, OutputRegs, InputRegs); + // FIXME: should be match fail. + assert(!InRegs.Regs.empty() && "Couldn't allocate input reg!"); + + InRegs.getCopyToRegs(InOperandVal, DAG, Chain, Flag); + + InRegs.AddInlineAsmOperands(1/*REGUSE*/, DAG, AsmNodeOperands); + break; } - - // Add information to the INLINEASM node to know about this input. - AsmNodeOperands.push_back(ResOp); - AsmNodeOperands.push_back(DAG.getConstant(ResOpType, MVT::i32)); break; } - case InlineAsm::isClobber: - // Nothing to do. + case InlineAsm::isClobber: { + RegsForValue ClobberedRegs = + GetRegistersForValue(ConstraintCode, MVT::Other, false, false, + OutputRegs, InputRegs); + // Add the clobbered value to the operand list, so that the register + // allocator is aware that the physreg got clobbered. + if (!ClobberedRegs.Regs.empty()) + ClobberedRegs.AddInlineAsmOperands(2/*REGDEF*/, DAG, AsmNodeOperands); break; } + } } // Finish up input operands. -- 2.34.1