X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FMips%2FMipsISelLowering.cpp;h=4c425616094febba0bf0931f65cf8c87cd328696;hb=cf0cd8005c81853ddea3ce26b71491c48dc4984e;hp=93e7a23ac47584d0089ef33890ac32a1324aa77c;hpb=053546c31e4752e3d76e1f0915ddd6c8a3280351;p=oota-llvm.git diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 93e7a23ac47..4c425616094 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -103,7 +103,6 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::SELECT, MVT::i32, Custom); setOperationAction(ISD::BRCOND, MVT::Other, Custom); setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom); - setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); setOperationAction(ISD::VASTART, MVT::Other, Custom); setOperationAction(ISD::SDIV, MVT::i32, Expand); @@ -128,8 +127,8 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); - setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); - setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); + setOperationAction(ISD::FCOPYSIGN, MVT::f32, Custom); + setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom); setOperationAction(ISD::FSIN, MVT::f32, Expand); setOperationAction(ISD::FSIN, MVT::f64, Expand); setOperationAction(ISD::FCOS, MVT::f32, Expand); @@ -142,8 +141,9 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::FLOG10, MVT::f32, Expand); setOperationAction(ISD::FEXP, MVT::f32, Expand); - setOperationAction(ISD::EH_LABEL, MVT::Other, Expand); - + setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand); + setOperationAction(ISD::EHSELECTION, MVT::i32, Expand); + setOperationAction(ISD::VAARG, MVT::Other, Expand); setOperationAction(ISD::VACOPY, MVT::Other, Expand); setOperationAction(ISD::VAEND, MVT::Other, Expand); @@ -177,6 +177,9 @@ MipsTargetLowering(MipsTargetMachine &TM) setStackPointerRegisterToSaveRestore(Mips::SP); computeRegisterProperties(); + + setExceptionPointerRegister(Mips::A0); + setExceptionSelectorRegister(Mips::A1); } MVT::SimpleValueType MipsTargetLowering::getSetCCResultType(EVT VT) const { @@ -508,13 +511,13 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const case ISD::BRCOND: return LowerBRCOND(Op, DAG); case ISD::ConstantPool: return LowerConstantPool(Op, DAG); case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG); - case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG); case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); case ISD::JumpTable: return LowerJumpTable(Op, DAG); case ISD::SELECT: return LowerSELECT(Op, DAG); case ISD::VASTART: return LowerVASTART(Op, DAG); + case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG); } return SDValue(); } @@ -655,40 +658,6 @@ MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, //===----------------------------------------------------------------------===// // Misc Lower Operation implementation //===----------------------------------------------------------------------===// - -SDValue MipsTargetLowering:: -LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const -{ - if (!Subtarget->isMips1()) - return Op; - - MachineFunction &MF = DAG.getMachineFunction(); - unsigned CCReg = AddLiveIn(MF, Mips::FCR31, Mips::CCRRegisterClass); - - SDValue Chain = DAG.getEntryNode(); - DebugLoc dl = Op.getDebugLoc(); - SDValue Src = Op.getOperand(0); - - // Set the condition register - SDValue CondReg = DAG.getCopyFromReg(Chain, dl, CCReg, MVT::i32); - CondReg = DAG.getCopyToReg(Chain, dl, Mips::AT, CondReg); - CondReg = DAG.getCopyFromReg(CondReg, dl, Mips::AT, MVT::i32); - - SDValue Cst = DAG.getConstant(3, MVT::i32); - SDValue Or = DAG.getNode(ISD::OR, dl, MVT::i32, CondReg, Cst); - Cst = DAG.getConstant(2, MVT::i32); - SDValue Xor = DAG.getNode(ISD::XOR, dl, MVT::i32, Or, Cst); - - SDValue InFlag(0, 0); - CondReg = DAG.getCopyToReg(Chain, dl, Mips::FCR31, Xor, InFlag); - - // 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::BITCAST, dl, MVT::i32, Trunc); - return BitCvt; -} - SDValue MipsTargetLowering:: LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const { @@ -714,10 +683,13 @@ LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const // must be placed in the stack pointer register. Chain = DAG.getCopyToReg(StackPointer.getValue(1), dl, Mips::SP, Sub, SDValue()); + // Retrieve updated $sp. There is a glue input to prevent instructions that + // clobber $sp from being inserted between copytoreg and copyfromreg. SDValue NewSP = DAG.getCopyFromReg(Chain, dl, Mips::SP, MVT::i32, Chain.getValue(1)); - // Align the allocated space. + // The stack space reserved by alloca is located right above the argument + // area. It is aligned on a boundary that is a multiple of StackAlignment. MachineFunction &MF = DAG.getMachineFunction(); MipsFunctionInfo *MipsFI = MF.getInfo(); unsigned SPOffset = (MipsFI->getMaxCallFrameSize() + StackAlignment - 1) / @@ -940,6 +912,60 @@ SDValue MipsTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { false, false, 0); } +static SDValue LowerFCOPYSIGN32(SDValue Op, SelectionDAG &DAG) { + // FIXME: Use ext/ins instructions if target architecture is Mips32r2. + DebugLoc dl = Op.getDebugLoc(); + SDValue Op0 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Op.getOperand(0)); + SDValue Op1 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Op.getOperand(1)); + SDValue And0 = DAG.getNode(ISD::AND, dl, MVT::i32, Op0, + DAG.getConstant(0x7fffffff, MVT::i32)); + SDValue And1 = DAG.getNode(ISD::AND, dl, MVT::i32, Op1, + DAG.getConstant(0x80000000, MVT::i32)); + SDValue Result = DAG.getNode(ISD::OR, dl, MVT::i32, And0, And1); + return DAG.getNode(ISD::BITCAST, dl, MVT::f32, Result); +} + +static SDValue LowerFCOPYSIGN64(SDValue Op, SelectionDAG &DAG, bool isLittle) { + // FIXME: + // Use ext/ins instructions if target architecture is Mips32r2. + // Eliminate redundant mfc1 and mtc1 instructions. + unsigned LoIdx = 0, HiIdx = 1; + + if (!isLittle) + std::swap(LoIdx, HiIdx); + + DebugLoc dl = Op.getDebugLoc(); + SDValue Word0 = DAG.getNode(MipsISD::ExtractElementF64, dl, MVT::i32, + Op.getOperand(0), + DAG.getConstant(LoIdx, MVT::i32)); + SDValue Hi0 = DAG.getNode(MipsISD::ExtractElementF64, dl, MVT::i32, + Op.getOperand(0), DAG.getConstant(HiIdx, MVT::i32)); + SDValue Hi1 = DAG.getNode(MipsISD::ExtractElementF64, dl, MVT::i32, + Op.getOperand(1), DAG.getConstant(HiIdx, MVT::i32)); + SDValue And0 = DAG.getNode(ISD::AND, dl, MVT::i32, Hi0, + DAG.getConstant(0x7fffffff, MVT::i32)); + SDValue And1 = DAG.getNode(ISD::AND, dl, MVT::i32, Hi1, + DAG.getConstant(0x80000000, MVT::i32)); + SDValue Word1 = DAG.getNode(ISD::OR, dl, MVT::i32, And0, And1); + + if (!isLittle) + std::swap(Word0, Word1); + + return DAG.getNode(MipsISD::BuildPairF64, dl, MVT::f64, Word0, Word1); +} + +SDValue MipsTargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) + const { + EVT Ty = Op.getValueType(); + + assert(Ty == MVT::f32 || Ty == MVT::f64); + + if (Ty == MVT::f32) + return LowerFCOPYSIGN32(Op, DAG); + else + return LowerFCOPYSIGN64(Op, DAG, Subtarget->isLittle()); +} + //===----------------------------------------------------------------------===// // Calling Convention Implementation //===----------------------------------------------------------------------===// @@ -1068,7 +1094,8 @@ WriteByValArg(SDValue& Chain, DebugLoc dl, SmallVector, 16>& RegsToPass, SmallVector& MemOpChains, int& LastFI, MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg, - const CCValAssign &VA, const ISD::ArgFlagsTy& Flags, MVT PtrType) { + const CCValAssign &VA, const ISD::ArgFlagsTy& Flags, + MVT PtrType) { unsigned FirstWord = VA.getLocMemOffset() / 4; unsigned NumWords = (Flags.getByValSize() + 3) / 4; unsigned LastWord = FirstWord + NumWords; @@ -1146,8 +1173,10 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, MipsFI->setHasCall(); - // Create GP frame object if this is the first call. - // SPOffset will be updated after call frame size is known. + // If this is the first call, create a stack frame object that points to + // a location to which .cprestore saves $gp. The offset of this frame object + // is set to 0, since we know nothing about the size of the argument area at + // this point. if (IsPIC && !MipsFI->getGPFI()) MipsFI->setGPFI(MFI->CreateFixedObject(4, 0, true)); @@ -1212,9 +1241,6 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, } // 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 - // if O32 ABI is used. For EABI the first address is zero. LastFI = MFI->CreateFixedObject(VA.getValVT().getSizeInBits()/8, VA.getLocMemOffset(), true); SDValue PtrOff = DAG.getFrameIndex(LastFI, getPointerTy()); @@ -1316,23 +1342,20 @@ 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 - // emitted CALL's to restore GP. - if (IsPIC) { - // Function can have an arbitrary number of calls, so - // hold the LastArgStackLoc with the biggest offset. - int MaxCallFrameSize = MipsFI->getMaxCallFrameSize(); - unsigned NextStackOffset = CCInfo.getNextStackOffset(); + // Function can have an arbitrary number of calls, so + // hold the LastArgStackLoc with the biggest offset. + unsigned MaxCallFrameSize = MipsFI->getMaxCallFrameSize(); + unsigned NextStackOffset = CCInfo.getNextStackOffset(); - // For O32, a minimum of four words (16 bytes) of argument space is - // allocated. - if (Subtarget->isABI_O32()) - NextStackOffset = std::max(NextStackOffset, (unsigned)16); + // For O32, a minimum of four words (16 bytes) of argument space is + // allocated. + if (Subtarget->isABI_O32()) + NextStackOffset = std::max(NextStackOffset, (unsigned)16); - if (MaxCallFrameSize < (int)NextStackOffset) { - MipsFI->setMaxCallFrameSize(NextStackOffset); + if (MaxCallFrameSize < NextStackOffset) { + MipsFI->setMaxCallFrameSize(NextStackOffset); + if (IsPIC) { // $gp restore slot must be aligned. unsigned StackAlignment = TFL->getStackAlignment(); NextStackOffset = (NextStackOffset + StackAlignment - 1) / @@ -1424,7 +1447,6 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl &InVals) const { - MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo(); @@ -1524,12 +1546,6 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, } // 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 - // used instead of a direct negative address (which is recorded to - // be used on emitPrologue) to avoid mis-calc of the first stack - // offset on PEI::calculateFrameObjectOffsets. LastFI = MFI->CreateFixedObject(VA.getValVT().getSizeInBits()/8, VA.getLocMemOffset(), true); @@ -1554,9 +1570,6 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, 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. if (isVarArg && Subtarget->isABI_O32()) { // Record the frame index of the first variable argument // which is a value necessary to VASTART. @@ -1565,8 +1578,10 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, "NextStackOffset must be aligned to 4-byte boundaries."); LastFI = MFI->CreateFixedObject(4, NextStackOffset, true); MipsFI->setVarArgsFrameIndex(LastFI); - - // Copy variable arguments passed in registers to stack. + + // If NextStackOffset is smaller than o32's 16-byte reserved argument area, + // copy the integer registers that have not been used for argument passing + // to the caller's stack frame. for (; NextStackOffset < 16; NextStackOffset += 4) { TargetRegisterClass *RC = Mips::CPURegsRegisterClass; unsigned Idx = NextStackOffset / 4;