diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/Mips/Mips64InstrInfo.td | 4 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsCCState.cpp | 12 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsCCState.h | 11 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsCallingConv.td | 36 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsISelLowering.cpp | 123 |
5 files changed, 143 insertions, 43 deletions
diff --git a/llvm/lib/Target/Mips/Mips64InstrInfo.td b/llvm/lib/Target/Mips/Mips64InstrInfo.td index 499253b1179..4e2dcd80b2d 100644 --- a/llvm/lib/Target/Mips/Mips64InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips64InstrInfo.td @@ -419,6 +419,10 @@ defm : SetgePats<GPR64, SLT64, SLTu64>; defm : SetgeImmPats<GPR64, SLTi64, SLTiu64>; // truncate +def : MipsPat<(trunc (assertsext GPR64:$src)), + (EXTRACT_SUBREG GPR64:$src, sub_32)>; +def : MipsPat<(trunc (assertzext GPR64:$src)), + (EXTRACT_SUBREG GPR64:$src, sub_32)>; def : MipsPat<(i32 (trunc GPR64:$src)), (SLL (EXTRACT_SUBREG GPR64:$src, sub_32), 0)>; diff --git a/llvm/lib/Target/Mips/MipsCCState.cpp b/llvm/lib/Target/Mips/MipsCCState.cpp index 6aac2203efb..f30f3ca8431 100644 --- a/llvm/lib/Target/Mips/MipsCCState.cpp +++ b/llvm/lib/Target/Mips/MipsCCState.cpp @@ -80,9 +80,11 @@ MipsCCState::getSpecialCallingConvForCallee(const SDNode *Callee, void MipsCCState::PreAnalyzeCallResultForF128( const SmallVectorImpl<ISD::InputArg> &Ins, const TargetLowering::CallLoweringInfo &CLI) { - for (unsigned i = 0; i < Ins.size(); ++i) + for (unsigned i = 0; i < Ins.size(); ++i) { OriginalArgWasF128.push_back( originalTypeIsF128(CLI.RetTy, CLI.Callee.getNode())); + OriginalArgWasFloat.push_back(CLI.RetTy->isFloatingPointTy()); + } } /// Identify lowered values that originated from f128 arguments and record @@ -90,9 +92,12 @@ void MipsCCState::PreAnalyzeCallResultForF128( void MipsCCState::PreAnalyzeReturnForF128( const SmallVectorImpl<ISD::OutputArg> &Outs) { const MachineFunction &MF = getMachineFunction(); - for (unsigned i = 0; i < Outs.size(); ++i) + for (unsigned i = 0; i < Outs.size(); ++i) { OriginalArgWasF128.push_back( originalTypeIsF128(MF.getFunction()->getReturnType(), nullptr)); + OriginalArgWasFloat.push_back( + MF.getFunction()->getReturnType()->isFloatingPointTy()); + } } /// Identify lowered values that originated from f128 arguments and record @@ -104,6 +109,8 @@ void MipsCCState::PreAnalyzeCallOperands( for (unsigned i = 0; i < Outs.size(); ++i) { OriginalArgWasF128.push_back( originalTypeIsF128(FuncArgs[Outs[i].OrigArgIndex].Ty, CallNode)); + OriginalArgWasFloat.push_back( + FuncArgs[Outs[i].OrigArgIndex].Ty->isFloatingPointTy()); CallOperandIsFixed.push_back(Outs[i].IsFixed); } } @@ -129,5 +136,6 @@ void MipsCCState::PreAnalyzeFormalArgumentsForF128( OriginalArgWasF128.push_back( originalTypeIsF128(FuncArg->getType(), nullptr)); + OriginalArgWasFloat.push_back(FuncArg->getType()->isFloatingPointTy()); } } diff --git a/llvm/lib/Target/Mips/MipsCCState.h b/llvm/lib/Target/Mips/MipsCCState.h index b5b9dbccda7..cc4531d8797 100644 --- a/llvm/lib/Target/Mips/MipsCCState.h +++ b/llvm/lib/Target/Mips/MipsCCState.h @@ -52,6 +52,9 @@ private: /// Records whether the value has been lowered from an f128. SmallVector<bool, 4> OriginalArgWasF128; + /// Records whether the value has been lowered from float. + SmallVector<bool, 4> OriginalArgWasFloat; + /// Records whether the value was a fixed argument. /// See ISD::OutputArg::IsFixed, SmallVector<bool, 4> CallOperandIsFixed; @@ -74,6 +77,7 @@ public: PreAnalyzeCallOperands(Outs, FuncArgs, CallNode); CCState::AnalyzeCallOperands(Outs, Fn); OriginalArgWasF128.clear(); + OriginalArgWasFloat.clear(); CallOperandIsFixed.clear(); } @@ -90,6 +94,7 @@ public: CCAssignFn Fn) { PreAnalyzeFormalArgumentsForF128(Ins); CCState::AnalyzeFormalArguments(Ins, Fn); + OriginalArgWasFloat.clear(); OriginalArgWasF128.clear(); } @@ -98,6 +103,7 @@ public: const TargetLowering::CallLoweringInfo &CLI) { PreAnalyzeCallResultForF128(Ins, CLI); CCState::AnalyzeCallResult(Ins, Fn); + OriginalArgWasFloat.clear(); OriginalArgWasF128.clear(); } @@ -105,6 +111,7 @@ public: CCAssignFn Fn) { PreAnalyzeReturnForF128(Outs); CCState::AnalyzeReturn(Outs, Fn); + OriginalArgWasFloat.clear(); OriginalArgWasF128.clear(); } @@ -112,11 +119,15 @@ public: CCAssignFn Fn) { PreAnalyzeReturnForF128(ArgsFlags); bool Return = CCState::CheckReturn(ArgsFlags, Fn); + OriginalArgWasFloat.clear(); OriginalArgWasF128.clear(); return Return; } bool WasOriginalArgF128(unsigned ValNo) { return OriginalArgWasF128[ValNo]; } + bool WasOriginalArgFloat(unsigned ValNo) { + return OriginalArgWasFloat[ValNo]; + } bool IsCallOperandFixed(unsigned ValNo) { return CallOperandIsFixed[ValNo]; } SpecialCallingConvType getSpecialCallingConv() { return SpecialCallingConv; } }; diff --git a/llvm/lib/Target/Mips/MipsCallingConv.td b/llvm/lib/Target/Mips/MipsCallingConv.td index 4d64da2b3e1..c6706a8e8fb 100644 --- a/llvm/lib/Target/Mips/MipsCallingConv.td +++ b/llvm/lib/Target/Mips/MipsCallingConv.td @@ -78,16 +78,28 @@ def CC_MipsO32_FP : CallingConv<[ // Mips N32/64 Calling Convention //===----------------------------------------------------------------------===// +def CC_MipsN_SoftFloat : CallingConv<[ + CCAssignToRegWithShadow<[A0, A1, A2, A3, + T0, T1, T2, T3], + [D12_64, D13_64, D14_64, D15_64, + D16_64, D17_64, D18_64, D19_64]>, + CCAssignToStack<4, 8> +]>; + def CC_MipsN : CallingConv<[ - // Promote i8/i16 arguments to i32. - CCIfType<[i8, i16], CCPromoteToType<i32>>, + CCIfType<[i8, i16, i32], + CCIfSubtargetNot<"isLittle()", + CCIfInReg<CCPromoteToUpperBitsInType<i64>>>>, - // Integer arguments are passed in integer registers. - CCIfType<[i32], CCAssignToRegWithShadow<[A0, A1, A2, A3, - T0, T1, T2, T3], - [F12, F13, F14, F15, - F16, F17, F18, F19]>>, + // All integers (except soft-float integers) are promoted to 64-bit. + CCIfType<[i8, i16, i32], + CCIf<"!static_cast<MipsCCState *>(&State)->WasOriginalArgFloat(ValNo)", + CCPromoteToType<i64>>>, + + // The only i32's we have left are soft-float arguments. + CCIfSubtarget<"abiUsesSoftFloat()", CCIfType<[i32], CCDelegateTo<CC_MipsN_SoftFloat>>>, + // Integer arguments are passed in integer registers. CCIfType<[i64], CCAssignToRegWithShadow<[A0_64, A1_64, A2_64, A3_64, T0_64, T1_64, T2_64, T3_64], [D12_64, D13_64, D14_64, D15_64, @@ -106,23 +118,23 @@ def CC_MipsN : CallingConv<[ T0_64, T1_64, T2_64, T3_64]>>, // All stack parameter slots become 64-bit doublewords and are 8-byte aligned. - CCIfType<[i32, f32], CCAssignToStack<4, 8>>, + CCIfType<[f32], CCAssignToStack<4, 8>>, CCIfType<[i64, f64], CCAssignToStack<8, 8>> ]>; // N32/64 variable arguments. // All arguments are passed in integer registers. def CC_MipsN_VarArg : CallingConv<[ - // Promote i8/i16 arguments to i32. - CCIfType<[i8, i16], CCPromoteToType<i32>>, + // All integers are promoted to 64-bit. + CCIfType<[i8, i16, i32], CCPromoteToType<i64>>, - CCIfType<[i32, f32], CCAssignToReg<[A0, A1, A2, A3, T0, T1, T2, T3]>>, + CCIfType<[f32], CCAssignToReg<[A0, A1, A2, A3, T0, T1, T2, T3]>>, CCIfType<[i64, f64], CCAssignToReg<[A0_64, A1_64, A2_64, A3_64, T0_64, T1_64, T2_64, T3_64]>>, // All stack parameter slots become 64-bit doublewords and are 8-byte aligned. - CCIfType<[i32, f32], CCAssignToStack<4, 8>>, + CCIfType<[f32], CCAssignToStack<4, 8>>, CCIfType<[i64, f64], CCAssignToStack<8, 8>> ]>; diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index 05e0746b8f7..99d26010038 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -2522,6 +2522,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, CCValAssign &VA = ArgLocs[i]; MVT ValVT = VA.getValVT(), LocVT = VA.getLocVT(); ISD::ArgFlagsTy Flags = Outs[i].Flags; + bool UseUpperBits = false; // ByVal Arg. if (Flags.isByVal()) { @@ -2543,7 +2544,8 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // Promote the value if needed. switch (VA.getLocInfo()) { - default: llvm_unreachable("Unknown loc info!"); + default: + llvm_unreachable("Unknown loc info!"); case CCValAssign::Full: if (VA.isRegLoc()) { if ((ValVT == MVT::f32 && LocVT == MVT::i32) || @@ -2568,17 +2570,34 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, case CCValAssign::BCvt: Arg = DAG.getNode(ISD::BITCAST, DL, LocVT, Arg); break; + case CCValAssign::SExtUpper: + UseUpperBits = true; + // Fallthrough case CCValAssign::SExt: Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, LocVT, Arg); break; + case CCValAssign::ZExtUpper: + UseUpperBits = true; + // Fallthrough case CCValAssign::ZExt: Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, LocVT, Arg); break; + case CCValAssign::AExtUpper: + UseUpperBits = true; + // Fallthrough case CCValAssign::AExt: Arg = DAG.getNode(ISD::ANY_EXTEND, DL, LocVT, Arg); break; } + if (UseUpperBits) { + unsigned ValSizeInBits = Outs[i].ArgVT.getSizeInBits(); + unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); + Arg = DAG.getNode( + ISD::SHL, DL, VA.getLocVT(), Arg, + DAG.getConstant(LocSizeInBits - ValSizeInBits, VA.getLocVT())); + } + // Arguments that can be passed on register must be kept at // RegsToPass vector if (VA.isRegLoc()) { @@ -2741,6 +2760,60 @@ SDValue MipsTargetLowering::LowerCallResult( return Chain; } +static SDValue UnpackFromArgumentSlot(SDValue Val, const CCValAssign &VA, + EVT ArgVT, SDLoc DL, SelectionDAG &DAG) { + MVT LocVT = VA.getLocVT(); + EVT ValVT = VA.getValVT(); + + // Shift into the upper bits if necessary. + switch (VA.getLocInfo()) { + default: + break; + case CCValAssign::AExtUpper: + case CCValAssign::SExtUpper: + case CCValAssign::ZExtUpper: { + unsigned ValSizeInBits = ArgVT.getSizeInBits(); + unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); + unsigned Opcode = + VA.getLocInfo() == CCValAssign::ZExtUpper ? ISD::SRL : ISD::SRA; + Val = DAG.getNode( + Opcode, DL, VA.getLocVT(), Val, + DAG.getConstant(LocSizeInBits - ValSizeInBits, VA.getLocVT())); + break; + } + } + + // If this is an value smaller than the argument slot size (32-bit for O32, + // 64-bit for N32/N64), it has been promoted in some way to the argument slot + // size. Extract the value and insert any appropriate assertions regarding + // sign/zero extension. + switch (VA.getLocInfo()) { + default: + llvm_unreachable("Unknown loc info!"); + case CCValAssign::Full: + break; + case CCValAssign::AExtUpper: + case CCValAssign::AExt: + Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val); + break; + case CCValAssign::SExtUpper: + case CCValAssign::SExt: + Val = DAG.getNode(ISD::AssertSext, DL, LocVT, Val, DAG.getValueType(ValVT)); + Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val); + break; + case CCValAssign::ZExtUpper: + case CCValAssign::ZExt: + Val = DAG.getNode(ISD::AssertZext, DL, LocVT, Val, DAG.getValueType(ValVT)); + Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val); + break; + case CCValAssign::BCvt: + Val = DAG.getNode(ISD::BITCAST, DL, ValVT, Val); + break; + } + + return Val; +} + //===----------------------------------------------------------------------===// // Formal Arguments Calling Convention Implementation //===----------------------------------------------------------------------===// @@ -2812,28 +2885,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, unsigned Reg = addLiveIn(DAG.getMachineFunction(), ArgReg, 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 - // truncate to the right size. - switch (VA.getLocInfo()) { - default: - llvm_unreachable("Unknown loc info!"); - case CCValAssign::Full: - break; - case CCValAssign::SExt: - ArgValue = DAG.getNode(ISD::AssertSext, DL, RegVT, ArgValue, - DAG.getValueType(ValVT)); - ArgValue = DAG.getNode(ISD::TRUNCATE, DL, ValVT, ArgValue); - break; - case CCValAssign::ZExt: - ArgValue = DAG.getNode(ISD::AssertZext, DL, RegVT, ArgValue, - DAG.getValueType(ValVT)); - ArgValue = DAG.getNode(ISD::TRUNCATE, DL, ValVT, ArgValue); - break; - case CCValAssign::BCvt: - ArgValue = DAG.getNode(ISD::BITCAST, DL, ValVT, ArgValue); - break; - } + ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG); // Handle floating point arguments passed in integer registers and // long double arguments passed in floating point registers. @@ -2854,21 +2906,34 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, InVals.push_back(ArgValue); } else { // VA.isRegLoc() + MVT LocVT = VA.getLocVT(); + + if (Subtarget.isABI_O32()) { + // We ought to be able to use LocVT directly but O32 sets it to i32 + // when allocating floating point values to integer registers. + // This shouldn't influence how we load the value into registers unless + // we are targetting softfloat. + if (VA.getValVT().isFloatingPoint() && !Subtarget.abiUsesSoftFloat()) + LocVT = VA.getValVT(); + } // sanity check assert(VA.isMemLoc()); // The stack pointer offset is relative to the caller stack frame. - int FI = MFI->CreateFixedObject(ValVT.getSizeInBits()/8, + int FI = MFI->CreateFixedObject(LocVT.getSizeInBits() / 8, VA.getLocMemOffset(), true); // Create load nodes to retrieve arguments from the stack SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); - SDValue Load = DAG.getLoad(ValVT, DL, Chain, FIN, - MachinePointerInfo::getFixedStack(FI), - false, false, false, 0); - InVals.push_back(Load); - OutChains.push_back(Load.getValue(1)); + SDValue ArgValue = DAG.getLoad(LocVT, DL, Chain, FIN, + MachinePointerInfo::getFixedStack(FI), + false, false, false, 0); + OutChains.push_back(ArgValue.getValue(1)); + + ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG); + + InVals.push_back(ArgValue); } } |