diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2011-02-20 12:57:14 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2011-02-20 12:57:14 +0000 |
commit | cf099d11218cb6f6c5cce947d6738e347f07fb12 (patch) | |
tree | d2b61ce94e654cb01a254d2195259db5f9cc3f3c /lib/Target/Mips/MipsISelLowering.cpp | |
parent | 49011b52fcba02a6051957b84705159f52fae4e4 (diff) | |
download | src-cf099d11218cb6f6c5cce947d6738e347f07fb12.tar.gz src-cf099d11218cb6f6c5cce947d6738e347f07fb12.zip |
Notes
Diffstat (limited to 'lib/Target/Mips/MipsISelLowering.cpp')
-rw-r--r-- | lib/Target/Mips/MipsISelLowering.cpp | 620 |
1 files changed, 440 insertions, 180 deletions
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index b0b99bad1607..1d7a1c0ae8c7 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -41,12 +41,15 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::Lo : return "MipsISD::Lo"; case MipsISD::GPRel : return "MipsISD::GPRel"; case MipsISD::Ret : return "MipsISD::Ret"; - case MipsISD::CMov : return "MipsISD::CMov"; case MipsISD::SelectCC : return "MipsISD::SelectCC"; case MipsISD::FPSelectCC : return "MipsISD::FPSelectCC"; case MipsISD::FPBrcond : return "MipsISD::FPBrcond"; case MipsISD::FPCmp : return "MipsISD::FPCmp"; case MipsISD::FPRound : return "MipsISD::FPRound"; + case MipsISD::MAdd : return "MipsISD::MAdd"; + case MipsISD::MAddu : return "MipsISD::MAddu"; + case MipsISD::MSub : return "MipsISD::MSub"; + case MipsISD::MSubu : return "MipsISD::MSubu"; default : return NULL; } } @@ -57,7 +60,7 @@ MipsTargetLowering(MipsTargetMachine &TM) Subtarget = &TM.getSubtarget<MipsSubtarget>(); // Mips does not have i1 type, so use i32 for - // setcc operations results (slt, sgt, ...). + // setcc operations results (slt, sgt, ...). setBooleanContents(ZeroOrOneBooleanContent); // Set up the register classes @@ -69,7 +72,7 @@ MipsTargetLowering(MipsTargetMachine &TM) if (!Subtarget->isFP64bit()) addRegisterClass(MVT::f64, Mips::AFGR64RegisterClass); - // Load extented operations for i1 types must be promoted + // Load extented operations for i1 types must be promoted setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); @@ -78,9 +81,9 @@ MipsTargetLowering(MipsTargetMachine &TM) setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); setTruncStoreAction(MVT::f64, MVT::f32, Expand); - // Used by legalize types to correctly generate the setcc result. - // Without this, every float setcc comes with a AND/OR with the result, - // we don't want this, since the fpcmp result goes to a flag register, + // Used by legalize types to correctly generate the setcc result. + // Without this, every float setcc comes with a AND/OR with the result, + // we don't want this, since the fpcmp result goes to a flag register, // which is used implicitly by brcond and select operations. AddPromotedToType(ISD::SETCC, MVT::i1, MVT::i32); @@ -100,8 +103,8 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::VASTART, MVT::Other, Custom); - // We custom lower AND/OR to handle the case where the DAG contain 'ands/ors' - // with operands comming from setcc fp comparions. This is necessary since + // We custom lower AND/OR to handle the case where the DAG contain 'ands/ors' + // with operands comming from setcc fp comparions. This is necessary since // the result from these setcc are in a flag registers (FCR31). setOperationAction(ISD::AND, MVT::i32, Custom); setOperationAction(ISD::OR, MVT::i32, Custom); @@ -116,7 +119,10 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::CTPOP, MVT::i32, Expand); setOperationAction(ISD::CTTZ, MVT::i32, Expand); setOperationAction(ISD::ROTL, MVT::i32, Expand); - setOperationAction(ISD::ROTR, MVT::i32, Expand); + + if (!Subtarget->isMips32r2()) + setOperationAction(ISD::ROTR, MVT::i32, Expand); + setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); @@ -152,6 +158,9 @@ MipsTargetLowering(MipsTargetMachine &TM) if (!Subtarget->hasSwap()) setOperationAction(ISD::BSWAP, MVT::i32, Expand); + setTargetDAGCombine(ISD::ADDE); + setTargetDAGCombine(ISD::SUBE); + setStackPointerRegisterToSaveRestore(Mips::SP); computeRegisterProperties(); } @@ -165,10 +174,198 @@ unsigned MipsTargetLowering::getFunctionAlignment(const Function *) const { return 2; } +// SelectMadd - +// Transforms a subgraph in CurDAG if the following pattern is found: +// (addc multLo, Lo0), (adde multHi, Hi0), +// where, +// multHi/Lo: product of multiplication +// Lo0: initial value of Lo register +// Hi0: initial value of Hi register +// Return true if mattern matching was successful. +static bool SelectMadd(SDNode* ADDENode, SelectionDAG* CurDAG) { + // ADDENode's second operand must be a flag output of an ADDC node in order + // for the matching to be successful. + SDNode* ADDCNode = ADDENode->getOperand(2).getNode(); + + if (ADDCNode->getOpcode() != ISD::ADDC) + return false; + + SDValue MultHi = ADDENode->getOperand(0); + SDValue MultLo = ADDCNode->getOperand(0); + SDNode* MultNode = MultHi.getNode(); + unsigned MultOpc = MultHi.getOpcode(); + + // MultHi and MultLo must be generated by the same node, + if (MultLo.getNode() != MultNode) + return false; + + // and it must be a multiplication. + if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI) + return false; + + // MultLo amd MultHi must be the first and second output of MultNode + // respectively. + if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0) + return false; + + // Transform this to a MADD only if ADDENode and ADDCNode are the only users + // of the values of MultNode, in which case MultNode will be removed in later + // phases. + // If there exist users other than ADDENode or ADDCNode, this function returns + // here, which will result in MultNode being mapped to a single MULT + // instruction node rather than a pair of MULT and MADD instructions being + // produced. + if (!MultHi.hasOneUse() || !MultLo.hasOneUse()) + return false; + + SDValue Chain = CurDAG->getEntryNode(); + DebugLoc dl = ADDENode->getDebugLoc(); + + // create MipsMAdd(u) node + MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MAddu : MipsISD::MAdd; + + SDValue MAdd = CurDAG->getNode(MultOpc, dl, + MVT::Glue, + MultNode->getOperand(0),// Factor 0 + MultNode->getOperand(1),// Factor 1 + ADDCNode->getOperand(1),// Lo0 + ADDENode->getOperand(1));// Hi0 + + // create CopyFromReg nodes + SDValue CopyFromLo = CurDAG->getCopyFromReg(Chain, dl, Mips::LO, MVT::i32, + MAdd); + SDValue CopyFromHi = CurDAG->getCopyFromReg(CopyFromLo.getValue(1), dl, + Mips::HI, MVT::i32, + CopyFromLo.getValue(2)); + + // replace uses of adde and addc here + if (!SDValue(ADDCNode, 0).use_empty()) + CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDCNode, 0), CopyFromLo); + + if (!SDValue(ADDENode, 0).use_empty()) + CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDENode, 0), CopyFromHi); + + return true; +} + +// SelectMsub - +// Transforms a subgraph in CurDAG if the following pattern is found: +// (addc Lo0, multLo), (sube Hi0, multHi), +// where, +// multHi/Lo: product of multiplication +// Lo0: initial value of Lo register +// Hi0: initial value of Hi register +// Return true if mattern matching was successful. +static bool SelectMsub(SDNode* SUBENode, SelectionDAG* CurDAG) { + // SUBENode's second operand must be a flag output of an SUBC node in order + // for the matching to be successful. + SDNode* SUBCNode = SUBENode->getOperand(2).getNode(); + + if (SUBCNode->getOpcode() != ISD::SUBC) + return false; + + SDValue MultHi = SUBENode->getOperand(1); + SDValue MultLo = SUBCNode->getOperand(1); + SDNode* MultNode = MultHi.getNode(); + unsigned MultOpc = MultHi.getOpcode(); + + // MultHi and MultLo must be generated by the same node, + if (MultLo.getNode() != MultNode) + return false; + + // and it must be a multiplication. + if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI) + return false; + + // MultLo amd MultHi must be the first and second output of MultNode + // respectively. + if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0) + return false; + + // Transform this to a MSUB only if SUBENode and SUBCNode are the only users + // of the values of MultNode, in which case MultNode will be removed in later + // phases. + // If there exist users other than SUBENode or SUBCNode, this function returns + // here, which will result in MultNode being mapped to a single MULT + // instruction node rather than a pair of MULT and MSUB instructions being + // produced. + if (!MultHi.hasOneUse() || !MultLo.hasOneUse()) + return false; + + SDValue Chain = CurDAG->getEntryNode(); + DebugLoc dl = SUBENode->getDebugLoc(); + + // create MipsSub(u) node + MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MSubu : MipsISD::MSub; + + SDValue MSub = CurDAG->getNode(MultOpc, dl, + MVT::Glue, + MultNode->getOperand(0),// Factor 0 + MultNode->getOperand(1),// Factor 1 + SUBCNode->getOperand(0),// Lo0 + SUBENode->getOperand(0));// Hi0 + + // create CopyFromReg nodes + SDValue CopyFromLo = CurDAG->getCopyFromReg(Chain, dl, Mips::LO, MVT::i32, + MSub); + SDValue CopyFromHi = CurDAG->getCopyFromReg(CopyFromLo.getValue(1), dl, + Mips::HI, MVT::i32, + CopyFromLo.getValue(2)); + + // replace uses of sube and subc here + if (!SDValue(SUBCNode, 0).use_empty()) + CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBCNode, 0), CopyFromLo); + + if (!SDValue(SUBENode, 0).use_empty()) + CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBENode, 0), CopyFromHi); + + return true; +} + +static SDValue PerformADDECombine(SDNode *N, SelectionDAG& DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget* Subtarget) { + if (DCI.isBeforeLegalize()) + return SDValue(); + + if (Subtarget->isMips32() && SelectMadd(N, &DAG)) + return SDValue(N, 0); + + return SDValue(); +} + +static SDValue PerformSUBECombine(SDNode *N, SelectionDAG& DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget* Subtarget) { + if (DCI.isBeforeLegalize()) + return SDValue(); + + if (Subtarget->isMips32() && SelectMsub(N, &DAG)) + return SDValue(N, 0); + + return SDValue(); +} + +SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) + const { + SelectionDAG &DAG = DCI.DAG; + unsigned opc = N->getOpcode(); + + switch (opc) { + default: break; + case ISD::ADDE: + return PerformADDECombine(N, DAG, DCI, Subtarget); + case ISD::SUBE: + return PerformSUBECombine(N, DAG, DCI, Subtarget); + } + + return SDValue(); +} + SDValue MipsTargetLowering:: LowerOperation(SDValue Op, SelectionDAG &DAG) const { - switch (Op.getOpcode()) + switch (Op.getOpcode()) { case ISD::AND: return LowerANDOR(Op, DAG); case ISD::BRCOND: return LowerBRCOND(Op, DAG); @@ -194,7 +391,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const // MachineFunction as a live in value. It also creates a corresponding // virtual register for it. static unsigned -AddLiveIn(MachineFunction &MF, unsigned PReg, TargetRegisterClass *RC) +AddLiveIn(MachineFunction &MF, unsigned PReg, TargetRegisterClass *RC) { assert(RC->contains(PReg) && "Not the correct regclass!"); unsigned VReg = MF.getRegInfo().createVirtualRegister(RC); @@ -212,7 +409,7 @@ static Mips::FPBranchCode GetFPBranchCodeFromCond(Mips::CondCode CC) { return Mips::BRANCH_INVALID; } - + static unsigned FPBranchCodeToOpc(Mips::FPBranchCode BC) { switch(BC) { default: @@ -227,24 +424,24 @@ static unsigned FPBranchCodeToOpc(Mips::FPBranchCode BC) { static Mips::CondCode FPCondCCodeToFCC(ISD::CondCode CC) { switch (CC) { default: llvm_unreachable("Unknown fp condition code!"); - case ISD::SETEQ: + case ISD::SETEQ: case ISD::SETOEQ: return Mips::FCOND_EQ; case ISD::SETUNE: return Mips::FCOND_OGL; - case ISD::SETLT: + case ISD::SETLT: case ISD::SETOLT: return Mips::FCOND_OLT; - case ISD::SETGT: + case ISD::SETGT: case ISD::SETOGT: return Mips::FCOND_OGT; - case ISD::SETLE: - case ISD::SETOLE: return Mips::FCOND_OLE; + case ISD::SETLE: + case ISD::SETOLE: return Mips::FCOND_OLE; case ISD::SETGE: case ISD::SETOGE: return Mips::FCOND_OGE; case ISD::SETULT: return Mips::FCOND_ULT; - case ISD::SETULE: return Mips::FCOND_ULE; + case ISD::SETULE: return Mips::FCOND_ULE; case ISD::SETUGT: return Mips::FCOND_UGT; case ISD::SETUGE: return Mips::FCOND_UGE; - case ISD::SETUO: return Mips::FCOND_UN; + case ISD::SETUO: return Mips::FCOND_UN; case ISD::SETO: return Mips::FCOND_OR; - case ISD::SETNE: + case ISD::SETNE: case ISD::SETONE: return Mips::FCOND_NEQ; case ISD::SETUEQ: return Mips::FCOND_UEQ; } @@ -364,7 +561,7 @@ LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const // Emit the round instruction and bit convert to integer SDValue Trunc = DAG.getNode(MipsISD::FPRound, dl, MVT::f32, Src, CondReg.getValue(1)); - SDValue BitCvt = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Trunc); + SDValue BitCvt = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Trunc); return BitCvt; } @@ -382,11 +579,11 @@ LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const // obtain the new stack size. SDValue Sub = DAG.getNode(ISD::SUB, dl, MVT::i32, StackPointer, Size); - // The Sub result contains the new stack start address, so it + // The Sub result contains the new stack start address, so it // must be placed in the stack pointer register. Chain = DAG.getCopyToReg(StackPointer.getValue(1), dl, Mips::SP, Sub); - - // This node always has two return values: a new stack pointer + + // This node always has two return values: a new stack pointer // value and a chain SDValue Ops[2] = { Sub, Chain }; return DAG.getMergeValues(Ops, 2, dl); @@ -405,9 +602,9 @@ LowerANDOR(SDValue Op, SelectionDAG &DAG) const SDValue True = DAG.getConstant(1, MVT::i32); SDValue False = DAG.getConstant(0, MVT::i32); - SDValue LSEL = DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(), + SDValue LSEL = DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(), LHS, True, False, LHS.getOperand(2)); - SDValue RSEL = DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(), + SDValue RSEL = DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(), RHS, True, False, RHS.getOperand(2)); return DAG.getNode(Op.getOpcode(), dl, MVT::i32, LSEL, RSEL); @@ -416,7 +613,7 @@ LowerANDOR(SDValue Op, SelectionDAG &DAG) const SDValue MipsTargetLowering:: LowerBRCOND(SDValue Op, SelectionDAG &DAG) const { - // The first operand is the chain, the second is the condition, the third is + // The first operand is the chain, the second is the condition, the third is // the block to branch to if the condition is true. SDValue Chain = Op.getOperand(0); SDValue Dest = Op.getOperand(2); @@ -424,55 +621,55 @@ LowerBRCOND(SDValue Op, SelectionDAG &DAG) const if (Op.getOperand(1).getOpcode() != MipsISD::FPCmp) return Op; - + SDValue CondRes = Op.getOperand(1); SDValue CCNode = CondRes.getOperand(2); Mips::CondCode CC = (Mips::CondCode)cast<ConstantSDNode>(CCNode)->getZExtValue(); - SDValue BrCode = DAG.getConstant(GetFPBranchCodeFromCond(CC), MVT::i32); + SDValue BrCode = DAG.getConstant(GetFPBranchCodeFromCond(CC), MVT::i32); - return DAG.getNode(MipsISD::FPBrcond, dl, Op.getValueType(), Chain, BrCode, + return DAG.getNode(MipsISD::FPBrcond, dl, Op.getValueType(), Chain, BrCode, Dest, CondRes); } SDValue MipsTargetLowering:: LowerSETCC(SDValue Op, SelectionDAG &DAG) const { - // The operands to this are the left and right operands to compare (ops #0, - // and #1) and the condition code to compare them with (op #2) as a + // The operands to this are the left and right operands to compare (ops #0, + // and #1) and the condition code to compare them with (op #2) as a // CondCodeSDNode. - SDValue LHS = Op.getOperand(0); + SDValue LHS = Op.getOperand(0); SDValue RHS = Op.getOperand(1); DebugLoc dl = Op.getDebugLoc(); ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); - - return DAG.getNode(MipsISD::FPCmp, dl, Op.getValueType(), LHS, RHS, + + return DAG.getNode(MipsISD::FPCmp, dl, Op.getValueType(), LHS, RHS, DAG.getConstant(FPCondCCodeToFCC(CC), MVT::i32)); } SDValue MipsTargetLowering:: LowerSELECT(SDValue Op, SelectionDAG &DAG) const { - SDValue Cond = Op.getOperand(0); + SDValue Cond = Op.getOperand(0); SDValue True = Op.getOperand(1); SDValue False = Op.getOperand(2); DebugLoc dl = Op.getDebugLoc(); - // if the incomming condition comes from a integer compare, the select - // operation must be SelectCC or a conditional move if the subtarget + // if the incomming condition comes from a integer compare, the select + // operation must be SelectCC or a conditional move if the subtarget // supports it. if (Cond.getOpcode() != MipsISD::FPCmp) { if (Subtarget->hasCondMov() && !True.getValueType().isFloatingPoint()) return Op; - return DAG.getNode(MipsISD::SelectCC, dl, True.getValueType(), + return DAG.getNode(MipsISD::SelectCC, dl, True.getValueType(), Cond, True, False); } // if the incomming condition comes from fpcmp, the select // operation must use FPSelectCC. SDValue CCNode = Cond.getOperand(2); - return DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(), + return DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(), Cond, True, False, CCNode); } @@ -484,16 +681,16 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op, if (getTargetMachine().getRelocationModel() != Reloc::PIC_) { SDVTList VTs = DAG.getVTList(MVT::i32); - + MipsTargetObjectFile &TLOF = (MipsTargetObjectFile&)getObjFileLowering(); - + // %gp_rel relocation - if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) { - SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, + if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) { + SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, MipsII::MO_GPREL); SDValue GPRelNode = DAG.getNode(MipsISD::GPRel, dl, VTs, &GA, 1); SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(MVT::i32); - return DAG.getNode(ISD::ADD, dl, MVT::i32, GOT, GPRelNode); + return DAG.getNode(ISD::ADD, dl, MVT::i32, GOT, GPRelNode); } // %hi/%lo relocation SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, @@ -505,8 +702,8 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op, } else { SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, MipsII::MO_GOT); - SDValue ResNode = DAG.getLoad(MVT::i32, dl, - DAG.getEntryNode(), GA, NULL, 0, + SDValue ResNode = DAG.getLoad(MVT::i32, dl, + DAG.getEntryNode(), GA, MachinePointerInfo(), false, false, 0); // On functions and global targets not internal linked only // a load from got/GP is necessary for PIC to work. @@ -531,7 +728,7 @@ SDValue MipsTargetLowering:: LowerJumpTable(SDValue Op, SelectionDAG &DAG) const { SDValue ResNode; - SDValue HiPart; + SDValue HiPart; // FIXME there isn't actually debug info here DebugLoc dl = Op.getDebugLoc(); bool IsPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_; @@ -546,7 +743,8 @@ LowerJumpTable(SDValue Op, SelectionDAG &DAG) const SDValue Ops[] = { JTI }; HiPart = DAG.getNode(MipsISD::Hi, dl, DAG.getVTList(MVT::i32), Ops, 1); } else // Emit Load from Global Pointer - HiPart = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), JTI, NULL, 0, + HiPart = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), JTI, + MachinePointerInfo(), false, false, 0); SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, JTI); @@ -565,26 +763,27 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) const DebugLoc dl = Op.getDebugLoc(); // gp_rel relocation - // FIXME: we should reference the constant pool using small data sections, + // FIXME: we should reference the constant pool using small data sections, // but the asm printer currently doens't support this feature without - // hacking it. This feature should come soon so we can uncomment the + // hacking it. This feature should come soon so we can uncomment the // stuff below. //if (IsInSmallSection(C->getType())) { // SDValue GPRelNode = DAG.getNode(MipsISD::GPRel, MVT::i32, CP); // SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(MVT::i32); - // ResNode = DAG.getNode(ISD::ADD, MVT::i32, GOT, GPRelNode); + // ResNode = DAG.getNode(ISD::ADD, MVT::i32, GOT, GPRelNode); if (getTargetMachine().getRelocationModel() != Reloc::PIC_) { - SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), + SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), N->getOffset(), MipsII::MO_ABS_HILO); SDValue HiPart = DAG.getNode(MipsISD::Hi, dl, MVT::i32, CP); SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, CP); ResNode = DAG.getNode(ISD::ADD, dl, MVT::i32, HiPart, Lo); } else { - SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), + SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), N->getOffset(), MipsII::MO_GOT); - SDValue Load = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), - CP, NULL, 0, false, false, 0); + SDValue Load = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), + CP, MachinePointerInfo::getConstantPool(), + false, false, 0); SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, CP); ResNode = DAG.getNode(ISD::ADD, dl, MVT::i32, Load, Lo); } @@ -603,7 +802,8 @@ SDValue MipsTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { // vastart just stores the address of the VarArgsFrameIndex slot into the // memory location argument. const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); - return DAG.getStore(Op.getOperand(0), dl, FI, Op.getOperand(1), SV, 0, + return DAG.getStore(Op.getOperand(0), dl, FI, Op.getOperand(1), + MachinePointerInfo(SV), false, false, 0); } @@ -614,23 +814,23 @@ SDValue MipsTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { #include "MipsGenCallingConv.inc" //===----------------------------------------------------------------------===// -// TODO: Implement a generic logic using tblgen that can support this. +// TODO: Implement a generic logic using tblgen that can support this. // Mips O32 ABI rules: // --- // i32 - Passed in A0, A1, A2, A3 and stack -// f32 - Only passed in f32 registers if no int reg has been used yet to hold +// f32 - Only passed in f32 registers if no int reg has been used yet to hold // an argument. Otherwise, passed in A1, A2, A3 and stack. -// f64 - Only passed in two aliased f32 registers if no int reg has been used -// yet to hold an argument. Otherwise, use A2, A3 and stack. If A1 is +// f64 - Only passed in two aliased f32 registers if no int reg has been used +// yet to hold an argument. Otherwise, use A2, A3 and stack. If A1 is // not used, it must be shadowed. If only A3 is avaiable, shadow it and // go to stack. //===----------------------------------------------------------------------===// -static bool CC_MipsO32(unsigned ValNo, EVT ValVT, - EVT LocVT, CCValAssign::LocInfo LocInfo, +static bool CC_MipsO32(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State) { - static const unsigned IntRegsSize=4, FloatRegsSize=2; + static const unsigned IntRegsSize=4, FloatRegsSize=2; static const unsigned IntRegs[] = { Mips::A0, Mips::A1, Mips::A2, Mips::A3 @@ -642,9 +842,15 @@ static bool CC_MipsO32(unsigned ValNo, EVT ValVT, Mips::D6, Mips::D7 }; - unsigned Reg=0; - unsigned UnallocIntReg = State.getFirstUnallocated(IntRegs, IntRegsSize); - bool IntRegUsed = (IntRegs[UnallocIntReg] != (unsigned (Mips::A0))); + unsigned Reg = 0; + static bool IntRegUsed = false; + + // This must be the first arg of the call if no regs have been allocated. + // Initialize IntRegUsed in that case. + if (IntRegs[State.getFirstUnallocated(IntRegs, IntRegsSize)] == Mips::A0 && + F32Regs[State.getFirstUnallocated(F32Regs, FloatRegsSize)] == Mips::F12 && + F64Regs[State.getFirstUnallocated(F64Regs, FloatRegsSize)] == Mips::D6) + IntRegUsed = false; // Promote i8 and i16 if (LocVT == MVT::i8 || LocVT == MVT::i16) { @@ -657,30 +863,48 @@ static bool CC_MipsO32(unsigned ValNo, EVT ValVT, LocInfo = CCValAssign::AExt; } - if (ValVT == MVT::i32 || (ValVT == MVT::f32 && IntRegUsed)) { + if (ValVT == MVT::i32) { Reg = State.AllocateReg(IntRegs, IntRegsSize); IntRegUsed = true; - LocVT = MVT::i32; - } - - if (ValVT.isFloatingPoint() && !IntRegUsed) { - if (ValVT == MVT::f32) - Reg = State.AllocateReg(F32Regs, FloatRegsSize); - else - Reg = State.AllocateReg(F64Regs, FloatRegsSize); - } + } else if (ValVT == MVT::f32) { + // An int reg has to be marked allocated regardless of whether or not + // IntRegUsed is true. + Reg = State.AllocateReg(IntRegs, IntRegsSize); - if (ValVT == MVT::f64 && IntRegUsed) { - if (UnallocIntReg != IntRegsSize) { - // If we hit register A3 as the first not allocated, we must - // mark it as allocated (shadow) and use the stack instead. - if (IntRegs[UnallocIntReg] != (unsigned (Mips::A3))) - Reg = Mips::A2; - for (;UnallocIntReg < IntRegsSize; ++UnallocIntReg) - State.AllocateReg(UnallocIntReg); - } - LocVT = MVT::i32; - } + if (IntRegUsed) { + if (Reg) // Int reg is available + LocVT = MVT::i32; + } else { + unsigned FReg = State.AllocateReg(F32Regs, FloatRegsSize); + if (FReg) // F32 reg is available + Reg = FReg; + else if (Reg) // No F32 regs are available, but an int reg is available. + LocVT = MVT::i32; + } + } else if (ValVT == MVT::f64) { + // Int regs have to be marked allocated regardless of whether or not + // IntRegUsed is true. + Reg = State.AllocateReg(IntRegs, IntRegsSize); + if (Reg == Mips::A1) + Reg = State.AllocateReg(IntRegs, IntRegsSize); + else if (Reg == Mips::A3) + Reg = 0; + State.AllocateReg(IntRegs, IntRegsSize); + + // At this point, Reg is A0, A2 or 0, and all the unavailable integer regs + // are marked as allocated. + if (IntRegUsed) { + if (Reg)// if int reg is available + LocVT = MVT::i32; + } else { + unsigned FReg = State.AllocateReg(F64Regs, FloatRegsSize); + if (FReg) // F64 reg is available. + Reg = FReg; + else if (Reg) // No F64 regs are available, but an int reg is available. + LocVT = MVT::i32; + } + } else + assert(false && "cannot handle this ValVT"); if (!Reg) { unsigned SizeInBytes = ValVT.getSizeInBits() >> 3; @@ -692,8 +916,8 @@ static bool CC_MipsO32(unsigned ValNo, EVT ValVT, return false; // CC must always match } -static bool CC_MipsO32_VarArgs(unsigned ValNo, EVT ValVT, - EVT LocVT, CCValAssign::LocInfo LocInfo, +static bool CC_MipsO32_VarArgs(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State) { static const unsigned IntRegsSize=4; @@ -736,7 +960,7 @@ static bool CC_MipsO32_VarArgs(unsigned ValNo, EVT ValVT, IntRegs[UnallocIntReg] == (unsigned (Mips::A2))) { unsigned Reg = State.AllocateReg(IntRegs, IntRegsSize); State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, MVT::i32, LocInfo)); - // Shadow the next register so it can be used + // Shadow the next register so it can be used // later to get the other 32bit part. State.AllocateReg(IntRegs, IntRegsSize); return false; @@ -786,13 +1010,13 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // To meet O32 ABI, Mips must always allocate 16 bytes on // the stack (even if less than 4 are used as arguments) if (Subtarget->isABI_O32()) { - int VTsize = EVT(MVT::i32).getSizeInBits()/8; + int VTsize = MVT(MVT::i32).getSizeInBits()/8; MFI->CreateFixedObject(VTsize, (VTsize*3), true); - CCInfo.AnalyzeCallOperands(Outs, + CCInfo.AnalyzeCallOperands(Outs, isVarArg ? CC_MipsO32_VarArgs : CC_MipsO32); } else CCInfo.AnalyzeCallOperands(Outs, CC_Mips); - + // Get a count of how many bytes are to be pushed on the stack. unsigned NumBytes = CCInfo.getNextStackOffset(); Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true)); @@ -801,7 +1025,7 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, SmallVector<std::pair<unsigned, SDValue>, 16> RegsToPass; SmallVector<SDValue, 8> MemOpChains; - // First/LastArgStackLoc contains the first/last + // First/LastArgStackLoc contains the first/last // "at stack" argument location. int LastArgStackLoc = 0; unsigned FirstStackArgLoc = (Subtarget->isABI_EABI() ? 0 : 16); @@ -814,12 +1038,12 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // Promote the value if needed. switch (VA.getLocInfo()) { default: llvm_unreachable("Unknown loc info!"); - case CCValAssign::Full: + case CCValAssign::Full: if (Subtarget->isABI_O32() && VA.isRegLoc()) { if (VA.getValVT() == MVT::f32 && VA.getLocVT() == MVT::i32) - Arg = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Arg); + Arg = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Arg); if (VA.getValVT() == MVT::f64 && VA.getLocVT() == MVT::i32) { - Arg = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i64, Arg); + Arg = DAG.getNode(ISD::BITCAST, dl, MVT::i64, Arg); SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Arg, DAG.getConstant(0, getPointerTy())); SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Arg, @@ -827,7 +1051,7 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, RegsToPass.push_back(std::make_pair(VA.getLocReg(), Lo)); RegsToPass.push_back(std::make_pair(VA.getLocReg()+1, Hi)); continue; - } + } } break; case CCValAssign::SExt: @@ -840,17 +1064,17 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); break; } - - // Arguments that can be passed on register must be kept at + + // Arguments that can be passed on register must be kept at // RegsToPass vector if (VA.isRegLoc()) { RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); continue; } - + // Register can't get to this point... assert(VA.isMemLoc()); - + // Create the frame index object for this incoming parameter // This guarantees that when allocating Local Area the firsts // 16 bytes which are alwayes reserved won't be overwritten @@ -861,50 +1085,51 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, SDValue PtrOff = DAG.getFrameIndex(FI,getPointerTy()); - // emit ISD::STORE whichs stores the + // emit ISD::STORE whichs stores the // parameter value to a stack Location - MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0, + MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, + MachinePointerInfo(), false, false, 0)); } // Transform all store nodes into one single node because all store // nodes are independent of each other. - if (!MemOpChains.empty()) - Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + if (!MemOpChains.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &MemOpChains[0], MemOpChains.size()); - // Build a sequence of copy-to-reg nodes chained together with token + // Build a sequence of copy-to-reg nodes chained together with token // chain and flag operands which copy the outgoing args into registers. // The InFlag in necessary since all emited instructions must be // stuck together. SDValue InFlag; for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { - Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, + Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, RegsToPass[i].second, InFlag); InFlag = Chain.getValue(1); } // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every - // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol - // node so that legalize doesn't hack it. + // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol + // node so that legalize doesn't hack it. unsigned char OpFlag = IsPIC ? MipsII::MO_GOT_CALL : MipsII::MO_NO_FLAG; - if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) - Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, + if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy(), 0, OpFlag); else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) - Callee = DAG.getTargetExternalSymbol(S->getSymbol(), + Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy(), OpFlag); // MipsJmpLink = #chain, #target_address, #opt_in_flags... - // = Chain, Callee, Reg#1, Reg#2, ... + // = Chain, Callee, Reg#1, Reg#2, ... // // Returns a chain & a flag for retval copy to use. - SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); SmallVector<SDValue, 8> Ops; Ops.push_back(Chain); Ops.push_back(Callee); - // Add argument registers to the end of the list so that they are + // Add argument registers to the end of the list so that they are // known live into the call. for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) Ops.push_back(DAG.getRegister(RegsToPass[i].first, @@ -916,17 +1141,17 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, Chain = DAG.getNode(MipsISD::JmpLink, dl, NodeTys, &Ops[0], Ops.size()); InFlag = Chain.getValue(1); - // Create a stack location to hold GP when PIC is used. This stack - // location is used on function prologue to save GP and also after all - // emited CALL's to restore GP. + // Create a stack location to hold GP when PIC is used. This stack + // location is used on function prologue to save GP and also after all + // emited CALL's to restore GP. if (IsPIC) { - // Function can have an arbitrary number of calls, so + // Function can have an arbitrary number of calls, so // hold the LastArgStackLoc with the biggest offset. int FI; MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); if (LastArgStackLoc >= MipsFI->getGPStackOffset()) { LastArgStackLoc = (!LastArgStackLoc) ? (16) : (LastArgStackLoc+4); - // Create the frame index only once. SPOffset here can be anything + // Create the frame index only once. SPOffset here can be anything // (this will be fixed on processFunctionBeforeFrameFinalized) if (MipsFI->getGPStackOffset() == -1) { FI = MFI->CreateFixedObject(4, 0, true); @@ -937,14 +1162,15 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // Reload GP value. FI = MipsFI->getGPFI(); - SDValue FIN = DAG.getFrameIndex(FI,getPointerTy()); - SDValue GPLoad = DAG.getLoad(MVT::i32, dl, Chain, FIN, NULL, 0, + SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); + SDValue GPLoad = DAG.getLoad(MVT::i32, dl, Chain, FIN, + MachinePointerInfo::getFixedStack(FI), false, false, 0); Chain = GPLoad.getValue(1); - Chain = DAG.getCopyToReg(Chain, dl, DAG.getRegister(Mips::GP, MVT::i32), + Chain = DAG.getCopyToReg(Chain, dl, DAG.getRegister(Mips::GP, MVT::i32), GPLoad, SDValue(0,0)); InFlag = Chain.getValue(1); - } + } // Create the CALLSEQ_END node. Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true), @@ -988,7 +1214,7 @@ MipsTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, // Formal Arguments Calling Convention Implementation //===----------------------------------------------------------------------===// -/// LowerFormalArguments - transform physical registers into virtual registers +/// LowerFormalArguments - transform physical registers into virtual registers /// and generate load operations for arguments places on the stack. SDValue MipsTargetLowering::LowerFormalArguments(SDValue Chain, @@ -1018,7 +1244,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, ArgLocs, *DAG.getContext()); if (Subtarget->isABI_O32()) - CCInfo.AnalyzeFormalArguments(Ins, + CCInfo.AnalyzeFormalArguments(Ins, isVarArg ? CC_MipsO32_VarArgs : CC_MipsO32); else CCInfo.AnalyzeFormalArguments(Ins, CC_Mips); @@ -1037,22 +1263,22 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, TargetRegisterClass *RC = 0; if (RegVT == MVT::i32) - RC = Mips::CPURegsRegisterClass; - else if (RegVT == MVT::f32) + RC = Mips::CPURegsRegisterClass; + else if (RegVT == MVT::f32) RC = Mips::FGR32RegisterClass; else if (RegVT == MVT::f64) { - if (!Subtarget->isSingleFloat()) + if (!Subtarget->isSingleFloat()) RC = Mips::AFGR64RegisterClass; - } else + } else llvm_unreachable("RegVT not supported by FormalArguments Lowering"); - // Transform the arguments stored on + // Transform the arguments stored on // physical registers into virtual ones unsigned Reg = AddLiveIn(DAG.getMachineFunction(), ArgRegEnd, RC); SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT); - - // If this is an 8 or 16-bit value, it has been passed promoted - // to 32 bits. Insert an assert[sz]ext to capture this, then + + // If this is an 8 or 16-bit value, it has been passed promoted + // to 32 bits. Insert an assert[sz]ext to capture this, then // truncate to the right size. if (VA.getLocInfo() != CCValAssign::Full) { unsigned Opcode = 0; @@ -1061,22 +1287,21 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, else if (VA.getLocInfo() == CCValAssign::ZExt) Opcode = ISD::AssertZext; if (Opcode) - ArgValue = DAG.getNode(Opcode, dl, RegVT, ArgValue, + ArgValue = DAG.getNode(Opcode, dl, RegVT, ArgValue, DAG.getValueType(VA.getValVT())); ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); } - // Handle O32 ABI cases: i32->f32 and (i32,i32)->f64 + // Handle O32 ABI cases: i32->f32 and (i32,i32)->f64 if (Subtarget->isABI_O32()) { - if (RegVT == MVT::i32 && VA.getValVT() == MVT::f32) - ArgValue = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, ArgValue); + if (RegVT == MVT::i32 && VA.getValVT() == MVT::f32) + ArgValue = DAG.getNode(ISD::BITCAST, dl, MVT::f32, ArgValue); if (RegVT == MVT::i32 && VA.getValVT() == MVT::f64) { - unsigned Reg2 = AddLiveIn(DAG.getMachineFunction(), + unsigned Reg2 = AddLiveIn(DAG.getMachineFunction(), VA.getLocReg()+1, RC); SDValue ArgValue2 = DAG.getCopyFromReg(Chain, dl, Reg2, RegVT); - SDValue Hi = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, ArgValue); - SDValue Lo = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, ArgValue2); - ArgValue = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::f64, Lo, Hi); + SDValue Pair = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, ArgValue2, ArgValue); + ArgValue = DAG.getNode(ISD::BITCAST, dl, MVT::f64, Pair); } } @@ -1088,13 +1313,13 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, // The last argument is not a register anymore ArgRegEnd = 0; - - // The stack pointer offset is relative to the caller stack frame. - // Since the real stack size is unknown here, a negative SPOffset + + // The stack pointer offset is relative to the caller stack frame. + // Since the real stack size is unknown here, a negative SPOffset // is used so there's a way to adjust these offsets when the stack - // size get known (on EliminateFrameIndex). A dummy SPOffset is + // size get known (on EliminateFrameIndex). A dummy SPOffset is // used instead of a direct negative address (which is recorded to - // be used on emitPrologue) to avoid mis-calc of the first stack + // be used on emitPrologue) to avoid mis-calc of the first stack // offset on PEI::calculateFrameObjectOffsets. // Arguments are always 32-bit. unsigned ArgSize = VA.getLocVT().getSizeInBits()/8; @@ -1104,7 +1329,8 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, // Create load nodes to retrieve arguments from the stack SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); - InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, NULL, 0, + InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, + MachinePointerInfo::getFixedStack(FI), false, false, 0)); } } @@ -1124,11 +1350,11 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, // To meet ABI, when VARARGS are passed on registers, the registers // must have their values written to the caller stack frame. If the last - // argument was placed in the stack, there's no need to save any register. + // argument was placed in the stack, there's no need to save any register. if ((isVarArg) && (Subtarget->isABI_O32() && ArgRegEnd)) { if (StackPtr.getNode() == 0) StackPtr = DAG.getRegister(StackReg, getPointerTy()); - + // The last register argument that must be saved is Mips::A3 TargetRegisterClass *RC = Mips::CPURegsRegisterClass; unsigned StackLoc = ArgLocs.size()-1; @@ -1140,7 +1366,8 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, int FI = MFI->CreateFixedObject(4, 0, true); MipsFI->recordStoreVarArgsFI(FI, -(4+(StackLoc*4))); SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy()); - OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, NULL, 0, + OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, + MachinePointerInfo(), false, false, 0)); // Record the frame index of the first variable argument @@ -1150,7 +1377,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, } } - // All stores are grouped in one node to allow the matching between + // All stores are grouped in one node to allow the matching between // the size of Ins and InVals. This only happens when on varg functions if (!OutChains.empty()) { OutChains.push_back(Chain); @@ -1183,7 +1410,7 @@ MipsTargetLowering::LowerReturn(SDValue Chain, // Analize return values. CCInfo.AnalyzeReturn(Outs, RetCC_Mips); - // If this is the first return lowered for this function, add + // If this is the first return lowered for this function, add // the regs to the liveout set for the function. if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { for (unsigned i = 0; i != RVLocs.size(); ++i) @@ -1198,7 +1425,7 @@ MipsTargetLowering::LowerReturn(SDValue Chain, CCValAssign &VA = RVLocs[i]; assert(VA.isRegLoc() && "Can only return in registers!"); - Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag); // guarantee that all emitted copies are @@ -1215,7 +1442,7 @@ MipsTargetLowering::LowerReturn(SDValue Chain, MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); unsigned Reg = MipsFI->getSRetReturnReg(); - if (!Reg) + if (!Reg) llvm_unreachable("sret virtual register not created in the entry block"); SDValue Val = DAG.getCopyFromReg(Chain, dl, Reg, getPointerTy()); @@ -1225,10 +1452,10 @@ MipsTargetLowering::LowerReturn(SDValue Chain, // Return on Mips is always a "jr $ra" if (Flag.getNode()) - return DAG.getNode(MipsISD::Ret, dl, MVT::Other, + return DAG.getNode(MipsISD::Ret, dl, MVT::Other, Chain, DAG.getRegister(Mips::RA, MVT::i32), Flag); else // Return Void - return DAG.getNode(MipsISD::Ret, dl, MVT::Other, + return DAG.getNode(MipsISD::Ret, dl, MVT::Other, Chain, DAG.getRegister(Mips::RA, MVT::i32)); } @@ -1239,21 +1466,21 @@ MipsTargetLowering::LowerReturn(SDValue Chain, /// getConstraintType - Given a constraint letter, return the type of /// constraint it is for this target. MipsTargetLowering::ConstraintType MipsTargetLowering:: -getConstraintType(const std::string &Constraint) const +getConstraintType(const std::string &Constraint) const { - // Mips specific constrainy + // Mips specific constrainy // GCC config/mips/constraints.md // - // 'd' : An address register. Equivalent to r - // unless generating MIPS16 code. - // 'y' : Equivalent to r; retained for - // backwards compatibility. - // 'f' : Floating Point registers. + // 'd' : An address register. Equivalent to r + // unless generating MIPS16 code. + // 'y' : Equivalent to r; retained for + // backwards compatibility. + // 'f' : Floating Point registers. if (Constraint.size() == 1) { switch (Constraint[0]) { default : break; - case 'd': - case 'y': + case 'd': + case 'y': case 'f': return C_RegisterClass; break; @@ -1262,6 +1489,37 @@ getConstraintType(const std::string &Constraint) const return TargetLowering::getConstraintType(Constraint); } +/// Examine constraint type and operand type and determine a weight value. +/// This object must already have been set up with the operand type +/// and the current alternative constraint selected. +TargetLowering::ConstraintWeight +MipsTargetLowering::getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const { + ConstraintWeight weight = CW_Invalid; + Value *CallOperandVal = info.CallOperandVal; + // If we don't have a value, we can't do a match, + // but allow it at the lowest weight. + if (CallOperandVal == NULL) + return CW_Default; + const Type *type = CallOperandVal->getType(); + // Look at the constraint type. + switch (*constraint) { + default: + weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); + break; + case 'd': + case 'y': + if (type->isIntegerTy()) + weight = CW_Register; + break; + case 'f': + if (type->isFloatTy()) + weight = CW_Register; + break; + } + return weight; +} + /// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"), /// return a list of registers that can be used to satisfy the constraint. /// This should only be used for C_RegisterClass constraints. @@ -1275,7 +1533,7 @@ getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const case 'f': if (VT == MVT::f32) return std::make_pair(0U, Mips::FGR32RegisterClass); - if (VT == MVT::f64) + if (VT == MVT::f64) if ((!Subtarget->isSingleFloat()) && (!Subtarget->isFP64bit())) return std::make_pair(0U, Mips::AFGR64RegisterClass); } @@ -1293,15 +1551,15 @@ getRegClassForInlineAsmConstraint(const std::string &Constraint, if (Constraint.size() != 1) return std::vector<unsigned>(); - switch (Constraint[0]) { + switch (Constraint[0]) { default : break; case 'r': // GCC Mips Constraint Letters - case 'd': - case 'y': - return make_vector<unsigned>(Mips::T0, Mips::T1, Mips::T2, Mips::T3, - Mips::T4, Mips::T5, Mips::T6, Mips::T7, Mips::S0, Mips::S1, - Mips::S2, Mips::S3, Mips::S4, Mips::S5, Mips::S6, Mips::S7, + case 'd': + case 'y': + return make_vector<unsigned>(Mips::T0, Mips::T1, Mips::T2, Mips::T3, + Mips::T4, Mips::T5, Mips::T6, Mips::T7, Mips::S0, Mips::S1, + Mips::S2, Mips::S3, Mips::S4, Mips::S5, Mips::S6, Mips::S7, Mips::T8, 0); case 'f': @@ -1313,15 +1571,15 @@ getRegClassForInlineAsmConstraint(const std::string &Constraint, Mips::F25, Mips::F26, Mips::F27, Mips::F28, Mips::F29, Mips::F30, Mips::F31, 0); else - return make_vector<unsigned>(Mips::F2, Mips::F4, Mips::F6, Mips::F8, - Mips::F10, Mips::F20, Mips::F22, Mips::F24, Mips::F26, + return make_vector<unsigned>(Mips::F2, Mips::F4, Mips::F6, Mips::F8, + Mips::F10, Mips::F20, Mips::F22, Mips::F24, Mips::F26, Mips::F28, Mips::F30, 0); } - if (VT == MVT::f64) + if (VT == MVT::f64) if ((!Subtarget->isSingleFloat()) && (!Subtarget->isFP64bit())) - return make_vector<unsigned>(Mips::D1, Mips::D2, Mips::D3, Mips::D4, - Mips::D5, Mips::D10, Mips::D11, Mips::D12, Mips::D13, + return make_vector<unsigned>(Mips::D1, Mips::D2, Mips::D3, Mips::D4, + Mips::D5, Mips::D10, Mips::D11, Mips::D12, Mips::D13, Mips::D14, Mips::D15, 0); } return std::vector<unsigned>(); @@ -1336,5 +1594,7 @@ MipsTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { bool MipsTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { if (VT != MVT::f32 && VT != MVT::f64) return false; + if (Imm.isNegZero()) + return false; return Imm.isZero(); } |