From b6f5b00c3bad3415d3f2ee1a6d5ee5a6f66a4540 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 28 Jun 2007 23:29:44 +0000 Subject: [PATCH] Add new TargetLowering code to provide the final register type that an illegal value type will be transformed to, for code that needs the register type after all transformations instead of just after the first transformation. Factor out the code that uses this information to do copy-from-regs and copy-to-regs for various purposes into separate functions so that they are done consistently. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@37781 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/SelectionDAGNodes.h | 2 +- include/llvm/Target/TargetLowering.h | 25 +- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 638 ++++++++---------- lib/CodeGen/SelectionDAG/TargetLowering.cpp | 162 ++--- 4 files changed, 372 insertions(+), 455 deletions(-) diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 792859a9b17..d22ffca2ddb 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -253,7 +253,7 @@ namespace ISD { /// CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of /// vector type with the same length and element type, this produces a /// concatenated vector result value, with length equal to the sum of the - /// input vectors. + /// lengths of the input vectors. CONCAT_VECTORS, /// EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR (an diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 1966a435294..a95a03bca0d 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -212,12 +212,13 @@ public: /// Similarly, MVT::v2i64 turns into 4 MVT::i32 values with both PPC and X86. /// /// This method returns the number of registers needed, and the VT for each - /// register. It also returns the VT of the VectorType elements before they - /// are promoted/expanded. + /// register. It also returns the VT and quantity of the intermediate values + /// before they are promoted/expanded. /// unsigned getVectorTypeBreakdown(MVT::ValueType VT, - MVT::ValueType &ElementVT, - MVT::ValueType &LegalElementVT) const; + MVT::ValueType &IntermediateVT, + unsigned &NumIntermediates, + MVT::ValueType &RegisterVT) const; typedef std::vector::const_iterator legal_fpimm_iterator; legal_fpimm_iterator legal_fpimm_begin() const { @@ -360,6 +361,18 @@ public: return VT == MVT::iPTR ? PointerTy : VT; } + /// getRegisterType - Return the type of registers that this ValueType will + /// eventually require. + MVT::ValueType getRegisterType(MVT::ValueType VT) const { + if (!MVT::isExtendedVT(VT)) + return RegisterTypeForVT[VT]; + + MVT::ValueType VT1, RegisterVT; + unsigned NumIntermediates; + (void)getVectorTypeBreakdown(VT, VT1, NumIntermediates, RegisterVT); + return RegisterVT; + } + /// getNumRegisters - Return the number of registers that this ValueType will /// eventually require. This is one for any types promoted to live in larger /// registers, but may be more than one for types (like i64) that are split @@ -369,7 +382,8 @@ public: return NumRegistersForVT[VT]; MVT::ValueType VT1, VT2; - return getVectorTypeBreakdown(VT, VT1, VT2); + unsigned NumIntermediates; + return getVectorTypeBreakdown(VT, VT1, NumIntermediates, VT2); } /// hasTargetDAGCombine - If true, the target has custom DAG combine @@ -1034,6 +1048,7 @@ private: /// each ValueType the target supports natively. TargetRegisterClass *RegClassForVT[MVT::LAST_VALUETYPE]; unsigned char NumRegistersForVT[MVT::LAST_VALUETYPE]; + MVT::ValueType RegisterTypeForVT[MVT::LAST_VALUETYPE]; /// TransformToType - For any value types we are promoting or expanding, this /// contains the value type that we are changing to. For Expanded types, this diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index d7369d3070e..224006106b2 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -90,7 +90,7 @@ namespace { /// This is needed because values can be promoted into larger registers and /// expanded into multiple smaller registers than the value. struct VISIBILITY_HIDDEN RegsForValue { - /// Regs - This list hold the register (for legal and promoted values) + /// Regs - This list holds the register (for legal and promoted values) /// or register set (for expanded values) that the value should be assigned /// to. std::vector Regs; @@ -117,15 +117,16 @@ namespace { /// getCopyFromRegs - Emit a series of CopyFromReg nodes that copies from /// this value and returns the result as a ValueVT value. This uses /// Chain/Flag as the input and updates them for the output Chain/Flag. + /// If the Flag pointer is NULL, no flag is used. SDOperand getCopyFromRegs(SelectionDAG &DAG, - SDOperand &Chain, SDOperand &Flag) const; + SDOperand &Chain, SDOperand *Flag) const; /// 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. + /// If the Flag pointer is NULL, no flag is used. void getCopyToRegs(SDOperand Val, SelectionDAG &DAG, - SDOperand &Chain, SDOperand &Flag, - MVT::ValueType PtrVT) const; + SDOperand &Chain, SDOperand *Flag) const; /// AddInlineAsmOperands - Add this value to the specified inlineasm node /// operand list. This adds the code marker and includes the number of @@ -306,15 +307,8 @@ FunctionLoweringInfo::FunctionLoweringInfo(TargetLowering &tli, unsigned FunctionLoweringInfo::CreateRegForValue(const Value *V) { MVT::ValueType VT = TLI.getValueType(V->getType()); - unsigned NumRegisters; - MVT::ValueType RegisterVT; - if (MVT::isVector(VT)) { - MVT::ValueType ElementVT; - NumRegisters = TLI.getVectorTypeBreakdown(VT, ElementVT, RegisterVT); - } else { - RegisterVT = TLI.getTypeToTransformTo(VT); - NumRegisters = TLI.getNumRegisters(VT); - } + unsigned NumRegisters = TLI.getNumRegisters(VT); + MVT::ValueType RegisterVT = TLI.getRegisterType(VT); unsigned R = MakeReg(RegisterVT); for (unsigned i = 1; i != NumRegisters; ++i) @@ -695,79 +689,17 @@ SDOperand SelectionDAGLowering::getValue(const Value *V) { unsigned InReg = FuncInfo.ValueMap[V]; assert(InReg && "Value not in map!"); - // If this type is not legal, make it so now. - if (!MVT::isVector(VT)) { - if (TLI.getTypeAction(VT) == TargetLowering::Expand) { - // Source must be expanded. This input value is actually coming from the - // register pair InReg and InReg+1. - MVT::ValueType DestVT = TLI.getTypeToExpandTo(VT); - unsigned NumVals = TLI.getNumRegisters(VT); - N = DAG.getCopyFromReg(DAG.getEntryNode(), InReg, DestVT); - if (NumVals == 1) - N = DAG.getNode(ISD::BIT_CONVERT, VT, N); - else { - assert(NumVals == 2 && "1 to 4 (and more) expansion not implemented!"); - N = DAG.getNode(ISD::BUILD_PAIR, VT, N, - DAG.getCopyFromReg(DAG.getEntryNode(), InReg+1, DestVT)); - } - } else { - MVT::ValueType DestVT = TLI.getTypeToTransformTo(VT); - N = DAG.getCopyFromReg(DAG.getEntryNode(), InReg, DestVT); - if (TLI.getTypeAction(VT) == TargetLowering::Promote) // Promotion case - N = MVT::isFloatingPoint(VT) - ? DAG.getNode(ISD::FP_ROUND, VT, N) - : DAG.getNode(ISD::TRUNCATE, VT, N); - } - } else { - // Otherwise, if this is a vector, make it available as a vector - // here. - MVT::ValueType ElementVT, LegalElementVT; - unsigned NE = TLI.getVectorTypeBreakdown(VT, ElementVT, - LegalElementVT); - - // Build a BUILD_VECTOR or CONCAT_VECTORS with the input registers. - SmallVector Ops; - if (ElementVT == LegalElementVT) { - // If the value types are legal, just BUILD the CopyFromReg nodes. - for (unsigned i = 0; i != NE; ++i) - Ops.push_back(DAG.getCopyFromReg(DAG.getEntryNode(), InReg++, - ElementVT)); - } else if (ElementVT < LegalElementVT) { - // If the register was promoted, use TRUNCATE or FP_ROUND as appropriate. - for (unsigned i = 0; i != NE; ++i) { - SDOperand Op = DAG.getCopyFromReg(DAG.getEntryNode(), InReg++, - LegalElementVT); - if (MVT::isFloatingPoint(ElementVT)) - Op = DAG.getNode(ISD::FP_ROUND, ElementVT, Op); - else - Op = DAG.getNode(ISD::TRUNCATE, ElementVT, Op); - Ops.push_back(Op); - } - } else { - // If the register was expanded, use BUILD_PAIR. - assert((NE & 1) == 0 && "Must expand into a multiple of 2 elements!"); - for (unsigned i = 0; i != NE; ++i) { - SDOperand Op0 = DAG.getCopyFromReg(DAG.getEntryNode(), InReg++, - LegalElementVT); - SDOperand Op1 = DAG.getCopyFromReg(DAG.getEntryNode(), InReg++, - LegalElementVT); - Ops.push_back(DAG.getNode(ISD::BUILD_PAIR, ElementVT, Op0, Op1)); - } - } - - if (MVT::isVector(ElementVT)) { - N = DAG.getNode(ISD::CONCAT_VECTORS, - MVT::getVectorType(MVT::getVectorElementType(ElementVT), - NE * MVT::getVectorNumElements(ElementVT)), - &Ops[0], Ops.size()); - } else { - N = DAG.getNode(ISD::BUILD_VECTOR, - MVT::getVectorType(ElementVT, NE), - &Ops[0], Ops.size()); - } - } - - return N; + MVT::ValueType RegisterVT = TLI.getRegisterType(VT); + unsigned NumRegs = TLI.getNumRegisters(VT); + + std::vector Regs(NumRegs); + for (unsigned i = 0; i != NumRegs; ++i) + Regs[i] = InReg + i; + + RegsForValue RFV(Regs, RegisterVT, VT); + SDOperand Chain = DAG.getEntryNode(); + + return RFV.getCopyFromRegs(DAG, Chain, NULL); } @@ -2819,88 +2751,239 @@ void SelectionDAGLowering::visitCall(CallInst &I) { } -SDOperand RegsForValue::getCopyFromRegs(SelectionDAG &DAG, - SDOperand &Chain, SDOperand &Flag)const{ - SDOperand Val = DAG.getCopyFromReg(Chain, Regs[0], RegVT, Flag); - Chain = Val.getValue(1); - Flag = Val.getValue(2); - - // If the result was expanded, copy from the top part. - if (Regs.size() > 1) { - assert(Regs.size() == 2 && - "Cannot expand to more than 2 elts yet!"); - SDOperand Hi = DAG.getCopyFromReg(Chain, Regs[1], RegVT, Flag); - Chain = Hi.getValue(1); - Flag = Hi.getValue(2); - if (DAG.getTargetLoweringInfo().isLittleEndian()) +/// getCopyFromParts - Create a value that contains the +/// specified legal parts combined into the value they represent. +static SDOperand getCopyFromParts(SelectionDAG &DAG, + const SDOperand *Parts, + unsigned NumParts, + MVT::ValueType PartVT, + MVT::ValueType ValueVT, + ISD::NodeType AssertOp = ISD::DELETED_NODE) { + if (!MVT::isVector(ValueVT) || NumParts == 1) { + SDOperand Val = Parts[0]; + + // If the value was expanded, copy from the top part. + if (NumParts > 1) { + assert(NumParts == 2 && + "Cannot expand to more than 2 elts yet!"); + SDOperand Hi = Parts[1]; return DAG.getNode(ISD::BUILD_PAIR, ValueVT, Val, Hi); - else - return DAG.getNode(ISD::BUILD_PAIR, ValueVT, Hi, Val); - } + } - // Otherwise, if the return value was promoted or extended, truncate it to the - // appropriate type. - if (RegVT == ValueVT) - return Val; + // Otherwise, if the value was promoted or extended, truncate it to the + // appropriate type. + if (PartVT == ValueVT) + return Val; - if (MVT::isVector(RegVT)) { - assert(MVT::isVector(ValueVT) && "Unknown vector conversion!"); - return DAG.getNode(ISD::BIT_CONVERT, RegVT, Val); - } + if (MVT::isVector(PartVT)) { + assert(MVT::isVector(ValueVT) && "Unknown vector conversion!"); + return DAG.getNode(ISD::BIT_CONVERT, PartVT, Val); + } - if (MVT::isInteger(RegVT)) { - if (ValueVT < RegVT) - return DAG.getNode(ISD::TRUNCATE, ValueVT, Val); - else - return DAG.getNode(ISD::ANY_EXTEND, ValueVT, Val); + if (MVT::isInteger(PartVT) && + MVT::isInteger(ValueVT)) { + if (ValueVT < PartVT) { + // For a truncate, see if we have any information to + // indicate whether the truncated bits will always be + // zero or sign-extension. + if (AssertOp != ISD::DELETED_NODE) + Val = DAG.getNode(AssertOp, PartVT, Val, + DAG.getValueType(ValueVT)); + return DAG.getNode(ISD::TRUNCATE, ValueVT, Val); + } else { + return DAG.getNode(ISD::ANY_EXTEND, ValueVT, Val); + } + } + + if (MVT::isFloatingPoint(PartVT) && + MVT::isFloatingPoint(ValueVT)) + return DAG.getNode(ISD::FP_ROUND, ValueVT, Val); + + if (MVT::getSizeInBits(PartVT) == + MVT::getSizeInBits(ValueVT)) + return DAG.getNode(ISD::BIT_CONVERT, ValueVT, Val); + + assert(0 && "Unknown mismatch!"); + } + + // Handle a multi-element vector. + MVT::ValueType IntermediateVT, RegisterVT; + unsigned NumIntermediates; + unsigned NumRegs = + DAG.getTargetLoweringInfo() + .getVectorTypeBreakdown(ValueVT, IntermediateVT, NumIntermediates, + RegisterVT); + + assert(NumRegs == NumParts && "Part count doesn't match vector breakdown!"); + assert(RegisterVT == PartVT && "Part type doesn't match vector breakdown!"); + assert(RegisterVT == Parts[0].getValueType() && + "Part type doesn't match part!"); + + // Assemble the parts into intermediate operands. + SmallVector Ops(NumIntermediates); + if (NumIntermediates == NumParts) { + // If the register was not expanded, truncate or copy the value, + // as appropriate. + for (unsigned i = 0; i != NumParts; ++i) + Ops[i] = getCopyFromParts(DAG, &Parts[i], 1, PartVT, IntermediateVT); + } else if (NumParts > 0) { + // If the intermediate type was expanded, build the intermediate operands + // from the parts. + assert(NumIntermediates % NumParts == 0 && + "Must expand into a divisible number of parts!"); + unsigned Factor = NumIntermediates / NumParts; + for (unsigned i = 0; i != NumIntermediates; ++i) + Ops[i] = getCopyFromParts(DAG, &Parts[i * Factor], Factor, + PartVT, IntermediateVT); } - assert(MVT::isFloatingPoint(RegVT) && MVT::isFloatingPoint(ValueVT)); - return DAG.getNode(ISD::FP_ROUND, ValueVT, Val); + // Build a vector with BUILD_VECTOR or CONCAT_VECTORS from the intermediate + // operands. + return DAG.getNode(MVT::isVector(IntermediateVT) ? + ISD::CONCAT_VECTORS : + ISD::BUILD_VECTOR, + ValueVT, &Ops[0], NumParts); } -/// 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, - MVT::ValueType PtrVT) const { - if (Regs.size() == 1) { - // If there is a single register and the types differ, this must be +/// getCopyToParts - Create a series of nodes that contain the +/// specified value split into legal parts. +static void getCopyToParts(SelectionDAG &DAG, + SDOperand Val, + SDOperand *Parts, + unsigned NumParts, + MVT::ValueType PartVT) { + MVT::ValueType ValueVT = Val.getValueType(); + + if (!MVT::isVector(ValueVT) || NumParts == 1) { + // If the value was expanded, copy from the parts. + if (NumParts > 1) { + for (unsigned i = 0; i < NumParts; ++i) + Parts[i] = DAG.getNode(ISD::EXTRACT_ELEMENT, PartVT, Val, + DAG.getConstant(i, MVT::i32)); + return; + } + + // If there is a single part and the types differ, this must be // a promotion. - if (RegVT != ValueVT) { - if (MVT::isVector(RegVT)) { - assert(MVT::isVector(Val.getValueType()) && + if (PartVT != ValueVT) { + if (MVT::isVector(PartVT)) { + assert(MVT::isVector(ValueVT) && "Not a vector-vector cast?"); - Val = DAG.getNode(ISD::BIT_CONVERT, RegVT, Val); - } else if (MVT::isInteger(RegVT) && MVT::isInteger(Val.getValueType())) { - if (RegVT < ValueVT) - Val = DAG.getNode(ISD::TRUNCATE, RegVT, Val); + Val = DAG.getNode(ISD::BIT_CONVERT, PartVT, Val); + } else if (MVT::isInteger(PartVT) && MVT::isInteger(ValueVT)) { + if (PartVT < ValueVT) + Val = DAG.getNode(ISD::TRUNCATE, PartVT, Val); else - Val = DAG.getNode(ISD::ANY_EXTEND, RegVT, Val); - } else if (MVT::isFloatingPoint(RegVT) && - MVT::isFloatingPoint(Val.getValueType())) { - Val = DAG.getNode(ISD::FP_EXTEND, RegVT, Val); - } else if (MVT::getSizeInBits(RegVT) == - MVT::getSizeInBits(Val.getValueType())) { - Val = DAG.getNode(ISD::BIT_CONVERT, RegVT, Val); + Val = DAG.getNode(ISD::ANY_EXTEND, PartVT, Val); + } else if (MVT::isFloatingPoint(PartVT) && + MVT::isFloatingPoint(ValueVT)) { + Val = DAG.getNode(ISD::FP_EXTEND, PartVT, Val); + } else if (MVT::getSizeInBits(PartVT) == + MVT::getSizeInBits(ValueVT)) { + Val = DAG.getNode(ISD::BIT_CONVERT, PartVT, Val); } else { assert(0 && "Unknown mismatch!"); } } - Chain = DAG.getCopyToReg(Chain, Regs[0], Val, Flag); - Flag = Chain.getValue(1); - } else { - std::vector R(Regs); - if (!DAG.getTargetLoweringInfo().isLittleEndian()) - std::reverse(R.begin(), R.end()); - - for (unsigned i = 0, e = R.size(); i != e; ++i) { - SDOperand Part = DAG.getNode(ISD::EXTRACT_ELEMENT, RegVT, Val, - DAG.getConstant(i, PtrVT)); - Chain = DAG.getCopyToReg(Chain, R[i], Part, Flag); - Flag = Chain.getValue(1); - } + Parts[0] = Val; + return; + } + + // Handle a multi-element vector. + MVT::ValueType IntermediateVT, RegisterVT; + unsigned NumIntermediates; + unsigned NumRegs = + DAG.getTargetLoweringInfo() + .getVectorTypeBreakdown(ValueVT, IntermediateVT, NumIntermediates, + RegisterVT); + unsigned NumElements = MVT::getVectorNumElements(ValueVT); + + assert(NumRegs == NumParts && "Part count doesn't match vector breakdown!"); + assert(RegisterVT == PartVT && "Part type doesn't match vector breakdown!"); + + // Split the vector into intermediate operands. + SmallVector Ops(NumIntermediates); + for (unsigned i = 0; i != NumIntermediates; ++i) + if (MVT::isVector(IntermediateVT)) + Ops[i] = DAG.getNode(ISD::EXTRACT_SUBVECTOR, + IntermediateVT, Val, + DAG.getConstant(i * (NumElements / NumIntermediates), + MVT::i32)); + else + Ops[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, + IntermediateVT, Val, + DAG.getConstant(i, MVT::i32)); + + // Split the intermediate operands into legal parts. + if (NumParts == NumIntermediates) { + // If the register was not expanded, promote or copy the value, + // as appropriate. + for (unsigned i = 0; i != NumParts; ++i) + getCopyToParts(DAG, Ops[i], &Parts[i], 1, PartVT); + } else if (NumParts > 0) { + // If the intermediate type was expanded, split each the value into + // legal parts. + assert(NumParts % NumIntermediates == 0 && + "Must expand into a divisible number of parts!"); + unsigned Factor = NumParts / NumIntermediates; + for (unsigned i = 0; i != NumIntermediates; ++i) + getCopyToParts(DAG, Ops[i], &Parts[i * Factor], Factor, PartVT); + } +} + + +/// getCopyFromRegs - Emit a series of CopyFromReg nodes that copies from +/// this value and returns the result as a ValueVT value. This uses +/// Chain/Flag as the input and updates them for the output Chain/Flag. +/// If the Flag pointer is NULL, no flag is used. +SDOperand RegsForValue::getCopyFromRegs(SelectionDAG &DAG, + SDOperand &Chain, SDOperand *Flag)const{ + // Get the list of registers, in the appropriate order. + std::vector R(Regs); + if (!DAG.getTargetLoweringInfo().isLittleEndian()) + std::reverse(R.begin(), R.end()); + + // Copy the legal parts from the registers. + unsigned NumParts = Regs.size(); + SmallVector Parts(NumParts); + for (unsigned i = 0; i < NumParts; ++i) { + SDOperand Part = Flag ? + DAG.getCopyFromReg(Chain, Regs[i], RegVT, *Flag) : + DAG.getCopyFromReg(Chain, Regs[i], RegVT); + Chain = Part.getValue(1); + if (Flag) + *Flag = Part.getValue(2); + Parts[i] = Part; + } + + // Assemble the legal parts into the final value. + return getCopyFromParts(DAG, &Parts[0], NumParts, RegVT, ValueVT); +} + +/// 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. +/// If the Flag pointer is NULL, no flag is used. +void RegsForValue::getCopyToRegs(SDOperand Val, SelectionDAG &DAG, + SDOperand &Chain, SDOperand *Flag) const { + // Get the list of registers, in the appropriate order. + std::vector R(Regs); + if (!DAG.getTargetLoweringInfo().isLittleEndian()) + std::reverse(R.begin(), R.end()); + + // Get the list of the values's legal parts. + unsigned NumParts = Regs.size(); + SmallVector Parts(NumParts); + getCopyToParts(DAG, Val, &Parts[0], NumParts, RegVT); + + // Copy the parts into the registers. + for (unsigned i = 0; i < NumParts; ++i) { + SDOperand Part = Flag ? + DAG.getCopyToReg(Chain, R[i], Parts[i], *Flag) : + DAG.getCopyToReg(Chain, R[i], Parts[i]); + Chain = Part.getValue(0); + if (Flag) + *Flag = Part.getValue(1); } } @@ -3456,8 +3539,7 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) { } // Use the produced MatchedRegs object to - MatchedRegs.getCopyToRegs(InOperandVal, DAG, Chain, Flag, - TLI.getPointerTy()); + MatchedRegs.getCopyToRegs(InOperandVal, DAG, Chain, &Flag); MatchedRegs.AddInlineAsmOperands(1 /*REGUSE*/, DAG, AsmNodeOperands); break; } else { @@ -3508,8 +3590,7 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) { assert(!OpInfo.AssignedRegs.Regs.empty() && "Couldn't allocate input reg!"); - OpInfo.AssignedRegs.getCopyToRegs(InOperandVal, DAG, Chain, Flag, - TLI.getPointerTy()); + OpInfo.AssignedRegs.getCopyToRegs(InOperandVal, DAG, Chain, &Flag); OpInfo.AssignedRegs.AddInlineAsmOperands(1/*REGUSE*/, DAG, AsmNodeOperands); @@ -3538,7 +3619,7 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) { // If this asm returns a register value, copy the result from that register // and set it as the value of the call. if (!RetValRegs.Regs.empty()) { - SDOperand Val = RetValRegs.getCopyFromRegs(DAG, Chain, Flag); + SDOperand Val = RetValRegs.getCopyFromRegs(DAG, Chain, &Flag); // If the result of the inline asm is a vector, it may have the wrong // width/num elts. Make sure to convert it to the right type with @@ -3560,7 +3641,7 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) { for (unsigned i = 0, e = IndirectStoresToEmit.size(); i != e; ++i) { RegsForValue &OutRegs = IndirectStoresToEmit[i].first; Value *Ptr = IndirectStoresToEmit[i].second; - SDOperand OutVal = OutRegs.getCopyFromRegs(DAG, Chain, Flag); + SDOperand OutVal = OutRegs.getCopyFromRegs(DAG, Chain, &Flag); StoresToEmit.push_back(std::make_pair(OutVal, Ptr)); } @@ -3733,40 +3814,22 @@ TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { RetVals.push_back(getTypeToTransformTo(VT)); Ops.push_back(DAG.getConstant(Flags, MVT::i32)); break; - case Expand: - if (!MVT::isVector(VT)) { - // If this is a large integer, it needs to be broken up into small - // integers. Figure out what the destination type is and how many small - // integers it turns into. - MVT::ValueType NVT = getTypeToExpandTo(VT); - unsigned NumVals = getNumRegisters(VT); - for (unsigned i = 0; i != NumVals; ++i) { - RetVals.push_back(NVT); - // if it isn't first piece, alignment must be 1 - if (i > 0) - Flags = (Flags & (~ISD::ParamFlags::OrigAlignment)) | - (1 << ISD::ParamFlags::OrigAlignmentOffs); - Ops.push_back(DAG.getConstant(Flags, MVT::i32)); - } - } else { - // Otherwise, this is a vector type. We only support legal vectors - // right now. - unsigned NumElems = cast(I->getType())->getNumElements(); - const Type *EltTy = cast(I->getType())->getElementType(); - - // Figure out if there is a Packed type corresponding to this Vector - // type. If so, convert to the vector type. - MVT::ValueType TVT = - MVT::getVectorType(getValueType(EltTy), NumElems); - if (TVT != MVT::Other && isTypeLegal(TVT)) { - RetVals.push_back(TVT); - Ops.push_back(DAG.getConstant(Flags, MVT::i32)); - } else { - assert(0 && "Don't support illegal by-val vector arguments yet!"); - } + case Expand: { + // If this is an illegal type, it needs to be broken up to fit into + // registers. + MVT::ValueType RegisterVT = getRegisterType(VT); + unsigned NumRegs = getNumRegisters(VT); + for (unsigned i = 0; i != NumRegs; ++i) { + RetVals.push_back(RegisterVT); + // if it isn't first piece, alignment must be 1 + if (i > 0) + Flags = (Flags & (~ISD::ParamFlags::OrigAlignment)) | + (1 << ISD::ParamFlags::OrigAlignmentOffs); + Ops.push_back(DAG.getConstant(Flags, MVT::i32)); } break; } + } } RetVals.push_back(MVT::Other); @@ -3979,108 +4042,33 @@ TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, } // Figure out the result value types. - SmallVector RetTys; - - if (RetTy != Type::VoidTy) { - MVT::ValueType VT = getValueType(RetTy); - switch (getTypeAction(VT)) { - default: assert(0 && "Unknown type action!"); - case Legal: - RetTys.push_back(VT); - break; - case Promote: - RetTys.push_back(getTypeToTransformTo(VT)); - break; - case Expand: - if (!MVT::isVector(VT)) { - // If this is a large integer, it needs to be reassembled from small - // integers. Figure out what the source elt type is and how many small - // integers it is. - MVT::ValueType NVT = getTypeToExpandTo(VT); - unsigned NumVals = getNumRegisters(VT); - for (unsigned i = 0; i != NumVals; ++i) - RetTys.push_back(NVT); - } else { - // Otherwise, this is a vector type. We only support legal vectors - // right now. - const VectorType *PTy = cast(RetTy); - unsigned NumElems = PTy->getNumElements(); - const Type *EltTy = PTy->getElementType(); - - // Figure out if there is a Packed type corresponding to this Vector - // type. If so, convert to the vector type. - MVT::ValueType TVT = - MVT::getVectorType(getValueType(EltTy), NumElems); - if (TVT != MVT::Other && isTypeLegal(TVT)) { - RetTys.push_back(TVT); - } else { - assert(0 && "Don't support illegal by-val vector call results yet!"); - abort(); - } - } - } - } + MVT::ValueType VT = getValueType(RetTy); + MVT::ValueType RegisterVT = getRegisterType(VT); + unsigned NumRegs = getNumRegisters(VT); + SmallVector RetTys(NumRegs); + for (unsigned i = 0; i != NumRegs; ++i) + RetTys[i] = RegisterVT; RetTys.push_back(MVT::Other); // Always has a chain. - // Finally, create the CALL node. + // Create the CALL node. SDOperand Res = DAG.getNode(ISD::CALL, - DAG.getVTList(&RetTys[0], RetTys.size()), + DAG.getVTList(&RetTys[0], NumRegs + 1), &Ops[0], Ops.size()); - - // This returns a pair of operands. The first element is the - // return value for the function (if RetTy is not VoidTy). The second - // element is the outgoing token chain. - SDOperand ResVal; - if (RetTys.size() != 1) { - MVT::ValueType VT = getValueType(RetTy); - if (RetTys.size() == 2) { - ResVal = Res; - - // If this value was promoted, truncate it down. - if (ResVal.getValueType() != VT) { - if (MVT::isVector(VT)) { - // Insert a BIT_CONVERT to convert from the packed result type to the - // new vector type. - unsigned NumElems = cast(RetTy)->getNumElements(); - const Type *EltTy = cast(RetTy)->getElementType(); - - // Figure out if there is a Packed type corresponding to this Vector - // type. If so, convert to the vector type. - MVT::ValueType TVT = - MVT::getVectorType(getValueType(EltTy),NumElems); - if (TVT != MVT::Other && isTypeLegal(TVT)) { - // Insert a BIT_CONVERT of the FORMAL_ARGUMENTS to a - // "N x PTyElementVT" vector type. - ResVal = DAG.getNode(ISD::BIT_CONVERT, TVT, ResVal); - } else { - abort(); - } - } else if (MVT::isInteger(VT)) { - unsigned AssertOp = ISD::AssertSext; - if (!RetTyIsSigned) - AssertOp = ISD::AssertZext; - ResVal = DAG.getNode(AssertOp, ResVal.getValueType(), ResVal, - DAG.getValueType(VT)); - ResVal = DAG.getNode(ISD::TRUNCATE, VT, ResVal); - } else { - assert(MVT::isFloatingPoint(VT)); - if (getTypeAction(VT) == Expand) - ResVal = DAG.getNode(ISD::BIT_CONVERT, VT, ResVal); - else - ResVal = DAG.getNode(ISD::FP_ROUND, VT, ResVal); - } - } - } else if (RetTys.size() == 3) { - ResVal = DAG.getNode(ISD::BUILD_PAIR, VT, - Res.getValue(0), Res.getValue(1)); - - } else { - assert(0 && "Case not handled yet!"); - } + SDOperand Chain = Res.getValue(NumRegs); + + // Gather up the call result into a single value. + if (RetTy != Type::VoidTy) { + ISD::NodeType AssertOp = ISD::AssertSext; + if (!RetTyIsSigned) + AssertOp = ISD::AssertZext; + SmallVector Results(NumRegs); + for (unsigned i = 0; i != NumRegs; ++i) + Results[i] = Res.getValue(i); + Res = getCopyFromParts(DAG, &Results[0], NumRegs, RegisterVT, VT, AssertOp); } - - return std::make_pair(ResVal, Res.getValue(Res.Val->getNumValues()-1)); + + return std::make_pair(Res, Chain); } SDOperand TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { @@ -4360,75 +4348,17 @@ SDOperand SelectionDAGLowering::CopyValueToVirtualRegister(Value *V, cast(Op.getOperand(1))->getReg() != Reg) && "Copy from a reg to the same reg!"); - // If this type is not legal, we must make sure to not create an invalid - // register use. MVT::ValueType SrcVT = Op.getValueType(); - MVT::ValueType DestVT = TLI.getTypeToTransformTo(SrcVT); - if (SrcVT == DestVT) { - return DAG.getCopyToReg(getRoot(), Reg, Op); - } else if (MVT::isVector(SrcVT)) { - // Handle copies from generic vectors to registers. - MVT::ValueType ElementVT, LegalElementVT; - unsigned NE = TLI.getVectorTypeBreakdown(SrcVT, - ElementVT, LegalElementVT); - uint64_t SrcVL = MVT::getVectorNumElements(SrcVT); - - // Loop over all of the elements of the resultant vector, - // EXTRACT_VECTOR_ELT'ing or EXTRACT_SUBVECTOR'ing them, converting them - // to LegalElementVT, then copying them into output registers. - SmallVector OutChains; - SDOperand Root = getRoot(); - for (unsigned i = 0; i != NE; ++i) { - SDOperand Elt = MVT::isVector(ElementVT) ? - DAG.getNode(ISD::EXTRACT_SUBVECTOR, ElementVT, - Op, DAG.getConstant(i * (SrcVL / NE), TLI.getPointerTy())) : - DAG.getNode(ISD::EXTRACT_VECTOR_ELT, ElementVT, - Op, DAG.getConstant(i, TLI.getPointerTy())); - if (ElementVT == LegalElementVT) { - // Elements are legal. - OutChains.push_back(DAG.getCopyToReg(Root, Reg++, Elt)); - } else if (LegalElementVT > ElementVT) { - // Elements are promoted. - if (MVT::isFloatingPoint(LegalElementVT)) - Elt = DAG.getNode(ISD::FP_EXTEND, LegalElementVT, Elt); - else - Elt = DAG.getNode(ISD::ANY_EXTEND, LegalElementVT, Elt); - OutChains.push_back(DAG.getCopyToReg(Root, Reg++, Elt)); - } else { - // Elements are expanded. - // The src value is expanded into multiple registers. - SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, LegalElementVT, - Elt, DAG.getConstant(0, TLI.getPointerTy())); - SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, LegalElementVT, - Elt, DAG.getConstant(1, TLI.getPointerTy())); - OutChains.push_back(DAG.getCopyToReg(Root, Reg++, Lo)); - OutChains.push_back(DAG.getCopyToReg(Root, Reg++, Hi)); - } - } - return DAG.getNode(ISD::TokenFactor, MVT::Other, - &OutChains[0], OutChains.size()); - } else if (TLI.getTypeAction(SrcVT) == TargetLowering::Promote) { - // The src value is promoted to the register. - if (MVT::isFloatingPoint(SrcVT)) - Op = DAG.getNode(ISD::FP_EXTEND, DestVT, Op); - else - Op = DAG.getNode(ISD::ANY_EXTEND, DestVT, Op); - return DAG.getCopyToReg(getRoot(), Reg, Op); - } else { - DestVT = TLI.getTypeToExpandTo(SrcVT); - unsigned NumVals = TLI.getNumRegisters(SrcVT); - if (NumVals == 1) - return DAG.getCopyToReg(getRoot(), Reg, - DAG.getNode(ISD::BIT_CONVERT, DestVT, Op)); - assert(NumVals == 2 && "1 to 4 (and more) expansion not implemented!"); - // The src value is expanded into multiple registers. - SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DestVT, - Op, DAG.getConstant(0, TLI.getPointerTy())); - SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DestVT, - Op, DAG.getConstant(1, TLI.getPointerTy())); - Op = DAG.getCopyToReg(getRoot(), Reg, Lo); - return DAG.getCopyToReg(Op, Reg+1, Hi); - } + MVT::ValueType RegisterVT = TLI.getRegisterType(SrcVT); + unsigned NumRegs = TLI.getNumRegisters(SrcVT); + SmallVector Regs(NumRegs); + SmallVector Chains(NumRegs); + + // Copy the value by legal parts into sequential virtual registers. + getCopyToParts(DAG, Op, &Regs[0], NumRegs, RegisterVT); + for (unsigned i = 0; i < NumRegs; ++i) + Chains[i] = DAG.getCopyToReg(getRoot(), Reg + i, Regs[i]); + return DAG.getNode(ISD::TokenFactor, MVT::Other, &Chains[0], NumRegs); } void SelectionDAGISel:: diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 7ab552839c1..44faf24b064 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -165,58 +165,19 @@ TargetLowering::TargetLowering(TargetMachine &tm) TargetLowering::~TargetLowering() {} -/// setValueTypeAction - Set the action for a particular value type. This -/// assumes an action has not already been set for this value type. -static void SetValueTypeAction(MVT::ValueType VT, - TargetLowering::LegalizeAction Action, - TargetLowering &TLI, - MVT::ValueType *TransformToType, - TargetLowering::ValueTypeActionImpl &ValueTypeActions) { - ValueTypeActions.setTypeAction(VT, Action); - if (Action == TargetLowering::Promote) { - MVT::ValueType PromoteTo; - if (VT == MVT::f32) - PromoteTo = MVT::f64; - else { - unsigned LargerReg = VT+1; - while (!TLI.isTypeLegal((MVT::ValueType)LargerReg)) { - ++LargerReg; - assert(MVT::isInteger((MVT::ValueType)LargerReg) && - "Nothing to promote to??"); - } - PromoteTo = (MVT::ValueType)LargerReg; - } - - assert(MVT::isInteger(VT) == MVT::isInteger(PromoteTo) && - MVT::isFloatingPoint(VT) == MVT::isFloatingPoint(PromoteTo) && - "Can only promote from int->int or fp->fp!"); - assert(VT < PromoteTo && "Must promote to a larger type!"); - TransformToType[VT] = PromoteTo; - } else if (Action == TargetLowering::Expand) { - // f32 and f64 is each expanded to corresponding integer type of same size. - if (VT == MVT::f32) - TransformToType[VT] = MVT::i32; - else if (VT == MVT::f64) - TransformToType[VT] = MVT::i64; - else { - assert((MVT::isVector(VT) || MVT::isInteger(VT)) && VT > MVT::i8 && - "Cannot expand this type: target must support SOME integer reg!"); - // Expand to the next smaller integer type! - TransformToType[VT] = (MVT::ValueType)(VT-1); - } - } -} - - /// computeRegisterProperties - Once all of the register classes are added, /// this allows us to compute derived properties we expose. void TargetLowering::computeRegisterProperties() { assert(MVT::LAST_VALUETYPE <= 32 && "Too many value types for ValueTypeActions to hold!"); - // Everything defaults to one. - for (unsigned i = 0; i != MVT::LAST_VALUETYPE; ++i) + // Everything defaults to needing one register. + for (unsigned i = 0; i != MVT::LAST_VALUETYPE; ++i) { NumRegistersForVT[i] = 1; + RegisterTypeForVT[i] = TransformToType[i] = i; + } + // ...except isVoid, which doesn't need any registers. + NumRegistersForVT[MVT::isVoid] = 0; // Find the largest integer register class. unsigned LargestIntReg = MVT::i128; @@ -225,57 +186,65 @@ void TargetLowering::computeRegisterProperties() { // Every integer value type larger than this largest register takes twice as // many registers to represent as the previous ValueType. - unsigned ExpandedReg = LargestIntReg; ++LargestIntReg; - for (++ExpandedReg; MVT::isInteger((MVT::ValueType)ExpandedReg);++ExpandedReg) + for (MVT::ValueType ExpandedReg = LargestIntReg + 1; + MVT::isInteger(ExpandedReg); ++ExpandedReg) { NumRegistersForVT[ExpandedReg] = 2*NumRegistersForVT[ExpandedReg-1]; + RegisterTypeForVT[ExpandedReg] = LargestIntReg; + TransformToType[ExpandedReg] = ExpandedReg - 1; + ValueTypeActions.setTypeAction(ExpandedReg, Expand); + } + + // Inspect all of the ValueType's smaller than the largest integer + // register to see which ones need promotion. + MVT::ValueType LegalIntReg = LargestIntReg; + for (MVT::ValueType IntReg = LargestIntReg - 1; + IntReg >= MVT::i1; --IntReg) { + if (isTypeLegal(IntReg)) { + LegalIntReg = IntReg; + } else { + RegisterTypeForVT[IntReg] = TransformToType[IntReg] = LegalIntReg; + ValueTypeActions.setTypeAction(IntReg, Promote); + } + } - // Inspect all of the ValueType's possible, deciding how to process them. - for (unsigned IntReg = MVT::i1; IntReg <= MVT::i128; ++IntReg) - // If we are expanding this type, expand it! - if (getNumRegisters((MVT::ValueType)IntReg) != 1) - SetValueTypeAction((MVT::ValueType)IntReg, Expand, *this, TransformToType, - ValueTypeActions); - else if (!isTypeLegal((MVT::ValueType)IntReg)) - // Otherwise, if we don't have native support, we must promote to a - // larger type. - SetValueTypeAction((MVT::ValueType)IntReg, Promote, *this, - TransformToType, ValueTypeActions); - else - TransformToType[(MVT::ValueType)IntReg] = (MVT::ValueType)IntReg; - - // If the target does not have native f64 support, expand it to i64. We will - // be generating soft float library calls. If the target does not have native - // support for f32, promote it to f64 if it is legal. Otherwise, expand it to - // i32. - if (isTypeLegal(MVT::f64)) - TransformToType[MVT::f64] = MVT::f64; - else { + // Decide how to handle f64. If the target does not have native f64 support, + // expand it to i64 and we will be generating soft float library calls. + if (!isTypeLegal(MVT::f64)) { NumRegistersForVT[MVT::f64] = NumRegistersForVT[MVT::i64]; - SetValueTypeAction(MVT::f64, Expand, *this, TransformToType, - ValueTypeActions); + RegisterTypeForVT[MVT::f64] = RegisterTypeForVT[MVT::i64]; + TransformToType[MVT::f64] = MVT::i64; + ValueTypeActions.setTypeAction(MVT::f64, Expand); } - if (isTypeLegal(MVT::f32)) - TransformToType[MVT::f32] = MVT::f32; - else if (isTypeLegal(MVT::f64)) - SetValueTypeAction(MVT::f32, Promote, *this, TransformToType, - ValueTypeActions); - else { - NumRegistersForVT[MVT::f32] = NumRegistersForVT[MVT::i32]; - SetValueTypeAction(MVT::f32, Expand, *this, TransformToType, - ValueTypeActions); + + // Decide how to handle f32. If the target does not have native support for + // f32, promote it to f64 if it is legal. Otherwise, expand it to i32. + if (!isTypeLegal(MVT::f32)) { + if (isTypeLegal(MVT::f64)) { + NumRegistersForVT[MVT::f32] = NumRegistersForVT[MVT::f64]; + RegisterTypeForVT[MVT::f32] = RegisterTypeForVT[MVT::f64]; + TransformToType[MVT::f32] = MVT::f64; + ValueTypeActions.setTypeAction(MVT::f32, Promote); + } else { + NumRegistersForVT[MVT::f32] = NumRegistersForVT[MVT::i32]; + RegisterTypeForVT[MVT::f32] = RegisterTypeForVT[MVT::i32]; + TransformToType[MVT::f32] = MVT::i32; + ValueTypeActions.setTypeAction(MVT::f32, Expand); + } } - // Loop over all of the legal vector value types, specifying an identity type - // transformation. - for (unsigned i = MVT::FIRST_VECTOR_VALUETYPE; + // Loop over all of the vector value types to see which need transformations. + for (MVT::ValueType i = MVT::FIRST_VECTOR_VALUETYPE; i <= MVT::LAST_VECTOR_VALUETYPE; ++i) { - if (isTypeLegal((MVT::ValueType)i)) - TransformToType[i] = (MVT::ValueType)i; - else { - MVT::ValueType VT1, VT2; - NumRegistersForVT[i] = getVectorTypeBreakdown(i, VT1, VT2); - SetValueTypeAction(i, Expand, *this, TransformToType, - ValueTypeActions); + if (!isTypeLegal(i)) { + MVT::ValueType IntermediateVT, RegisterVT; + unsigned NumIntermediates; + NumRegistersForVT[i] = + getVectorTypeBreakdown(i, + IntermediateVT, NumIntermediates, + RegisterVT); + RegisterTypeForVT[i] = RegisterVT; + TransformToType[i] = MVT::Other; // this isn't actually used + ValueTypeActions.setTypeAction(i, Expand); } } } @@ -290,12 +259,13 @@ const char *TargetLowering::getTargetNodeName(unsigned Opcode) const { /// Similarly, MVT::v2i64 turns into 4 MVT::i32 values with both PPC and X86. /// /// This method returns the number of registers needed, and the VT for each -/// register. It also returns the VT of the VectorType elements before they -/// are promoted/expanded. +/// register. It also returns the VT and quantity of the intermediate values +/// before they are promoted/expanded. /// unsigned TargetLowering::getVectorTypeBreakdown(MVT::ValueType VT, - MVT::ValueType &ElementVT, - MVT::ValueType &LegalElementVT) const { + MVT::ValueType &IntermediateVT, + unsigned &NumIntermediates, + MVT::ValueType &RegisterVT) const { // Figure out the right, legal destination reg to copy into. unsigned NumElts = MVT::getVectorNumElements(VT); MVT::ValueType EltTy = MVT::getVectorElementType(VT); @@ -309,14 +279,16 @@ unsigned TargetLowering::getVectorTypeBreakdown(MVT::ValueType VT, NumElts >>= 1; NumVectorRegs <<= 1; } + + NumIntermediates = NumVectorRegs; MVT::ValueType NewVT = MVT::getVectorType(EltTy, NumElts); if (!isTypeLegal(NewVT)) NewVT = EltTy; - ElementVT = NewVT; + IntermediateVT = NewVT; MVT::ValueType DestVT = getTypeToTransformTo(NewVT); - LegalElementVT = DestVT; + RegisterVT = DestVT; if (DestVT < NewVT) { // Value is expanded, e.g. i64 -> i16. return NumVectorRegs*(MVT::getSizeInBits(NewVT)/MVT::getSizeInBits(DestVT)); -- 2.34.1