Index: llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h +++ llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h @@ -281,7 +281,7 @@ /// \return The number of \p VAs that have been assigned after the first /// one, and which should therefore be skipped from further /// processing. - virtual unsigned assignCustomValue(const ArgInfo &Arg, + virtual unsigned assignCustomValue(ArgInfo &Arg, ArrayRef VAs) { // This is not a pure virtual method because not all targets need to worry // about custom values. Index: llvm/lib/Target/ARM/ARMCallLowering.cpp =================================================================== --- llvm/lib/Target/ARM/ARMCallLowering.cpp +++ llvm/lib/Target/ARM/ARMCallLowering.cpp @@ -129,7 +129,7 @@ MIRBuilder.buildStore(ExtReg, Addr, *MMO); } - unsigned assignCustomValue(const CallLowering::ArgInfo &Arg, + unsigned assignCustomValue(CallLowering::ArgInfo &Arg, ArrayRef VAs) override { assert(Arg.Regs.size() == 1 && "Can't handle multple regs yet"); @@ -297,7 +297,7 @@ } } - unsigned assignCustomValue(const ARMCallLowering::ArgInfo &Arg, + unsigned assignCustomValue(ARMCallLowering::ArgInfo &Arg, ArrayRef VAs) override { assert(Arg.Regs.size() == 1 && "Can't handle multple regs yet"); Index: llvm/lib/Target/Mips/MipsCCState.h =================================================================== --- llvm/lib/Target/Mips/MipsCCState.h +++ llvm/lib/Target/Mips/MipsCCState.h @@ -26,6 +26,21 @@ getSpecialCallingConvForCallee(const SDNode *Callee, const MipsSubtarget &Subtarget); + /// This function returns true if CallSym is a long double emulation routine. + /// + /// FIXME: Changing the ABI based on the callee name is unsound. The lib func + /// address could be captured. + static bool isF128SoftLibCall(const char *CallSym); + + static bool originalTypeIsF128(const Type *Ty, const char *Func); + static bool originalEVTTypeIsVectorFloat(EVT Ty); + static bool originalTypeIsVectorFloat(const Type *Ty); + + void PreAnalyzeCallOperand(const Type *ArgTy, bool IsFixed, const char *Func); + + void PreAnalyzeFormalArgument(const Type *ArgTy, ISD::ArgFlagsTy Flags); + void PreAnalyzeReturnValue(EVT ArgVT); + private: /// Identify lowered values that originated from f128 arguments and record /// this for use by RetCC_MipsN. @@ -85,17 +100,23 @@ SpecialCallingConvType SpecialCC = NoSpecialCallingConv) : CCState(CC, isVarArg, MF, locs, C), SpecialCallingConv(SpecialCC) {} + void PreAnalyzeCallOperands( + const SmallVectorImpl &Outs, CCAssignFn Fn, + std::vector &FuncArgs, const char *Func) { + OriginalArgWasF128.clear(); + OriginalArgWasFloat.clear(); + OriginalArgWasFloatVector.clear(); + CallOperandIsFixed.clear(); + PreAnalyzeCallOperands(Outs, FuncArgs, Func); + } + void AnalyzeCallOperands(const SmallVectorImpl &Outs, CCAssignFn Fn, std::vector &FuncArgs, const char *Func) { - PreAnalyzeCallOperands(Outs, FuncArgs, Func); + PreAnalyzeCallOperands(Outs, Fn, FuncArgs, Func); CCState::AnalyzeCallOperands(Outs, Fn); - OriginalArgWasF128.clear(); - OriginalArgWasFloat.clear(); - OriginalArgWasFloatVector.clear(); - CallOperandIsFixed.clear(); } // The AnalyzeCallOperands in the base class is not usable since we must @@ -107,34 +128,56 @@ SmallVectorImpl &Flags, CCAssignFn Fn) = delete; + void PreAnalyzeFormalArguments(const SmallVectorImpl &Ins, + CCAssignFn Fn) { + OriginalArgWasFloat.clear(); + OriginalArgWasF128.clear(); + OriginalArgWasFloatVector.clear(); + PreAnalyzeFormalArgumentsForF128(Ins); + } + void AnalyzeFormalArguments(const SmallVectorImpl &Ins, CCAssignFn Fn) { - PreAnalyzeFormalArgumentsForF128(Ins); + PreAnalyzeFormalArguments(Ins, Fn); CCState::AnalyzeFormalArguments(Ins, Fn); + } + + void PreAnalyzeCallResult(const Type *RetTy, const char *Func) { + OriginalArgWasF128.push_back(originalTypeIsF128(RetTy, Func)); + OriginalArgWasFloat.push_back(RetTy->isFloatingPointTy()); + OriginalRetWasFloatVector.push_back(originalTypeIsVectorFloat(RetTy)); + } + + void PreAnalyzeCallResult(const SmallVectorImpl &Ins, + CCAssignFn Fn, const Type *RetTy, + const char *Func) { OriginalArgWasFloat.clear(); OriginalArgWasF128.clear(); OriginalArgWasFloatVector.clear(); + PreAnalyzeCallResultForF128(Ins, RetTy, Func); + PreAnalyzeCallResultForVectorFloat(Ins, RetTy); } void AnalyzeCallResult(const SmallVectorImpl &Ins, CCAssignFn Fn, const Type *RetTy, const char *Func) { - PreAnalyzeCallResultForF128(Ins, RetTy, Func); - PreAnalyzeCallResultForVectorFloat(Ins, RetTy); + PreAnalyzeCallResult(Ins, Fn, RetTy, Func); CCState::AnalyzeCallResult(Ins, Fn); + } + + void PreAnalyzeReturn(const SmallVectorImpl &Outs, + CCAssignFn Fn) { OriginalArgWasFloat.clear(); OriginalArgWasF128.clear(); OriginalArgWasFloatVector.clear(); + PreAnalyzeReturnForF128(Outs); + PreAnalyzeReturnForVectorFloat(Outs); } void AnalyzeReturn(const SmallVectorImpl &Outs, CCAssignFn Fn) { - PreAnalyzeReturnForF128(Outs); - PreAnalyzeReturnForVectorFloat(Outs); + PreAnalyzeReturn(Outs, Fn); CCState::AnalyzeReturn(Outs, Fn); - OriginalArgWasFloat.clear(); - OriginalArgWasF128.clear(); - OriginalArgWasFloatVector.clear(); } bool CheckReturn(const SmallVectorImpl &ArgsFlags, Index: llvm/lib/Target/Mips/MipsCCState.cpp =================================================================== --- llvm/lib/Target/Mips/MipsCCState.cpp +++ llvm/lib/Target/Mips/MipsCCState.cpp @@ -12,8 +12,7 @@ using namespace llvm; -/// This function returns true if CallSym is a long double emulation routine. -static bool isF128SoftLibCall(const char *CallSym) { +bool MipsCCState::isF128SoftLibCall(const char *CallSym) { const char *const LibCalls[] = { "__addtf3", "__divtf3", "__eqtf2", "__extenddftf2", "__extendsftf2", "__fixtfdi", "__fixtfsi", "__fixtfti", @@ -37,7 +36,7 @@ /// This function returns true if Ty is fp128, {f128} or i128 which was /// originally a fp128. -static bool originalTypeIsF128(const Type *Ty, const char *Func) { +bool MipsCCState::originalTypeIsF128(const Type *Ty, const char *Func) { if (Ty->isFP128Ty()) return true; @@ -47,11 +46,12 @@ // If the Ty is i128 and the function being called is a long double emulation // routine, then the original type is f128. + // FIXME: This is unsound because these functions could be indirectly called return (Func && Ty->isIntegerTy(128) && isF128SoftLibCall(Func)); } /// Return true if the original type was vXfXX. -static bool originalEVTTypeIsVectorFloat(EVT Ty) { +bool MipsCCState::originalEVTTypeIsVectorFloat(EVT Ty) { if (Ty.isVector() && Ty.getVectorElementType().isFloatingPoint()) return true; @@ -59,7 +59,7 @@ } /// Return true if the original type was vXfXX / vXfXX. -static bool originalTypeIsVectorFloat(const Type * Ty) { +bool MipsCCState::originalTypeIsVectorFloat(const Type *Ty) { if (Ty->isVectorTy() && Ty->isFPOrFPVectorTy()) return true; @@ -126,6 +126,18 @@ } } +void MipsCCState::PreAnalyzeReturnValue(EVT ArgVT) { + OriginalRetWasFloatVector.push_back(originalEVTTypeIsVectorFloat(ArgVT)); +} + +void MipsCCState::PreAnalyzeCallOperand(const Type *ArgTy, bool IsFixed, + const char *Func) { + OriginalArgWasF128.push_back(originalTypeIsF128(ArgTy, Func)); + OriginalArgWasFloat.push_back(ArgTy->isFloatingPointTy()); + OriginalArgWasFloatVector.push_back(ArgTy->isVectorTy()); + CallOperandIsFixed.push_back(IsFixed); +} + /// Identify lowered values that originated from f128, float and sret to vXfXX /// arguments and record this. void MipsCCState::PreAnalyzeCallOperands( @@ -142,6 +154,27 @@ } } +void MipsCCState::PreAnalyzeFormalArgument(const Type *ArgTy, + ISD::ArgFlagsTy Flags) { + // SRet arguments cannot originate from f128 or {f128} returns so we just + // push false. We have to handle this specially since SRet arguments + // aren't mapped to an original argument. + if (Flags.isSRet()) { + OriginalArgWasF128.push_back(false); + OriginalArgWasFloat.push_back(false); + OriginalArgWasFloatVector.push_back(false); + return; + } + + OriginalArgWasF128.push_back(originalTypeIsF128(ArgTy, nullptr)); + OriginalArgWasFloat.push_back(ArgTy->isFloatingPointTy()); + + // The MIPS vector ABI exhibits a corner case of sorts or quirk; if the + // first argument is actually an SRet pointer to a vector, then the next + // argument slot is $a2. + OriginalArgWasFloatVector.push_back(ArgTy->isVectorTy()); +} + /// Identify lowered values that originated from f128, float and vXfXX arguments /// and record this. void MipsCCState::PreAnalyzeFormalArgumentsForF128( Index: llvm/lib/Target/Mips/MipsCallLowering.h =================================================================== --- llvm/lib/Target/Mips/MipsCallLowering.h +++ llvm/lib/Target/Mips/MipsCallLowering.h @@ -24,6 +24,7 @@ class MipsCallLowering : public CallLowering { public: +#if 0 class MipsHandler { public: MipsHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) @@ -60,6 +61,7 @@ unsigned ArgLocsStartIndex, Register ArgsReg, const EVT &VT) = 0; }; +#endif MipsCallLowering(const MipsTargetLowering &TLI); @@ -73,14 +75,6 @@ bool lowerCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info) const override; - -private: - /// Based on registers available on target machine split or extend - /// type if needed, also change pointer type to appropriate integer - /// type. - template - void subTargetRegTypeForCallingConv(const Function &F, ArrayRef Args, - SmallVectorImpl &ISDArgs) const; }; } // end namespace llvm Index: llvm/lib/Target/Mips/MipsCallLowering.cpp =================================================================== --- llvm/lib/Target/Mips/MipsCallLowering.cpp +++ llvm/lib/Target/Mips/MipsCallLowering.cpp @@ -24,98 +24,89 @@ MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI) : CallLowering(&TLI) {} -bool MipsCallLowering::MipsHandler::assign(Register VReg, const CCValAssign &VA, - const EVT &VT) { - if (VA.isRegLoc()) { - assignValueToReg(VReg, VA, VT); - } else if (VA.isMemLoc()) { - assignValueToAddress(VReg, VA); - } else { - return false; +struct MipsOutgoingValueAssigner : public CallLowering::OutgoingValueAssigner { + /// This is the name of the function being called + /// FIXME: Relying on this is unsound + const char *Func = nullptr; + + /// Is this a return value, or an outgoing call operand. + bool IsReturn; + + MipsOutgoingValueAssigner(CCAssignFn *AssignFn_, const char *Func, + bool IsReturn) + : OutgoingValueAssigner(AssignFn_), Func(Func), IsReturn(IsReturn) {} + + bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, + const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags, + CCState &State_) override { + MipsCCState &State = static_cast(State_); + + if (IsReturn) + State.PreAnalyzeReturnValue(EVT::getEVT(Info.Ty)); + else + State.PreAnalyzeCallOperand(Info.Ty, Info.IsFixed, Func); + + return CallLowering::OutgoingValueAssigner::assignArg( + ValNo, OrigVT, ValVT, LocVT, LocInfo, Info, Flags, State); } - return true; -} +}; -bool MipsCallLowering::MipsHandler::assignVRegs(ArrayRef VRegs, - ArrayRef ArgLocs, - unsigned ArgLocsStartIndex, - const EVT &VT) { - for (unsigned i = 0; i < VRegs.size(); ++i) - if (!assign(VRegs[i], ArgLocs[ArgLocsStartIndex + i], VT)) - return false; - return true; -} +struct MipsIncomingValueAssigner : public CallLowering::IncomingValueAssigner { + /// This is the name of the function being called + /// FIXME: Relying on this is unsound + const char *Func = nullptr; -void MipsCallLowering::MipsHandler::setLeastSignificantFirst( - SmallVectorImpl &VRegs) { - if (!MIRBuilder.getMF().getDataLayout().isLittleEndian()) - std::reverse(VRegs.begin(), VRegs.end()); -} + /// Is this a call return value, or an incoming function argument. + bool IsReturn; -bool MipsCallLowering::MipsHandler::handle( - ArrayRef ArgLocs, ArrayRef Args) { - SmallVector VRegs; - unsigned SplitLength; - const Function &F = MIRBuilder.getMF().getFunction(); - const DataLayout &DL = F.getParent()->getDataLayout(); - const MipsTargetLowering &TLI = *static_cast( - MIRBuilder.getMF().getSubtarget().getTargetLowering()); - - for (unsigned ArgsIndex = 0, ArgLocsIndex = 0; ArgsIndex < Args.size(); - ++ArgsIndex, ArgLocsIndex += SplitLength) { - EVT VT = TLI.getValueType(DL, Args[ArgsIndex].Ty); - SplitLength = TLI.getNumRegistersForCallingConv(F.getContext(), - F.getCallingConv(), VT); - assert(Args[ArgsIndex].Regs.size() == 1 && "Can't handle multple regs yet"); - - if (SplitLength > 1) { - VRegs.clear(); - MVT RegisterVT = TLI.getRegisterTypeForCallingConv( - F.getContext(), F.getCallingConv(), VT); - for (unsigned i = 0; i < SplitLength; ++i) - VRegs.push_back(MRI.createGenericVirtualRegister(LLT{RegisterVT})); - - if (!handleSplit(VRegs, ArgLocs, ArgLocsIndex, Args[ArgsIndex].Regs[0], - VT)) - return false; - } else { - if (!assign(Args[ArgsIndex].Regs[0], ArgLocs[ArgLocsIndex], VT)) - return false; - } + MipsIncomingValueAssigner(CCAssignFn *AssignFn_, const char *Func, + bool IsReturn) + : IncomingValueAssigner(AssignFn_), Func(Func), IsReturn(IsReturn) {} + + bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, + const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags, + CCState &State_) override { + MipsCCState &State = static_cast(State_); + + if (IsReturn) + State.PreAnalyzeCallResult(Info.Ty, Func); + else + State.PreAnalyzeFormalArgument(Info.Ty, Flags); + + return CallLowering::IncomingValueAssigner::assignArg( + ValNo, OrigVT, ValVT, LocVT, LocInfo, Info, Flags, State); } - return true; -} +}; namespace { -class MipsIncomingValueHandler : public MipsCallLowering::MipsHandler { +class MipsIncomingValueHandler : public CallLowering::IncomingValueHandler { + const MipsSubtarget &STI; + public: MipsIncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) - : MipsHandler(MIRBuilder, MRI) {} + : IncomingValueHandler(MIRBuilder, MRI), + STI(MIRBuilder.getMF().getSubtarget()) {} private: - void assignValueToReg(Register ValVReg, const CCValAssign &VA, - const EVT &VT) override; + void assignValueToReg(Register ValVReg, Register PhysReg, + CCValAssign &VA) override; - Register getStackAddress(const CCValAssign &VA, - MachineMemOperand *&MMO) override; + Register getStackAddress(uint64_t Size, int64_t Offset, + MachinePointerInfo &MPO, + ISD::ArgFlagsTy Flags) override; + void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, + MachinePointerInfo &MPO, CCValAssign &VA) override; - void assignValueToAddress(Register ValVReg, const CCValAssign &VA) override; - - bool handleSplit(SmallVectorImpl &VRegs, - ArrayRef ArgLocs, unsigned ArgLocsStartIndex, - Register ArgsReg, const EVT &VT) override; + unsigned assignCustomValue(CallLowering::ArgInfo &Arg, + ArrayRef VAs) override; virtual void markPhysRegUsed(unsigned PhysReg) { MIRBuilder.getMRI()->addLiveIn(PhysReg); MIRBuilder.getMBB().addLiveIn(PhysReg); } - - MachineInstrBuilder buildLoad(const DstOp &Res, const CCValAssign &VA) { - MachineMemOperand *MMO; - Register Addr = getStackAddress(VA, MMO); - return MIRBuilder.buildLoad(Res, Addr, *MMO); - } }; class CallReturnHandler : public MipsIncomingValueHandler { @@ -135,191 +126,154 @@ } // end anonymous namespace void MipsIncomingValueHandler::assignValueToReg(Register ValVReg, - const CCValAssign &VA, - const EVT &VT) { - Register PhysReg = VA.getLocReg(); - if (VT == MVT::f64 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { - const MipsSubtarget &STI = - static_cast(MIRBuilder.getMF().getSubtarget()); - bool IsEL = STI.isLittle(); - LLT s32 = LLT::scalar(32); - auto Lo = MIRBuilder.buildCopy(s32, Register(PhysReg + (IsEL ? 0 : 1))); - auto Hi = MIRBuilder.buildCopy(s32, Register(PhysReg + (IsEL ? 1 : 0))); - MIRBuilder.buildMerge(ValVReg, {Lo, Hi}); - markPhysRegUsed(PhysReg); - markPhysRegUsed(PhysReg + 1); - } else if (VT == MVT::f32 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { - MIRBuilder.buildCopy(ValVReg, PhysReg); - markPhysRegUsed(PhysReg); - } else { - switch (VA.getLocInfo()) { - case CCValAssign::LocInfo::SExt: - case CCValAssign::LocInfo::ZExt: - case CCValAssign::LocInfo::AExt: { - auto Copy = MIRBuilder.buildCopy(LLT{VA.getLocVT()}, PhysReg); - MIRBuilder.buildTrunc(ValVReg, Copy); - break; - } - default: - MIRBuilder.buildCopy(ValVReg, PhysReg); - break; - } - markPhysRegUsed(PhysReg); - } + Register PhysReg, + CCValAssign &VA) { + markPhysRegUsed(PhysReg); + IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA); } -Register MipsIncomingValueHandler::getStackAddress(const CCValAssign &VA, - MachineMemOperand *&MMO) { +Register MipsIncomingValueHandler::getStackAddress(uint64_t Size, + int64_t Offset, + MachinePointerInfo &MPO, + ISD::ArgFlagsTy Flags) { + MachineFunction &MF = MIRBuilder.getMF(); - unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8; - unsigned Offset = VA.getLocMemOffset(); MachineFrameInfo &MFI = MF.getFrameInfo(); // FIXME: This should only be immutable for non-byval memory arguments. int FI = MFI.CreateFixedObject(Size, Offset, true); - MachinePointerInfo MPO = - MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); - - const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); - Align Alignment = commonAlignment(TFL->getStackAlign(), Offset); - MMO = - MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, Size, Alignment); + MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); return MIRBuilder.buildFrameIndex(LLT::pointer(0, 32), FI).getReg(0); } void MipsIncomingValueHandler::assignValueToAddress(Register ValVReg, - const CCValAssign &VA) { - if (VA.getLocInfo() == CCValAssign::SExt || - VA.getLocInfo() == CCValAssign::ZExt || - VA.getLocInfo() == CCValAssign::AExt) { - auto Load = buildLoad(LLT::scalar(32), VA); - MIRBuilder.buildTrunc(ValVReg, Load); - } else - buildLoad(ValVReg, VA); + Register Addr, LLT MemTy, + MachinePointerInfo &MPO, + CCValAssign &VA) { + MachineFunction &MF = MIRBuilder.getMF(); + auto MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy, + inferAlignFromPtrInfo(MF, MPO)); + MIRBuilder.buildLoad(ValVReg, Addr, *MMO); } -bool MipsIncomingValueHandler::handleSplit(SmallVectorImpl &VRegs, - ArrayRef ArgLocs, - unsigned ArgLocsStartIndex, - Register ArgsReg, const EVT &VT) { - if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex, VT)) - return false; - setLeastSignificantFirst(VRegs); - MIRBuilder.buildMerge(ArgsReg, VRegs); - return true; +/// Handle cases when f64 is split into 2 32-bit GPRs. This is a custom +/// assignment because generic code assumes getNumRegistersForCallingConv is +/// accurate. In this case it is not because the type/number are context +/// dependent on other arguments. +unsigned +MipsIncomingValueHandler::assignCustomValue(CallLowering::ArgInfo &Arg, + ArrayRef VAs) { + const CCValAssign &VALo = VAs[0]; + const CCValAssign &VAHi = VAs[1]; + + assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 && + VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 && + "unexpected custom value"); + + auto CopyLo = MIRBuilder.buildCopy(LLT::scalar(32), VALo.getLocReg()); + auto CopyHi = MIRBuilder.buildCopy(LLT::scalar(32), VAHi.getLocReg()); + if (!STI.isLittle()) + std::swap(CopyLo, CopyHi); + + Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end()); + Arg.Regs = { CopyLo.getReg(0), CopyHi.getReg(0) }; + MIRBuilder.buildMerge(Arg.OrigRegs[0], {CopyLo, CopyHi}); + + markPhysRegUsed(VALo.getLocReg()); + markPhysRegUsed(VAHi.getLocReg()); + return 2; } namespace { -class MipsOutgoingValueHandler : public MipsCallLowering::MipsHandler { +class MipsOutgoingValueHandler : public CallLowering::OutgoingValueHandler { + const MipsSubtarget &STI; + public: MipsOutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, MachineInstrBuilder &MIB) - : MipsHandler(MIRBuilder, MRI), MIB(MIB) {} + : OutgoingValueHandler(MIRBuilder, MRI), + STI(MIRBuilder.getMF().getSubtarget()), MIB(MIB) {} private: - void assignValueToReg(Register ValVReg, const CCValAssign &VA, - const EVT &VT) override; + void assignValueToReg(Register ValVReg, Register PhysReg, + CCValAssign &VA) override; - Register getStackAddress(const CCValAssign &VA, - MachineMemOperand *&MMO) override; + Register getStackAddress(uint64_t Size, int64_t Offset, + MachinePointerInfo &MPO, + ISD::ArgFlagsTy Flags) override; - void assignValueToAddress(Register ValVReg, const CCValAssign &VA) override; - - bool handleSplit(SmallVectorImpl &VRegs, - ArrayRef ArgLocs, unsigned ArgLocsStartIndex, - Register ArgsReg, const EVT &VT) override; - - Register extendRegister(Register ValReg, const CCValAssign &VA); + void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, + MachinePointerInfo &MPO, CCValAssign &VA) override; + unsigned assignCustomValue(CallLowering::ArgInfo &Arg, + ArrayRef VAs) override; MachineInstrBuilder &MIB; }; } // end anonymous namespace void MipsOutgoingValueHandler::assignValueToReg(Register ValVReg, - const CCValAssign &VA, - const EVT &VT) { - Register PhysReg = VA.getLocReg(); - if (VT == MVT::f64 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { - const MipsSubtarget &STI = - static_cast(MIRBuilder.getMF().getSubtarget()); - bool IsEL = STI.isLittle(); - auto Unmerge = MIRBuilder.buildUnmerge(LLT::scalar(32), ValVReg); - MIRBuilder.buildCopy(Register(PhysReg + (IsEL ? 0 : 1)), Unmerge.getReg(0)); - MIRBuilder.buildCopy(Register(PhysReg + (IsEL ? 1 : 0)), Unmerge.getReg(1)); - } else if (VT == MVT::f32 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { - MIRBuilder.buildCopy(PhysReg, ValVReg); - } else { - Register ExtReg = extendRegister(ValVReg, VA); - MIRBuilder.buildCopy(PhysReg, ExtReg); - MIB.addUse(PhysReg, RegState::Implicit); - } + Register PhysReg, + CCValAssign &VA) { + Register ExtReg = extendRegister(ValVReg, VA); + MIRBuilder.buildCopy(PhysReg, ExtReg); + MIB.addUse(PhysReg, RegState::Implicit); } -Register MipsOutgoingValueHandler::getStackAddress(const CCValAssign &VA, - MachineMemOperand *&MMO) { +Register MipsOutgoingValueHandler::getStackAddress(uint64_t Size, + int64_t Offset, + MachinePointerInfo &MPO, + ISD::ArgFlagsTy Flags) { MachineFunction &MF = MIRBuilder.getMF(); - const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); + MPO = MachinePointerInfo::getStack(MF, Offset); LLT p0 = LLT::pointer(0, 32); LLT s32 = LLT::scalar(32); auto SPReg = MIRBuilder.buildCopy(p0, Register(Mips::SP)); - unsigned Offset = VA.getLocMemOffset(); auto OffsetReg = MIRBuilder.buildConstant(s32, Offset); - auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg); - - MachinePointerInfo MPO = - MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); - unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8; - Align Alignment = commonAlignment(TFL->getStackAlign(), Offset); - MMO = - MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, Size, Alignment); - return AddrReg.getReg(0); } void MipsOutgoingValueHandler::assignValueToAddress(Register ValVReg, - const CCValAssign &VA) { - MachineMemOperand *MMO; - Register Addr = getStackAddress(VA, MMO); + Register Addr, LLT MemTy, + MachinePointerInfo &MPO, + CCValAssign &VA) { + MachineFunction &MF = MIRBuilder.getMF(); + uint64_t LocMemOffset = VA.getLocMemOffset(); + + auto MMO = MF.getMachineMemOperand( + MPO, MachineMemOperand::MOStore, MemTy, + commonAlignment(STI.getStackAlignment(), LocMemOffset)); + Register ExtReg = extendRegister(ValVReg, VA); MIRBuilder.buildStore(ExtReg, Addr, *MMO); } -Register MipsOutgoingValueHandler::extendRegister(Register ValReg, - const CCValAssign &VA) { - LLT LocTy{VA.getLocVT()}; - switch (VA.getLocInfo()) { - case CCValAssign::SExt: { - return MIRBuilder.buildSExt(LocTy, ValReg).getReg(0); - } - case CCValAssign::ZExt: { - return MIRBuilder.buildZExt(LocTy, ValReg).getReg(0); - } - case CCValAssign::AExt: { - return MIRBuilder.buildAnyExt(LocTy, ValReg).getReg(0); - } - // TODO : handle upper extends - case CCValAssign::Full: - return ValReg; - default: - break; - } - llvm_unreachable("unable to extend register"); -} - -bool MipsOutgoingValueHandler::handleSplit(SmallVectorImpl &VRegs, - ArrayRef ArgLocs, - unsigned ArgLocsStartIndex, - Register ArgsReg, const EVT &VT) { - MIRBuilder.buildUnmerge(VRegs, ArgsReg); - setLeastSignificantFirst(VRegs); - if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex, VT)) - return false; - - return true; +unsigned +MipsOutgoingValueHandler::assignCustomValue(CallLowering::ArgInfo &Arg, + ArrayRef VAs) { + const CCValAssign &VALo = VAs[0]; + const CCValAssign &VAHi = VAs[1]; + + assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 && + VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 && + "unexpected custom value"); + + auto Unmerge = + MIRBuilder.buildUnmerge({LLT::scalar(32), LLT::scalar(32)}, Arg.Regs[0]); + Register Lo = Unmerge.getReg(0); + Register Hi = Unmerge.getReg(1); + + Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end()); + Arg.Regs = { Lo, Hi }; + if (!STI.isLittle()) + std::swap(Lo, Hi); + + MIRBuilder.buildCopy(VALo.getLocReg(), Lo); + MIRBuilder.buildCopy(VAHi.getLocReg(), Hi); + return 2; } static bool isSupportedArgumentType(Type *T) { @@ -344,36 +298,6 @@ return false; } -static CCValAssign::LocInfo determineLocInfo(const MVT RegisterVT, const EVT VT, - const ISD::ArgFlagsTy &Flags) { - // > does not mean loss of information as type RegisterVT can't hold type VT, - // it means that type VT is split into multiple registers of type RegisterVT - if (VT.getFixedSizeInBits() >= RegisterVT.getFixedSizeInBits()) - return CCValAssign::LocInfo::Full; - if (Flags.isSExt()) - return CCValAssign::LocInfo::SExt; - if (Flags.isZExt()) - return CCValAssign::LocInfo::ZExt; - return CCValAssign::LocInfo::AExt; -} - -template -static void setLocInfo(SmallVectorImpl &ArgLocs, - const SmallVectorImpl &Arguments) { - for (unsigned i = 0; i < ArgLocs.size(); ++i) { - const CCValAssign &VA = ArgLocs[i]; - CCValAssign::LocInfo LocInfo = determineLocInfo( - Arguments[i].VT, Arguments[i].ArgVT, Arguments[i].Flags); - if (VA.isMemLoc()) - ArgLocs[i] = - CCValAssign::getMem(VA.getValNo(), VA.getValVT(), - VA.getLocMemOffset(), VA.getLocVT(), LocInfo); - else - ArgLocs[i] = CCValAssign::getReg(VA.getValNo(), VA.getValVT(), - VA.getLocReg(), VA.getLocVT(), LocInfo); - } -} - bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, ArrayRef VRegs, FunctionLoweringInfo &FLI) const { @@ -391,24 +315,28 @@ SmallVector RetInfos; - ArgInfo ArgRetInfo(VRegs, Val->getType(), 0); + ArgInfo ArgRetInfo(VRegs, *Val, 0); setArgFlags(ArgRetInfo, AttributeList::ReturnIndex, DL, F); splitToValueTypes(ArgRetInfo, RetInfos, DL, F.getCallingConv()); + SmallVector ArgLocs; SmallVector Outs; - subTargetRegTypeForCallingConv(F, RetInfos, Outs); - SmallVector ArgLocs; MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, F.getContext()); - CCInfo.AnalyzeReturn(Outs, TLI.CCAssignFnForReturn()); - setLocInfo(ArgLocs, Outs); MipsOutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret); - if (!RetHandler.handle(ArgLocs, RetInfos)) { + std::string FuncName = F.getName().str(); + MipsOutgoingValueAssigner Assigner(TLI.CCAssignFnForReturn(), + FuncName.c_str(), /*IsReturn*/ true); + + if (!determineAssignments(Assigner, RetInfos, CCInfo)) + return false; + + if (!handleAssignments(RetHandler, RetInfos, CCInfo, ArgLocs, MIRBuilder)) return false; - } } + MIRBuilder.insertInstr(Ret); return true; } @@ -434,14 +362,14 @@ SmallVector ArgInfos; unsigned i = 0; for (auto &Arg : F.args()) { - ArgInfo AInfo(VRegs[i], Arg.getType(), i); + ArgInfo AInfo(VRegs[i], Arg, i); setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F); - ArgInfos.push_back(AInfo); + + splitToValueTypes(AInfo, ArgInfos, DL, F.getCallingConv()); ++i; } SmallVector Ins; - subTargetRegTypeForCallingConv(F, ArgInfos, Ins); SmallVector ArgLocs; MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, @@ -452,11 +380,15 @@ const MipsABIInfo &ABI = TM.getABI(); CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(F.getCallingConv()), Align(1)); - CCInfo.AnalyzeFormalArguments(Ins, TLI.CCAssignFnForCall()); - setLocInfo(ArgLocs, Ins); + + const std::string FuncName = F.getName().str(); + MipsIncomingValueAssigner Assigner(TLI.CCAssignFnForCall(), FuncName.c_str(), + /*IsReturn*/ false); + if (!determineAssignments(Assigner, ArgInfos, CCInfo)) + return false; MipsIncomingValueHandler Handler(MIRBuilder, MF.getRegInfo()); - if (!Handler.handle(ArgLocs, ArgInfos)) + if (!handleAssignments(Handler, ArgInfos, CCInfo, ArgLocs, MIRBuilder)) return false; if (F.isVarArg()) { @@ -547,19 +479,8 @@ FuncOrigArgs.reserve(Info.OrigArgs.size()); SmallVector ArgInfos; - unsigned i = 0; - for (auto &Arg : Info.OrigArgs) { - - TargetLowering::ArgListEntry Entry; - Entry.Ty = Arg.Ty; - FuncOrigArgs.push_back(Entry); - - ArgInfos.push_back(Arg); - ++i; - } - - SmallVector Outs; - subTargetRegTypeForCallingConv(F, ArgInfos, Outs); + for (auto &Arg : Info.OrigArgs) + splitToValueTypes(Arg, ArgInfos, DL, Info.CallConv); SmallVector ArgLocs; bool IsCalleeVarArg = false; @@ -567,20 +488,26 @@ const Function *CF = static_cast(Info.Callee.getGlobal()); IsCalleeVarArg = CF->isVarArg(); } + + // FIXME: Should use MipsCCState::getSpecialCallingConvForCallee, but it + // depends on looking directly at the call target. MipsCCState CCInfo(Info.CallConv, IsCalleeVarArg, MF, ArgLocs, F.getContext()); CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(Info.CallConv), Align(1)); + const char *Call = Info.Callee.isSymbol() ? Info.Callee.getSymbolName() : nullptr; - CCInfo.AnalyzeCallOperands(Outs, TLI.CCAssignFnForCall(), FuncOrigArgs, Call); - setLocInfo(ArgLocs, Outs); - MipsOutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB); - if (!RetHandler.handle(ArgLocs, ArgInfos)) { + MipsOutgoingValueAssigner Assigner(TLI.CCAssignFnForCall(), Call, + /*IsReturn*/ false); + if (!determineAssignments(Assigner, ArgInfos, CCInfo)) + return false; + + MipsOutgoingValueHandler ArgHandler(MIRBuilder, MF.getRegInfo(), MIB); + if (!handleAssignments(ArgHandler, ArgInfos, CCInfo, ArgLocs, MIRBuilder)) return false; - } unsigned NextStackOffset = CCInfo.getNextStackOffset(); unsigned StackAlignment = F.getParent()->getOverrideStackAlignment(); @@ -607,21 +534,25 @@ if (!Info.OrigRet.Ty->isVoidTy()) { ArgInfos.clear(); - splitToValueTypes(Info.OrigRet, ArgInfos, DL, Info.CallConv); - SmallVector Ins; - subTargetRegTypeForCallingConv(F, ArgInfos, Ins); + CallLowering::splitToValueTypes(Info.OrigRet, ArgInfos, DL, + F.getCallingConv()); + const std::string FuncName = F.getName().str(); + SmallVector Ins; SmallVector ArgLocs; - MipsCCState CCInfo(Info.CallConv, F.isVarArg(), MF, ArgLocs, + MipsIncomingValueAssigner Assigner(TLI.CCAssignFnForReturn(), + FuncName.c_str(), + /*IsReturn*/ true); + CallReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB); + + MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, F.getContext()); - CCInfo.AnalyzeCallResult(Ins, TLI.CCAssignFnForReturn(), Info.OrigRet.Ty, - Call); - setLocInfo(ArgLocs, Ins); + if (!determineAssignments(Assigner, ArgInfos, CCInfo)) + return false; - CallReturnHandler Handler(MIRBuilder, MF.getRegInfo(), MIB); - if (!Handler.handle(ArgLocs, ArgInfos)) + if (!handleAssignments(RetHandler, ArgInfos, CCInfo, ArgLocs, MIRBuilder)) return false; } @@ -629,34 +560,3 @@ return true; } - -template -void MipsCallLowering::subTargetRegTypeForCallingConv( - const Function &F, ArrayRef Args, - SmallVectorImpl &ISDArgs) const { - const DataLayout &DL = F.getParent()->getDataLayout(); - const MipsTargetLowering &TLI = *getTLI(); - - unsigned ArgNo = 0; - for (auto &Arg : Args) { - - EVT VT = TLI.getValueType(DL, Arg.Ty); - MVT RegisterVT = TLI.getRegisterTypeForCallingConv(F.getContext(), - F.getCallingConv(), VT); - unsigned NumRegs = TLI.getNumRegistersForCallingConv( - F.getContext(), F.getCallingConv(), VT); - - for (unsigned i = 0; i < NumRegs; ++i) { - ISD::ArgFlagsTy Flags = Arg.Flags[0]; - - if (i == 0) - Flags.setOrigAlign(TLI.getABIAlignmentForCallingConv(Arg.Ty, DL)); - else - Flags.setOrigAlign(Align(1)); - - ISDArgs.emplace_back(Flags, RegisterVT, VT, true, Arg.OrigArgIndex, - 0); - } - ++ArgNo; - } -} Index: llvm/test/CodeGen/Mips/GlobalISel/irtranslator/extend_args.ll =================================================================== --- llvm/test/CodeGen/Mips/GlobalISel/irtranslator/extend_args.ll +++ llvm/test/CodeGen/Mips/GlobalISel/irtranslator/extend_args.ll @@ -7,7 +7,8 @@ ; MIPS32: bb.1.entry: ; MIPS32: liveins: $a0 ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 - ; MIPS32: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) + ; MIPS32: [[ASSERT_SEXT:%[0-9]+]]:_(s32) = G_ASSERT_SEXT [[COPY]], 8 + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[ASSERT_SEXT]](s32) ; MIPS32: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[TRUNC]](s8) ; MIPS32: $v0 = COPY [[SEXT]](s32) ; MIPS32: RetRA implicit $v0 @@ -20,7 +21,8 @@ ; MIPS32: bb.1.entry: ; MIPS32: liveins: $a0 ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 - ; MIPS32: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) + ; MIPS32: [[ASSERT_ZEXT:%[0-9]+]]:_(s32) = G_ASSERT_ZEXT [[COPY]], 8 + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[ASSERT_ZEXT]](s32) ; MIPS32: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s8) ; MIPS32: $v0 = COPY [[ZEXT]](s32) ; MIPS32: RetRA implicit $v0 @@ -55,20 +57,22 @@ ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3 ; MIPS32: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0 ; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s32) from %fixed-stack.0, align 8) - ; MIPS32: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[LOAD]](s32) + ; MIPS32: [[ASSERT_SEXT:%[0-9]+]]:_(s32) = G_ASSERT_SEXT [[LOAD]], 8 + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[ASSERT_SEXT]](s32) ; MIPS32: ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp ; MIPS32: $a0 = COPY [[COPY]](s32) ; MIPS32: $a1 = COPY [[COPY1]](s32) ; MIPS32: $a2 = COPY [[COPY2]](s32) ; MIPS32: $a3 = COPY [[COPY3]](s32) + ; MIPS32: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[TRUNC]](s8) ; MIPS32: [[COPY4:%[0-9]+]]:_(p0) = COPY $sp ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 ; MIPS32: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY4]], [[C]](s32) - ; MIPS32: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[TRUNC]](s8) ; MIPS32: G_STORE [[SEXT]](s32), [[PTR_ADD]](p0) :: (store (s32) into stack + 16, align 8) ; MIPS32: JAL @sext_stack_arg_i8, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0 ; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v0 - ; MIPS32: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY5]](s32) + ; MIPS32: [[ASSERT_SEXT1:%[0-9]+]]:_(s32) = G_ASSERT_SEXT [[COPY5]], 8 + ; MIPS32: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[ASSERT_SEXT1]](s32) ; MIPS32: ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp ; MIPS32: [[SEXT1:%[0-9]+]]:_(s32) = G_SEXT [[TRUNC1]](s8) ; MIPS32: $v0 = COPY [[SEXT1]](s32) @@ -88,20 +92,22 @@ ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3 ; MIPS32: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0 ; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s32) from %fixed-stack.0, align 8) - ; MIPS32: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[LOAD]](s32) + ; MIPS32: [[ASSERT_ZEXT:%[0-9]+]]:_(s32) = G_ASSERT_ZEXT [[LOAD]], 8 + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[ASSERT_ZEXT]](s32) ; MIPS32: ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp ; MIPS32: $a0 = COPY [[COPY]](s32) ; MIPS32: $a1 = COPY [[COPY1]](s32) ; MIPS32: $a2 = COPY [[COPY2]](s32) ; MIPS32: $a3 = COPY [[COPY3]](s32) + ; MIPS32: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s8) ; MIPS32: [[COPY4:%[0-9]+]]:_(p0) = COPY $sp ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 ; MIPS32: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY4]], [[C]](s32) - ; MIPS32: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s8) ; MIPS32: G_STORE [[ZEXT]](s32), [[PTR_ADD]](p0) :: (store (s32) into stack + 16, align 8) ; MIPS32: JAL @zext_stack_arg_i8, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0 ; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v0 - ; MIPS32: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY5]](s32) + ; MIPS32: [[ASSERT_ZEXT1:%[0-9]+]]:_(s32) = G_ASSERT_ZEXT [[COPY5]], 8 + ; MIPS32: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[ASSERT_ZEXT1]](s32) ; MIPS32: ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp ; MIPS32: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC1]](s8) ; MIPS32: $v0 = COPY [[ZEXT1]](s32) @@ -127,10 +133,10 @@ ; MIPS32: $a1 = COPY [[COPY1]](s32) ; MIPS32: $a2 = COPY [[COPY2]](s32) ; MIPS32: $a3 = COPY [[COPY3]](s32) + ; MIPS32: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s8) ; MIPS32: [[COPY4:%[0-9]+]]:_(p0) = COPY $sp ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 ; MIPS32: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY4]], [[C]](s32) - ; MIPS32: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s8) ; MIPS32: G_STORE [[ANYEXT]](s32), [[PTR_ADD]](p0) :: (store (s32) into stack + 16, align 8) ; MIPS32: JAL @aext_stack_arg_i8, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0 ; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v0 @@ -150,7 +156,8 @@ ; MIPS32: bb.1.entry: ; MIPS32: liveins: $a0 ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 - ; MIPS32: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; MIPS32: [[ASSERT_SEXT:%[0-9]+]]:_(s32) = G_ASSERT_SEXT [[COPY]], 16 + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[ASSERT_SEXT]](s32) ; MIPS32: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[TRUNC]](s16) ; MIPS32: $v0 = COPY [[SEXT]](s32) ; MIPS32: RetRA implicit $v0 @@ -163,7 +170,8 @@ ; MIPS32: bb.1.entry: ; MIPS32: liveins: $a0 ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 - ; MIPS32: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; MIPS32: [[ASSERT_ZEXT:%[0-9]+]]:_(s32) = G_ASSERT_ZEXT [[COPY]], 16 + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[ASSERT_ZEXT]](s32) ; MIPS32: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s16) ; MIPS32: $v0 = COPY [[ZEXT]](s32) ; MIPS32: RetRA implicit $v0 @@ -198,20 +206,22 @@ ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3 ; MIPS32: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0 ; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s32) from %fixed-stack.0, align 8) - ; MIPS32: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[LOAD]](s32) + ; MIPS32: [[ASSERT_SEXT:%[0-9]+]]:_(s32) = G_ASSERT_SEXT [[LOAD]], 16 + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[ASSERT_SEXT]](s32) ; MIPS32: ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp ; MIPS32: $a0 = COPY [[COPY]](s32) ; MIPS32: $a1 = COPY [[COPY1]](s32) ; MIPS32: $a2 = COPY [[COPY2]](s32) ; MIPS32: $a3 = COPY [[COPY3]](s32) + ; MIPS32: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[TRUNC]](s16) ; MIPS32: [[COPY4:%[0-9]+]]:_(p0) = COPY $sp ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 ; MIPS32: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY4]], [[C]](s32) - ; MIPS32: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[TRUNC]](s16) ; MIPS32: G_STORE [[SEXT]](s32), [[PTR_ADD]](p0) :: (store (s32) into stack + 16, align 8) ; MIPS32: JAL @sext_stack_arg_i16, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0 ; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v0 - ; MIPS32: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY5]](s32) + ; MIPS32: [[ASSERT_SEXT1:%[0-9]+]]:_(s32) = G_ASSERT_SEXT [[COPY5]], 16 + ; MIPS32: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[ASSERT_SEXT1]](s32) ; MIPS32: ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp ; MIPS32: [[SEXT1:%[0-9]+]]:_(s32) = G_SEXT [[TRUNC1]](s16) ; MIPS32: $v0 = COPY [[SEXT1]](s32) @@ -231,20 +241,22 @@ ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3 ; MIPS32: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0 ; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s32) from %fixed-stack.0, align 8) - ; MIPS32: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[LOAD]](s32) + ; MIPS32: [[ASSERT_ZEXT:%[0-9]+]]:_(s32) = G_ASSERT_ZEXT [[LOAD]], 16 + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[ASSERT_ZEXT]](s32) ; MIPS32: ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp ; MIPS32: $a0 = COPY [[COPY]](s32) ; MIPS32: $a1 = COPY [[COPY1]](s32) ; MIPS32: $a2 = COPY [[COPY2]](s32) ; MIPS32: $a3 = COPY [[COPY3]](s32) + ; MIPS32: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s16) ; MIPS32: [[COPY4:%[0-9]+]]:_(p0) = COPY $sp ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 ; MIPS32: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY4]], [[C]](s32) - ; MIPS32: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s16) ; MIPS32: G_STORE [[ZEXT]](s32), [[PTR_ADD]](p0) :: (store (s32) into stack + 16, align 8) ; MIPS32: JAL @zext_stack_arg_i16, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0 ; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v0 - ; MIPS32: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY5]](s32) + ; MIPS32: [[ASSERT_ZEXT1:%[0-9]+]]:_(s32) = G_ASSERT_ZEXT [[COPY5]], 16 + ; MIPS32: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[ASSERT_ZEXT1]](s32) ; MIPS32: ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp ; MIPS32: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC1]](s16) ; MIPS32: $v0 = COPY [[ZEXT1]](s32) @@ -270,10 +282,10 @@ ; MIPS32: $a1 = COPY [[COPY1]](s32) ; MIPS32: $a2 = COPY [[COPY2]](s32) ; MIPS32: $a3 = COPY [[COPY3]](s32) + ; MIPS32: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s16) ; MIPS32: [[COPY4:%[0-9]+]]:_(p0) = COPY $sp ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 ; MIPS32: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY4]], [[C]](s32) - ; MIPS32: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s16) ; MIPS32: G_STORE [[ANYEXT]](s32), [[PTR_ADD]](p0) :: (store (s32) into stack + 16, align 8) ; MIPS32: JAL @aext_stack_arg_i16, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0 ; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v0 Index: llvm/test/CodeGen/Mips/GlobalISel/irtranslator/float_args.ll =================================================================== --- llvm/test/CodeGen/Mips/GlobalISel/irtranslator/float_args.ll +++ llvm/test/CodeGen/Mips/GlobalISel/irtranslator/float_args.ll @@ -1,4 +1,3 @@ -; XFAIL: * ; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py ; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=FP32 @@ -157,7 +156,7 @@ ; FP32: ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp ; FP32: $a0 = COPY [[COPY]](s32) ; FP32: $a1 = COPY [[COPY1]](s32) - ; FP32: JAL @float_in_gpr, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit-def $f0 + ; FP32: JAL @float_in_gpr, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $f0 ; FP32: [[COPY2:%[0-9]+]]:_(s32) = COPY $f0 ; FP32: ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp ; FP32: $f0 = COPY [[COPY2]](s32) @@ -170,7 +169,7 @@ ; FP64: ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp ; FP64: $a0 = COPY [[COPY]](s32) ; FP64: $a1 = COPY [[COPY1]](s32) - ; FP64: JAL @float_in_gpr, csr_o32_fp64, implicit-def $ra, implicit-def $sp, implicit $a0, implicit-def $f0 + ; FP64: JAL @float_in_gpr, csr_o32_fp64, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit-def $f0 ; FP64: [[COPY2:%[0-9]+]]:_(s32) = COPY $f0 ; FP64: ADJCALLSTACKUP 16, 0, implicit-def $sp, implicit $sp ; FP64: $f0 = COPY [[COPY2]](s32) Index: llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/float_args.ll =================================================================== --- llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/float_args.ll +++ llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/float_args.ll @@ -1,4 +1,3 @@ -; XFAIL: * ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32,FP32 ; RUN: llc -O0 -mtriple=mipsel-linux-gnu -mattr=+fp64,+mips32r2 -global-isel -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32,FP64