diff --git a/llvm/include/llvm/CodeGen/CallingConvLower.h b/llvm/include/llvm/CodeGen/CallingConvLower.h --- a/llvm/include/llvm/CodeGen/CallingConvLower.h +++ b/llvm/include/llvm/CodeGen/CallingConvLower.h @@ -259,6 +259,10 @@ CallingConv::ID getCallingConv() const { return CallingConv; } bool isVarArg() const { return IsVarArg; } + /// getTargetRegisterInfo - Useful when checking if a register is part of a + /// calling convention. + const TargetRegisterInfo &getTargetRegisterInfo() const { return TRI; } + /// getNextStackOffset - Return the next stack offset such that all stack /// slots satisfy their alignment requirements. unsigned getNextStackOffset() const { diff --git a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h --- a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h @@ -229,8 +229,8 @@ /// Returns true if the updated CSR list was initialized and false otherwise. bool isUpdatedCSRsInitialized() const { return IsUpdatedCSRsInitialized; } - /// Returns true if a register can be used as an argument to a function. - bool isArgumentRegister(const MachineFunction &MF, MCRegister Reg) const; + /// Returns true if Reg is part of the calling convention. + bool isCCArgumentReg(MachineFunction &MF, MCRegister Reg) const; /// Returns true if a register is a fixed register. bool isFixedRegister(const MachineFunction &MF, MCRegister Reg) const; diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h --- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h +++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h @@ -559,11 +559,8 @@ virtual bool isCalleeSavedPhysReg(MCRegister PhysReg, const MachineFunction &MF) const; - /// Returns true if PhysReg can be used as an argument to a function. - virtual bool isArgumentRegister(const MachineFunction &MF, - MCRegister PhysReg) const { - return false; - } + /// Returns true if Reg is part of the calling convention. + virtual bool isCCArgumentReg(MachineFunction &MF, MCRegister Reg) const = 0; /// Returns true if PhysReg is a fixed register. virtual bool isFixedRegister(const MachineFunction &MF, diff --git a/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/llvm/lib/CodeGen/MachineRegisterInfo.cpp --- a/llvm/lib/CodeGen/MachineRegisterInfo.cpp +++ b/llvm/lib/CodeGen/MachineRegisterInfo.cpp @@ -652,9 +652,9 @@ return false; } -bool MachineRegisterInfo::isArgumentRegister(const MachineFunction &MF, - MCRegister Reg) const { - return getTargetRegisterInfo()->isArgumentRegister(MF, Reg); +bool MachineRegisterInfo::isCCArgumentReg(MachineFunction &MF, + MCRegister Reg) const { + return getTargetRegisterInfo()->isCCArgumentReg(MF, Reg); } bool MachineRegisterInfo::isFixedRegister(const MachineFunction &MF, diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp --- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -1237,7 +1237,7 @@ continue; // Want only registers used for arguments. - if (OnlyArg && !TRI.isArgumentRegister(MF, Reg)) + if (OnlyArg && !TRI.isCCArgumentReg(MF, Reg)) continue; RegsToZero.set(Reg); diff --git a/llvm/lib/Target/AArch64/AArch64CallingConvention.h b/llvm/lib/Target/AArch64/AArch64CallingConvention.h --- a/llvm/lib/Target/AArch64/AArch64CallingConvention.h +++ b/llvm/lib/Target/AArch64/AArch64CallingConvention.h @@ -16,6 +16,7 @@ #include "llvm/CodeGen/CallingConvLower.h" namespace llvm { + bool CC_AArch64_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State); @@ -46,6 +47,36 @@ bool RetCC_AArch64_WebKit_JS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State); + +// Methods to determine if a register belongs to the calling convention. +bool CC_AArch64_AAPCS_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, + MVT LocVT, ISD::ArgFlagsTy ArgFlags, + CCState &State); +bool CC_AArch64_DarwinPCS_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, + MVT LocVT, ISD::ArgFlagsTy ArgFlags, + CCState &State); +bool CC_AArch64_DarwinPCS_ILP32_VarArg_IsCCReg(MCPhysReg RegA, unsigned ValNo, + MVT ValVT, MVT LocVT, + ISD::ArgFlagsTy ArgFlags, + CCState &State); +bool CC_AArch64_DarwinPCS_VarArg_IsCCReg(MCPhysReg RegA, unsigned ValNo, + MVT ValVT, MVT LocVT, + ISD::ArgFlagsTy ArgFlags, + CCState &State); +bool CC_AArch64_GHC_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, + MVT LocVT, ISD::ArgFlagsTy ArgFlags, + CCState &State); +bool CC_AArch64_WebKit_JS_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, + MVT LocVT, ISD::ArgFlagsTy ArgFlags, + CCState &State); +bool CC_AArch64_Win64_CFGuard_Check_IsCCReg(MCPhysReg RegA, unsigned ValNo, + MVT ValVT, MVT LocVT, + ISD::ArgFlagsTy ArgFlags, + CCState &State); +bool CC_AArch64_Win64_VarArg_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, + MVT LocVT, ISD::ArgFlagsTy ArgFlags, + CCState &State); + } // namespace llvm #endif diff --git a/llvm/lib/Target/AArch64/AArch64CallingConvention.cpp b/llvm/lib/Target/AArch64/AArch64CallingConvention.cpp --- a/llvm/lib/Target/AArch64/AArch64CallingConvention.cpp +++ b/llvm/lib/Target/AArch64/AArch64CallingConvention.cpp @@ -202,6 +202,43 @@ return finishStackBlock(PendingMembers, LocVT, ArgFlags, State, SlotAlign); } +static bool CC_AArch64_Custom_Stack_Block_IsCCReg(MCPhysReg &, unsigned &, + MVT &, MVT &, + ISD::ArgFlagsTy &, + CCState &) { + return false; +} + +static bool CC_AArch64_Custom_Block_IsCCReg(MCPhysReg &RegA, unsigned &ValNo, + MVT &ValVT, MVT &LocVT, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + const AArch64Subtarget &Subtarget = static_cast( + State.getMachineFunction().getSubtarget()); + bool IsDarwinILP32 = Subtarget.isTargetILP32() && Subtarget.isTargetMachO(); + + ArrayRef RegList; + if (LocVT.SimpleTy == MVT::i64 || + (IsDarwinILP32 && LocVT.SimpleTy == MVT::i32)) + RegList = XRegList; + else if (LocVT.SimpleTy == MVT::f16) + RegList = HRegList; + else if (LocVT.SimpleTy == MVT::f32 || LocVT.is32BitVector()) + RegList = SRegList; + else if (LocVT.SimpleTy == MVT::f64 || LocVT.is64BitVector()) + RegList = DRegList; + else if (LocVT.SimpleTy == MVT::f128 || LocVT.is128BitVector()) + RegList = QRegList; + else if (LocVT.isScalableVector()) + RegList = ZRegList; + + for (MCPhysReg RegB : RegList) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + + return false; +} + // TableGen provides definitions of the calling convention analysis entry // points. #include "AArch64GenCallingConv.inc" diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h @@ -120,6 +120,8 @@ bool hasBasePointer(const MachineFunction &MF) const; unsigned getBaseRegister() const; + bool isCCArgumentReg(MachineFunction &MF, MCRegister PhysReg) const override; + // Debug information queries. Register getFrameRegister(const MachineFunction &MF) const override; diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "AArch64RegisterInfo.h" +#include "AArch64CallingConvention.h" #include "AArch64FrameLowering.h" #include "AArch64InstrInfo.h" #include "AArch64MachineFunctionInfo.h" @@ -434,6 +435,58 @@ return true; } +bool AArch64RegisterInfo::isCCArgumentReg(MachineFunction &MF, + MCRegister Reg) const { + const Function &F = MF.getFunction(); + const TargetRegisterClass *RC = getMinimalPhysRegClass(Reg); + const AArch64Subtarget &STI = MF.getSubtarget(); + + bool IsVarArg = F.isVarArg(); + SmallVector RVLocs; + CCState CCInfo(F.getCallingConv(), IsVarArg, MF, RVLocs, F.getContext()); + MVT VT = MVT(*legalclasstypes_begin(*RC)); + ISD::ArgFlagsTy ArgFlags; + ArgFlags.setInReg(); + + switch (F.getCallingConv()) { + default: + report_fatal_error("Unsupported calling convention."); + case CallingConv::WebKit_JS: + return CC_AArch64_WebKit_JS_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + case CallingConv::GHC: + return CC_AArch64_GHC_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + case CallingConv::C: + case CallingConv::Fast: + case CallingConv::PreserveMost: + case CallingConv::CXX_FAST_TLS: + case CallingConv::Swift: + case CallingConv::SwiftTail: + case CallingConv::Tail: + if (STI.isTargetWindows() && IsVarArg) + return CC_AArch64_Win64_VarArg_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + if (!STI.isTargetDarwin()) + return CC_AArch64_AAPCS_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + if (!IsVarArg) + return CC_AArch64_DarwinPCS_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + if (STI.isTargetILP32()) + return CC_AArch64_DarwinPCS_ILP32_VarArg_IsCCReg(Reg, 0, VT, VT, ArgFlags, + CCInfo); + return CC_AArch64_DarwinPCS_VarArg_IsCCReg(Reg, 0, VT, VT, ArgFlags, + CCInfo); + case CallingConv::Win64: + if (IsVarArg) + return CC_AArch64_Win64_VarArg_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + return CC_AArch64_AAPCS_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + case CallingConv::CFGuard_Check: + return CC_AArch64_Win64_CFGuard_Check_IsCCReg(Reg, 0, VT, VT, ArgFlags, + CCInfo); + case CallingConv::AArch64_VectorCall: + case CallingConv::AArch64_SVE_VectorCall: + return CC_AArch64_AAPCS_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + } + return false; +} + bool AArch64RegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const { // This function indicates whether the emergency spillslot should be placed diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp @@ -27,6 +27,7 @@ using namespace llvm; +#define CC_ASSIGN_REGS_ONLY #include "AMDGPUGenCallingConv.inc" static cl::opt AMDGPUBypassSlowDiv( diff --git a/llvm/lib/Target/AMDGPU/R600ISelLowering.cpp b/llvm/lib/Target/AMDGPU/R600ISelLowering.cpp --- a/llvm/lib/Target/AMDGPU/R600ISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/R600ISelLowering.cpp @@ -24,6 +24,7 @@ using namespace llvm; +#define CC_ASSIGN_REGS_ONLY #include "R600GenCallingConv.inc" R600TargetLowering::R600TargetLowering(const TargetMachine &TM, diff --git a/llvm/lib/Target/AMDGPU/R600RegisterInfo.h b/llvm/lib/Target/AMDGPU/R600RegisterInfo.h --- a/llvm/lib/Target/AMDGPU/R600RegisterInfo.h +++ b/llvm/lib/Target/AMDGPU/R600RegisterInfo.h @@ -52,6 +52,8 @@ RegScavenger *RS = nullptr) const override; void reserveRegisterTuples(BitVector &Reserved, unsigned Reg) const; + + bool isCCArgumentReg(MachineFunction &MF, MCRegister Reg) const override; }; } // End namespace llvm diff --git a/llvm/lib/Target/AMDGPU/R600RegisterInfo.cpp b/llvm/lib/Target/AMDGPU/R600RegisterInfo.cpp --- a/llvm/lib/Target/AMDGPU/R600RegisterInfo.cpp +++ b/llvm/lib/Target/AMDGPU/R600RegisterInfo.cpp @@ -116,3 +116,9 @@ for (; R.isValid(); ++R) Reserved.set(*R); } + +bool R600RegisterInfo::isCCArgumentReg(MachineFunction &MF, + MCRegister Reg) const { + llvm_unreachable("Not supported yet"); + return false; +} diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h --- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h +++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h @@ -284,6 +284,8 @@ return !isSGPRClass(RC); } + bool isCCArgumentReg(MachineFunction &MF, MCRegister Reg) const override; + ArrayRef getRegSplitParts(const TargetRegisterClass *RC, unsigned EltSize) const; diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp --- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp +++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp @@ -21,6 +21,7 @@ #include "llvm/CodeGen/LiveIntervals.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/CodeGen/TargetCallingConv.h" using namespace llvm; @@ -3043,3 +3044,41 @@ SIRegisterInfo::getAllSGPR32(const MachineFunction &MF) const { return makeArrayRef(AMDGPU::SGPR_32RegClass.begin(), ST.getMaxNumSGPRs(MF)); } + +#define CC_CHECK_REGS_ONLY +#include "AMDGPUGenCallingConv.inc" + +bool SIRegisterInfo::isCCArgumentReg(MachineFunction &MF, + MCRegister Reg) const { + const Function &F = MF.getFunction(); + const TargetRegisterClass *RC = getMinimalPhysRegClass(Reg); + + SmallVector RVLocs; + CCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, RVLocs, F.getContext()); + MVT VT = MVT(*legalclasstypes_begin(*RC)); + ISD::ArgFlagsTy ArgFlags; + ArgFlags.setInReg(); + + switch (F.getCallingConv()) { + case CallingConv::AMDGPU_VS: + case CallingConv::AMDGPU_GS: + case CallingConv::AMDGPU_PS: + case CallingConv::AMDGPU_CS: + case CallingConv::AMDGPU_HS: + case CallingConv::AMDGPU_ES: + case CallingConv::AMDGPU_LS: + return CC_AMDGPU_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + case CallingConv::C: + case CallingConv::Fast: + case CallingConv::Cold: + return CC_AMDGPU_Func_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + case CallingConv::AMDGPU_Gfx: + return CC_SI_Gfx_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + case CallingConv::AMDGPU_KERNEL: + case CallingConv::SPIR_KERNEL: + default: + report_fatal_error("Unsupported calling convention for call"); + } + + return false; +} diff --git a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h --- a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h +++ b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h @@ -177,6 +177,8 @@ bool cannotEliminateFrame(const MachineFunction &MF) const; + bool isCCArgumentReg(MachineFunction &MF, MCRegister Reg) const override; + // Debug information queries. Register getFrameRegister(const MachineFunction &MF) const override; Register getBaseRegister() const { return BasePtr; } diff --git a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp --- a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -13,6 +13,7 @@ #include "ARMBaseRegisterInfo.h" #include "ARM.h" #include "ARMBaseInstrInfo.h" +#include "ARMCallingConv.h" #include "ARMFrameLowering.h" #include "ARMMachineFunctionInfo.h" #include "ARMSubtarget.h" @@ -475,6 +476,39 @@ hasStackRealignment(MF); } +bool ARMBaseRegisterInfo::isCCArgumentReg(MachineFunction &MF, + MCRegister Reg) const { + const Function &F = MF.getFunction(); + const TargetRegisterClass *RC = getMinimalPhysRegClass(Reg); + + SmallVector RVLocs; + CCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, RVLocs, F.getContext()); + MVT VT = MVT(*legalclasstypes_begin(*RC)); + ISD::ArgFlagsTy ArgFlags; + ArgFlags.setInReg(); + + switch (F.getCallingConv()) { + default: + report_fatal_error("Unsupported calling convention"); + case CallingConv::ARM_APCS: + return CC_ARM_APCS_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + case CallingConv::ARM_AAPCS: + return CC_ARM_AAPCS_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + case CallingConv::ARM_AAPCS_VFP: + return CC_ARM_AAPCS_VFP_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + case CallingConv::Fast: + return FastCC_ARM_APCS_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + case CallingConv::GHC: + return CC_ARM_APCS_GHC_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + case CallingConv::PreserveMost: + return CC_ARM_AAPCS_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + case CallingConv::CFGuard_Check: + return CC_ARM_Win32_CFGuard_Check_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + } + + return false; +} + Register ARMBaseRegisterInfo::getFrameRegister(const MachineFunction &MF) const { const ARMSubtarget &STI = MF.getSubtarget(); diff --git a/llvm/lib/Target/ARM/ARMCallingConv.h b/llvm/lib/Target/ARM/ARMCallingConv.h --- a/llvm/lib/Target/ARM/ARMCallingConv.h +++ b/llvm/lib/Target/ARM/ARMCallingConv.h @@ -48,6 +48,25 @@ CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State); +// Methods to determine if a register belongs to the calling convention. +bool CC_ARM_AAPCS_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, MVT LocVT, + ISD::ArgFlagsTy ArgFlags, CCState &State); +bool CC_ARM_AAPCS_VFP_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, + MVT LocVT, ISD::ArgFlagsTy ArgFlags, + CCState &State); +bool CC_ARM_APCS_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, MVT LocVT, + ISD::ArgFlagsTy ArgFlags, CCState &State); +bool CC_ARM_APCS_GHC_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, + MVT LocVT, ISD::ArgFlagsTy ArgFlags, + CCState &State); +bool FastCC_ARM_APCS_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, + MVT LocVT, ISD::ArgFlagsTy ArgFlags, + CCState &State); +bool CC_ARM_Win32_CFGuard_Check_IsCCReg(MCPhysReg RegA, unsigned ValNo, + MVT ValVT, MVT LocVT, + ISD::ArgFlagsTy ArgFlags, + CCState &State); + } // namespace llvm #endif diff --git a/llvm/lib/Target/ARM/ARMCallingConv.cpp b/llvm/lib/Target/ARM/ARMCallingConv.cpp --- a/llvm/lib/Target/ARM/ARMCallingConv.cpp +++ b/llvm/lib/Target/ARM/ARMCallingConv.cpp @@ -312,5 +312,83 @@ SRegList); } +static bool CC_ARM_AAPCS_Custom_f64_IsCCReg(MCPhysReg RegA, unsigned ValNo, + MVT ValVT, MVT LocVT, + ISD::ArgFlagsTy ArgFlags, + CCState &State) { + for (MCPhysReg RegB : {ARM::R0, ARM::R1, ARM::R2, ARM::R3}) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + return false; +} + +static bool CC_ARM_AAPCS_Custom_f16_IsCCReg(MCPhysReg RegA, unsigned ValNo, + MVT ValVT, MVT LocVT, + ISD::ArgFlagsTy ArgFlags, + CCState &State) { + for (MCPhysReg RegB : RRegList) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + return false; +} + +static bool CC_ARM_AAPCS_VFP_Custom_f16_IsCCReg(MCPhysReg RegA, unsigned ValNo, + MVT ValVT, MVT LocVT, + ISD::ArgFlagsTy ArgFlags, + CCState &State) { + for (MCPhysReg RegB : SRegList) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + return false; +} + +static bool CC_ARM_AAPCS_Custom_Aggregate_IsCCReg(MCPhysReg RegA, + unsigned ValNo, MVT ValVT, + MVT LocVT, + ISD::ArgFlagsTy ArgFlags, + CCState &State) { + ArrayRef RegList; + switch (LocVT.SimpleTy) { + case MVT::i32: + RegList = RRegList; + break; + case MVT::f16: + case MVT::bf16: + case MVT::f32: + RegList = SRegList; + break; + case MVT::v4f16: + case MVT::v4bf16: + case MVT::f64: + RegList = DRegList; + break; + case MVT::v8f16: + case MVT::v8bf16: + case MVT::v2f64: + RegList = QRegList; + break; + default: + llvm_unreachable("Unexpected member type for block aggregate"); + break; + } + + for (MCPhysReg RegB : RegList) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + + return false; +} + +static bool CC_ARM_APCS_Custom_f64_IsCCReg(MCPhysReg RegA, unsigned ValNo, + MVT ValVT, MVT LocVT, + ISD::ArgFlagsTy ArgFlags, + CCState &State) { + for (MCPhysReg RegB : {ARM::R0, ARM::R1, ARM::R2, ARM::R3}) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + + return true; +} + // Include the table generated calling convention implementations. #include "ARMGenCallingConv.inc" diff --git a/llvm/lib/Target/AVR/AVRCallingConv.h b/llvm/lib/Target/AVR/AVRCallingConv.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/AVR/AVRCallingConv.h @@ -0,0 +1,28 @@ +//===-- AVRCallingConv.h - AVR Calling Convention Info ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains information about the AVR calling conventions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_AVR_CALLING_CONV_H +#define LLVM_AVR_CALLING_CONV_H + +namespace llvm { +namespace avr { + +/// Registers for calling conventions, ordered in reverse as required by ABI. +/// Both arrays must be of the same length. +extern const MCPhysReg RegList8[]; +extern const MCPhysReg RegList16[]; +extern const unsigned RegListSize; + +} // end namespace avr +} // end namespace llvm + +#endif // LLVM_AVR_REGISTER_INFO_H diff --git a/llvm/lib/Target/AVR/AVRISelLowering.cpp b/llvm/lib/Target/AVR/AVRISelLowering.cpp --- a/llvm/lib/Target/AVR/AVRISelLowering.cpp +++ b/llvm/lib/Target/AVR/AVRISelLowering.cpp @@ -25,6 +25,7 @@ #include "llvm/Support/ErrorHandling.h" #include "AVR.h" +#include "AVRCallingConv.h" #include "AVRMachineFunctionInfo.h" #include "AVRSubtarget.h" #include "AVRTargetMachine.h" @@ -1019,22 +1020,28 @@ // Formal Arguments Calling Convention Implementation //===----------------------------------------------------------------------===// +#define CC_ASSIGN_REGS_ONLY #include "AVRGenCallingConv.inc" +namespace avr { /// Registers for calling conventions, ordered in reverse as required by ABI. /// Both arrays must be of the same length. -static const MCPhysReg RegList8[] = { - AVR::R25, AVR::R24, AVR::R23, AVR::R22, AVR::R21, AVR::R20, - AVR::R19, AVR::R18, AVR::R17, AVR::R16, AVR::R15, AVR::R14, - AVR::R13, AVR::R12, AVR::R11, AVR::R10, AVR::R9, AVR::R8}; -static const MCPhysReg RegList16[] = { +const MCPhysReg RegList8[] = {AVR::R25, AVR::R24, AVR::R23, AVR::R22, AVR::R21, + AVR::R20, AVR::R19, AVR::R18, AVR::R17, AVR::R16, + AVR::R15, AVR::R14, AVR::R13, AVR::R12, AVR::R11, + AVR::R10, AVR::R9, AVR::R8}; + +const MCPhysReg RegList16[] = { AVR::R26R25, AVR::R25R24, AVR::R24R23, AVR::R23R22, AVR::R22R21, AVR::R21R20, AVR::R20R19, AVR::R19R18, AVR::R18R17, AVR::R17R16, AVR::R16R15, AVR::R15R14, AVR::R14R13, AVR::R13R12, AVR::R12R11, AVR::R11R10, AVR::R10R9, AVR::R9R8}; +const unsigned RegListSize = array_lengthof(RegList8); + static_assert(array_lengthof(RegList8) == array_lengthof(RegList16), "8-bit and 16-bit register arrays must be of equal length"); +} // namespace avr /// Analyze incoming and outgoing function arguments. We need custom C++ code /// to handle special constraints in the ABI. @@ -1074,7 +1081,7 @@ unsigned RegIdx = RegLastIdx + TotalBytes; RegLastIdx = RegIdx; // If there are not enough registers, use the stack - if (RegIdx >= array_lengthof(RegList8)) { + if (RegIdx >= array_lengthof(avr::RegList8)) { UseStack = true; } for (; i != j; ++i) { @@ -1089,9 +1096,9 @@ } else { unsigned Reg; if (VT == MVT::i8) { - Reg = CCInfo.AllocateReg(RegList8[RegIdx]); + Reg = CCInfo.AllocateReg(avr::RegList8[RegIdx]); } else if (VT == MVT::i16) { - Reg = CCInfo.AllocateReg(RegList16[RegIdx]); + Reg = CCInfo.AllocateReg(avr::RegList16[RegIdx]); } else { llvm_unreachable( "calling convention can only manage i8 and i16 types"); @@ -1144,9 +1151,9 @@ MVT VT = Args[i].VT; unsigned Reg; if (VT == MVT::i8) { - Reg = CCInfo.AllocateReg(RegList8[RegIdx]); + Reg = CCInfo.AllocateReg(avr::RegList8[RegIdx]); } else if (VT == MVT::i16) { - Reg = CCInfo.AllocateReg(RegList16[RegIdx]); + Reg = CCInfo.AllocateReg(avr::RegList16[RegIdx]); } else { llvm_unreachable("calling convention can only manage i8 and i16 types"); } diff --git a/llvm/lib/Target/AVR/AVRRegisterInfo.h b/llvm/lib/Target/AVR/AVRRegisterInfo.h --- a/llvm/lib/Target/AVR/AVRRegisterInfo.h +++ b/llvm/lib/Target/AVR/AVRRegisterInfo.h @@ -55,6 +55,9 @@ unsigned SubReg, const TargetRegisterClass *DstRC, unsigned DstSubReg, const TargetRegisterClass *NewRC, LiveIntervals &LIS) const override; + + /// Returns true if PhysReg is part of the calling convention. + bool isCCArgumentReg(MachineFunction &MF, MCRegister Reg) const override; }; } // end namespace llvm diff --git a/llvm/lib/Target/AVR/AVRRegisterInfo.cpp b/llvm/lib/Target/AVR/AVRRegisterInfo.cpp --- a/llvm/lib/Target/AVR/AVRRegisterInfo.cpp +++ b/llvm/lib/Target/AVR/AVRRegisterInfo.cpp @@ -21,6 +21,7 @@ #include "llvm/IR/Function.h" #include "AVR.h" +#include "AVRCallingConv.h" #include "AVRInstrInfo.h" #include "AVRMachineFunctionInfo.h" #include "AVRTargetMachine.h" @@ -286,4 +287,37 @@ NewRC, LIS); } +#define CC_CHECK_REGS_ONLY +#include "AVRGenCallingConv.inc" + +bool AVRRegisterInfo::isCCArgumentReg(MachineFunction &MF, + MCRegister RegA) const { + const Function &F = MF.getFunction(); + const AVRSubtarget &STI = MF.getSubtarget(); + const AVRRegisterInfo *TRI = STI.getRegisterInfo(); + const TargetRegisterClass *RC = getMinimalPhysRegClass(RegA); + MVT VT = MVT(*legalclasstypes_begin(*RC)); + + if (F.isVarArg()) { + SmallVector RVLocs; + CCState CCInfo(F.getCallingConv(), true, MF, RVLocs, F.getContext()); + ISD::ArgFlagsTy ArgFlags; + ArgFlags.setInReg(); + + return ArgCC_AVR_Vararg_IsCCReg(RegA, 0, VT, VT, ArgFlags, CCInfo); + } + + const MCPhysReg *RegList; + if (VT == MVT::i8) + RegList = avr::RegList8; + else if (VT == MVT::i16) + RegList = avr::RegList16; + + for (unsigned I = 0, E = avr::RegListSize; I != E; ++I) + if (TRI->isSuperOrSubRegisterEq(RegA, RegList[I])) + return true; + + return false; +} + } // end of namespace llvm diff --git a/llvm/lib/Target/BPF/BPFISelLowering.cpp b/llvm/lib/Target/BPF/BPFISelLowering.cpp --- a/llvm/lib/Target/BPF/BPFISelLowering.cpp +++ b/llvm/lib/Target/BPF/BPFISelLowering.cpp @@ -294,6 +294,7 @@ } // Calling Convention Implementation +#define CC_ASSIGN_REGS_ONLY #include "BPFGenCallingConv.inc" SDValue BPFTargetLowering::LowerFormalArguments( diff --git a/llvm/lib/Target/BPF/BPFRegisterInfo.h b/llvm/lib/Target/BPF/BPFRegisterInfo.h --- a/llvm/lib/Target/BPF/BPFRegisterInfo.h +++ b/llvm/lib/Target/BPF/BPFRegisterInfo.h @@ -20,7 +20,7 @@ namespace llvm { -struct BPFRegisterInfo : public BPFGenRegisterInfo { +struct BPFRegisterInfo final : public BPFGenRegisterInfo { BPFRegisterInfo(); @@ -33,6 +33,8 @@ RegScavenger *RS = nullptr) const override; Register getFrameRegister(const MachineFunction &MF) const override; + + bool isCCArgumentReg(MachineFunction &MF, MCRegister Reg) const override; }; } diff --git a/llvm/lib/Target/BPF/BPFRegisterInfo.cpp b/llvm/lib/Target/BPF/BPFRegisterInfo.cpp --- a/llvm/lib/Target/BPF/BPFRegisterInfo.cpp +++ b/llvm/lib/Target/BPF/BPFRegisterInfo.cpp @@ -13,6 +13,7 @@ #include "BPFRegisterInfo.h" #include "BPF.h" #include "BPFSubtarget.h" +#include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -124,3 +125,23 @@ Register BPFRegisterInfo::getFrameRegister(const MachineFunction &MF) const { return BPF::R10; } + +#define CC_CHECK_REGS_ONLY +#include "BPFGenCallingConv.inc" + +bool BPFRegisterInfo::isCCArgumentReg(MachineFunction &MF, + MCRegister Reg) const { + const Function &F = MF.getFunction(); + const TargetRegisterClass *RC = getMinimalPhysRegClass(Reg); + + SmallVector RVLocs; + CCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, RVLocs, F.getContext()); + MVT VT = MVT(*legalclasstypes_begin(*RC)); + ISD::ArgFlagsTy ArgFlags; + ArgFlags.setInReg(); + + if (MF.getSubtarget().getHasAlu32()) + return CC_BPF32_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + + return CC_BPF64_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); +} diff --git a/llvm/lib/Target/Hexagon/HexagonCallingConv.h b/llvm/lib/Target/Hexagon/HexagonCallingConv.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/Hexagon/HexagonCallingConv.h @@ -0,0 +1,34 @@ +//==- HexagonCallingConv.h - Hexagon Calling Conventions ---------*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains information for the Hexagon's calling conventions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONCALLINGCONV_H +#define LLVM_LIB_TARGET_HEXAGON_HEXAGONCALLINGCONV_H + +#include "llvm/CodeGen/CallingConvLower.h" + +namespace llvm { + +class HexagonCCState final : public CCState { + unsigned NumNamedVarArgParams = 0; + +public: + HexagonCCState(CallingConv::ID CC, bool IsVarArg, MachineFunction &MF, + SmallVectorImpl &locs, LLVMContext &C, + unsigned NumNamedArgs) + : CCState(CC, IsVarArg, MF, locs, C), NumNamedVarArgParams(NumNamedArgs) { + } + unsigned getNumNamedVarArgParams() const { return NumNamedVarArgParams; } +}; + +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_HEXAGON_HEXAGONCALLINGCONV_H diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp --- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -13,6 +13,7 @@ #include "HexagonISelLowering.h" #include "Hexagon.h" +#include "HexagonCallingConv.h" #include "HexagonMachineFunctionInfo.h" #include "HexagonRegisterInfo.h" #include "HexagonSubtarget.h" @@ -39,12 +40,12 @@ #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalValue.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicsHexagon.h" -#include "llvm/IR/IRBuilder.h" #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" @@ -118,23 +119,6 @@ cl::desc("Disable minimum alignment of 1 for " "arguments passed by value on stack")); -namespace { - - class HexagonCCState : public CCState { - unsigned NumNamedVarArgParams = 0; - - public: - HexagonCCState(CallingConv::ID CC, bool IsVarArg, MachineFunction &MF, - SmallVectorImpl &locs, LLVMContext &C, - unsigned NumNamedArgs) - : CCState(CC, IsVarArg, MF, locs, C), - NumNamedVarArgParams(NumNamedArgs) {} - unsigned getNumNamedVarArgParams() const { return NumNamedVarArgParams; } - }; - -} // end anonymous namespace - - // Implement calling convention for Hexagon. static bool CC_SkipOdd(unsigned &ValNo, MVT &ValVT, MVT &LocVT, @@ -157,9 +141,9 @@ return false; } +#define CC_ASSIGN_REGS_ONLY #include "HexagonGenCallingConv.inc" - SDValue HexagonTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const { diff --git a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.h b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.h --- a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.h +++ b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.h @@ -26,7 +26,7 @@ enum { ps_sub_lo = 0, ps_sub_hi = 1 }; } -class HexagonRegisterInfo : public HexagonGenRegisterInfo { +class HexagonRegisterInfo final : public HexagonGenRegisterInfo { public: HexagonRegisterInfo(unsigned HwMode); @@ -79,6 +79,8 @@ unsigned Kind = 0) const override; bool isEHReturnCalleeSaveReg(unsigned Reg) const; + + bool isCCArgumentReg(MachineFunction &MF, MCRegister Reg) const override; }; } // end namespace llvm diff --git a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp --- a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp +++ b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp @@ -13,12 +13,13 @@ #include "HexagonRegisterInfo.h" #include "Hexagon.h" +#include "HexagonCallingConv.h" #include "HexagonMachineFunctionInfo.h" #include "HexagonSubtarget.h" #include "HexagonTargetMachine.h" #include "llvm/ADT/BitVector.h" -#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/CodeGen/LiveIntervals.h" #include "llvm/CodeGen/LiveRegUnits.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -456,3 +457,40 @@ return Hexagon::R6; } +static bool CC_SkipOdd_IsCCReg(MCPhysReg RegA, unsigned ValNO, MVT &ValVT, + MVT &LocVT, ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + static const MCPhysReg ArgRegs[] = {Hexagon::R0, Hexagon::R1, Hexagon::R2, + Hexagon::R3, Hexagon::R4, Hexagon::R5}; + + for (MCPhysReg RegB : ArgRegs) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + + return false; +} + +#define CC_CHECK_REGS_ONLY +#include "HexagonGenCallingConv.inc" + +bool HexagonRegisterInfo::isCCArgumentReg(MachineFunction &MF, + MCRegister Reg) const { + (void)CC_Hexagon_Legacy_IsCCReg; // Silence unused function warning. + const Function &F = MF.getFunction(); + const TargetRegisterClass *RC = getMinimalPhysRegClass(Reg); + + unsigned NumParams = F.getFunctionType()->getNumParams(); + SmallVector RVLocs; + HexagonCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, RVLocs, + F.getContext(), NumParams); + MVT VT = MVT(*legalclasstypes_begin(*RC)); + ISD::ArgFlagsTy ArgFlags; + ArgFlags.setInReg(); + + if (MF.getSubtarget().useHVXOps()) + return CC_Hexagon_HVX_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + else + return CC_Hexagon_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + + return false; +} diff --git a/llvm/lib/Target/Lanai/LanaiISelLowering.cpp b/llvm/lib/Target/Lanai/LanaiISelLowering.cpp --- a/llvm/lib/Target/Lanai/LanaiISelLowering.cpp +++ b/llvm/lib/Target/Lanai/LanaiISelLowering.cpp @@ -363,6 +363,7 @@ // Calling Convention Implementation //===----------------------------------------------------------------------===// +#define CC_ASSIGN_REGS_ONLY #include "LanaiGenCallingConv.inc" static unsigned NumFixedArgs; diff --git a/llvm/lib/Target/Lanai/LanaiRegisterInfo.h b/llvm/lib/Target/Lanai/LanaiRegisterInfo.h --- a/llvm/lib/Target/Lanai/LanaiRegisterInfo.h +++ b/llvm/lib/Target/Lanai/LanaiRegisterInfo.h @@ -20,7 +20,7 @@ namespace llvm { -struct LanaiRegisterInfo : public LanaiGenRegisterInfo { +struct LanaiRegisterInfo final : public LanaiGenRegisterInfo { LanaiRegisterInfo(); const uint32_t *getCallPreservedMask(const MachineFunction &MF, @@ -38,6 +38,8 @@ unsigned FIOperandNum, RegScavenger *RS = nullptr) const override; + bool isCCArgumentReg(MachineFunction &MF, MCRegister Reg) const override; + // Debug information queries. unsigned getRARegister() const; Register getFrameRegister(const MachineFunction &MF) const override; diff --git a/llvm/lib/Target/Lanai/LanaiRegisterInfo.cpp b/llvm/lib/Target/Lanai/LanaiRegisterInfo.cpp --- a/llvm/lib/Target/Lanai/LanaiRegisterInfo.cpp +++ b/llvm/lib/Target/Lanai/LanaiRegisterInfo.cpp @@ -17,10 +17,12 @@ #include "LanaiInstrInfo.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/CodeGen/TargetCallingConv.h" #include "llvm/CodeGen/TargetFrameLowering.h" #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/IR/Function.h" @@ -251,6 +253,28 @@ return false; } +#define CC_CHECK_REGS_ONLY +#include "LanaiGenCallingConv.inc" + +bool LanaiRegisterInfo::isCCArgumentReg(MachineFunction &MF, + MCRegister Reg) const { + const Function &F = MF.getFunction(); + const TargetRegisterClass *RC = getMinimalPhysRegClass(Reg); + + SmallVector RVLocs; + CCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, RVLocs, F.getContext()); + MVT VT = MVT(*legalclasstypes_begin(*RC)); + ISD::ArgFlagsTy ArgFlags; + ArgFlags.setInReg(); + + if (F.getCallingConv() == CallingConv::Fast) + return CC_Lanai32_Fast_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + else + return CC_Lanai32_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + + return false; +} + unsigned LanaiRegisterInfo::getRARegister() const { return Lanai::RCA; } Register diff --git a/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp b/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp --- a/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -412,6 +412,7 @@ // Calling Convention Implementation //===----------------------------------------------------------------------===// +#define CC_ASSIGN_REGS_ONLY #include "MSP430GenCallingConv.inc" /// For each argument in a function store the number of pieces it is composed diff --git a/llvm/lib/Target/MSP430/MSP430RegisterInfo.h b/llvm/lib/Target/MSP430/MSP430RegisterInfo.h --- a/llvm/lib/Target/MSP430/MSP430RegisterInfo.h +++ b/llvm/lib/Target/MSP430/MSP430RegisterInfo.h @@ -20,7 +20,7 @@ namespace llvm { -struct MSP430RegisterInfo : public MSP430GenRegisterInfo { +struct MSP430RegisterInfo final : public MSP430GenRegisterInfo { public: MSP430RegisterInfo(); @@ -36,6 +36,10 @@ int SPAdj, unsigned FIOperandNum, RegScavenger *RS = nullptr) const override; + bool isCCArgumentReg(MachineFunction &MF, MCRegister Reg) const override { + return false; + } + // Debug information queries. Register getFrameRegister(const MachineFunction &MF) const override; }; diff --git a/llvm/lib/Target/Mips/MipsFastISel.cpp b/llvm/lib/Target/Mips/MipsFastISel.cpp --- a/llvm/lib/Target/Mips/MipsFastISel.cpp +++ b/llvm/lib/Target/Mips/MipsFastISel.cpp @@ -286,6 +286,7 @@ llvm_unreachable("should not be called"); } +#define CC_ASSIGN_REGS_ONLY #include "MipsGenCallingConv.inc" CCAssignFn *MipsFastISel::CCAssignFnForCall(CallingConv::ID CC) const { diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -2982,6 +2982,7 @@ CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State) LLVM_ATTRIBUTE_UNUSED; +#define CC_ASSIGN_REGS_ONLY #include "MipsGenCallingConv.inc" CCAssignFn *MipsTargetLowering::CCAssignFnForCall() const{ diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.h b/llvm/lib/Target/Mips/MipsRegisterInfo.h --- a/llvm/lib/Target/Mips/MipsRegisterInfo.h +++ b/llvm/lib/Target/Mips/MipsRegisterInfo.h @@ -58,6 +58,8 @@ bool requiresRegisterScavenging(const MachineFunction &MF) const override; + bool isCCArgumentReg(MachineFunction &MF, MCRegister Reg) const override; + /// Stack Frame Processing Methods void eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp --- a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp @@ -13,6 +13,7 @@ #include "MipsRegisterInfo.h" #include "MCTargetDesc/MipsABIInfo.h" #include "Mips.h" +#include "MipsCCState.h" #include "MipsMachineFunction.h" #include "MipsSubtarget.h" #include "MipsTargetMachine.h" @@ -318,3 +319,51 @@ // sized objects. return MF.getRegInfo().canReserveReg(BP); } + +static bool CC_MipsO32_FP32_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, + MVT LocVT, ISD::ArgFlagsTy ArgFlags, + CCState &State) { + for (MCPhysReg RegB : {Mips::D6, Mips::D7}) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + + return false; +} + +static bool CC_MipsO32_FP64_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, + MVT LocVT, ISD::ArgFlagsTy ArgFlags, + CCState &State) { + for (MCPhysReg RegB : {Mips::D12_64, Mips::D14_64}) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + + return false; +} + +static bool CC_Mips_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, + MVT LocVT, ISD::ArgFlagsTy ArgFlags, + CCState &State) LLVM_ATTRIBUTE_UNUSED; +static bool CC_MipsO32_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, + MVT LocVT, ISD::ArgFlagsTy ArgFlags, + CCState &State); + +#define CC_CHECK_REGS_ONLY +#include "MipsGenCallingConv.inc" + +bool MipsRegisterInfo::isCCArgumentReg(MachineFunction &MF, + MCRegister Reg) const { + const Function &F = MF.getFunction(); + const TargetRegisterClass *RC = getMinimalPhysRegClass(Reg); + + SmallVector RVLocs; + MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, RVLocs, + F.getContext()); + MVT VT = MVT(*legalclasstypes_begin(*RC)); + ISD::ArgFlagsTy ArgFlags; + ArgFlags.setInReg(); + + if (F.getCallingConv() == CallingConv::Fast) + return CC_MipsO32_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + + return CC_Mips_FixedArg_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); +} diff --git a/llvm/lib/Target/NVPTX/NVPTXRegisterInfo.h b/llvm/lib/Target/NVPTX/NVPTXRegisterInfo.h --- a/llvm/lib/Target/NVPTX/NVPTXRegisterInfo.h +++ b/llvm/lib/Target/NVPTX/NVPTXRegisterInfo.h @@ -21,7 +21,8 @@ #include "NVPTXGenRegisterInfo.inc" namespace llvm { -class NVPTXRegisterInfo : public NVPTXGenRegisterInfo { + +class NVPTXRegisterInfo final : public NVPTXGenRegisterInfo { private: // Hold Strings that can be free'd all together with NVPTXRegisterInfo ManagedStringPool ManagedStrPool; @@ -42,6 +43,11 @@ unsigned FIOperandNum, RegScavenger *RS = nullptr) const override; + // No calling convention is specified. + bool isCCArgumentReg(MachineFunction &, MCRegister) const override { + return false; + } + Register getFrameRegister(const MachineFunction &MF) const override; Register getFrameLocalRegister(const MachineFunction &MF) const; @@ -54,7 +60,6 @@ O << "reg" << RegNo; return getStrPool()->getManagedString(O.str().c_str())->c_str(); } - }; std::string getNVPTXRegClassName(const TargetRegisterClass *RC); diff --git a/llvm/lib/Target/PowerPC/PPCCallingConv.h b/llvm/lib/Target/PowerPC/PPCCallingConv.h --- a/llvm/lib/Target/PowerPC/PPCCallingConv.h +++ b/llvm/lib/Target/PowerPC/PPCCallingConv.h @@ -41,6 +41,19 @@ CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State); +// Methods to determine if a register belongs to the calling convention. +bool CC_PPC32_SVR4_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, MVT LocVT, + ISD::ArgFlagsTy ArgFlags, CCState &State); +bool CC_PPC64_ELF_FIS_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, + MVT LocVT, ISD::ArgFlagsTy ArgFlags, + CCState &State); +bool CC_PPC32_SVR4_ByVal_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, + MVT LocVT, ISD::ArgFlagsTy ArgFlags, + CCState &State); +bool CC_PPC32_SVR4_VarArg_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, + MVT LocVT, ISD::ArgFlagsTy ArgFlags, + CCState &State); + } // End llvm namespace #endif diff --git a/llvm/lib/Target/PowerPC/PPCCallingConv.cpp b/llvm/lib/Target/PowerPC/PPCCallingConv.cpp --- a/llvm/lib/Target/PowerPC/PPCCallingConv.cpp +++ b/llvm/lib/Target/PowerPC/PPCCallingConv.cpp @@ -159,4 +159,5 @@ return true; } +#define CC_ASSIGN_REGS_ONLY #include "PPCGenCallingConv.inc" diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h --- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h @@ -149,6 +149,8 @@ unsigned FIOperandNum, RegScavenger *RS = nullptr) const override; + bool isCCArgumentReg(MachineFunction &MF, MCRegister Reg) const override; + // Support for virtual base registers. bool needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const override; Register materializeFrameBaseRegister(MachineBasicBlock *MBB, int FrameIdx, diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp --- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -12,6 +12,8 @@ //===----------------------------------------------------------------------===// #include "PPCRegisterInfo.h" +#include "PPCCCState.h" +#include "PPCCallingConv.h" #include "PPCFrameLowering.h" #include "PPCInstrBuilder.h" #include "PPCMachineFunctionInfo.h" @@ -1695,3 +1697,93 @@ MI->getOpcode() == TargetOpcode::PATCHPOINT || (isInt<16>(Offset) && (Offset % offsetMinAlign(*MI)) == 0); } + +static bool CC_PPC32_SVR4_Custom_Dummy_IsCCReg(MCPhysReg &RegA, unsigned &ValNo, + MVT &ValVT, MVT &LocVT, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + return false; +} + +static bool CC_PPC32_SVR4_Custom_AlignArgRegs_IsCCReg(MCPhysReg &RegA, + unsigned &ValNo, + MVT &ValVT, MVT &LocVT, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + static const MCPhysReg ArgRegs[] = { + PPC::R3, PPC::R4, PPC::R5, PPC::R6, PPC::R7, PPC::R8, PPC::R9, PPC::R10, + }; + + for (MCPhysReg RegB : ArgRegs) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + return false; +} + +static bool CC_PPC32_SVR4_Custom_SkipLastArgRegsPPCF128_IsCCReg( + MCPhysReg &RegA, unsigned &ValNo, MVT &ValVT, MVT &LocVT, + ISD::ArgFlagsTy &ArgFlags, CCState &State) { + static const MCPhysReg ArgRegs[] = { + PPC::R3, PPC::R4, PPC::R5, PPC::R6, PPC::R7, PPC::R8, PPC::R9, PPC::R10, + }; + + for (MCPhysReg RegB : ArgRegs) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + return false; +} + +static bool CC_PPC32_SVR4_Custom_AlignFPArgRegs_IsCCReg( + MCPhysReg &RegA, unsigned &ValNo, MVT &ValVT, MVT &LocVT, + ISD::ArgFlagsTy &ArgFlags, CCState &State) { + static const MCPhysReg ArgRegs[] = {PPC::F1, PPC::F2, PPC::F3, PPC::F4, + PPC::F5, PPC::F6, PPC::F7, PPC::F8}; + + for (MCPhysReg RegB : ArgRegs) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + return false; +} + +static bool CC_PPC32_SPE_CustomSplitFP64_IsCCReg(MCPhysReg &RegA, + unsigned &ValNo, MVT &ValVT, + MVT &LocVT, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + static const MCPhysReg RegList[] = {PPC::R3, PPC::R5, PPC::R7, PPC::R9, + PPC::R4, PPC::R6, PPC::R8, PPC::R10}; + + for (MCPhysReg RegB : RegList) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + return false; +} + +inline bool CC_PPC_AnyReg_Error_IsCCReg(MCPhysReg &, unsigned &, MVT &, MVT &, + ISD::ArgFlagsTy &, CCState &) { + llvm_unreachable("The AnyReg calling convention is only supported by the " + "stackmap and patchpoint intrinsics."); + // gracefully fallback to PPC C calling convention on Release builds. + return false; +} + +#define CC_CHECK_REGS_ONLY +#include "PPCGenCallingConv.inc" + +bool PPCRegisterInfo::isCCArgumentReg(MachineFunction &MF, + MCRegister Reg) const { + const Function &F = MF.getFunction(); + const TargetRegisterClass *RC = getMinimalPhysRegClass(Reg); + + CallingConv::ID CC = F.getCallingConv(); + SmallVector RVLocs; + PPCCCState CCInfo(CC, F.isVarArg(), MF, RVLocs, F.getContext()); + MVT VT = MVT(*legalclasstypes_begin(*RC)); + ISD::ArgFlagsTy ArgFlags; + ArgFlags.setInReg(); + + if (CC == CallingConv::Fast) + return CC_PPC64_ELF_FIS_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + + return false; +} diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.h b/llvm/lib/Target/RISCV/RISCVRegisterInfo.h --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.h +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.h @@ -20,7 +20,7 @@ namespace llvm { -struct RISCVRegisterInfo : public RISCVGenRegisterInfo { +struct RISCVRegisterInfo final : public RISCVGenRegisterInfo { RISCVRegisterInfo(unsigned HwMode); @@ -68,6 +68,11 @@ SmallVectorImpl &Ops) const override; unsigned getRegisterCostTableIndex(const MachineFunction &MF) const override; + + bool isCCArgumentReg(MachineFunction &, MCRegister) const override { + llvm_unreachable("isCCArgumentReg not implemented for RISCV"); + return false; + } }; } diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -177,7 +177,7 @@ State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); return true; } - +#define CC_ASSIGN_REGS_ONLY #include "SparcGenCallingConv.inc" // The calling conventions in SparcCallingConv.td are described in terms of the diff --git a/llvm/lib/Target/Sparc/SparcRegisterInfo.h b/llvm/lib/Target/Sparc/SparcRegisterInfo.h --- a/llvm/lib/Target/Sparc/SparcRegisterInfo.h +++ b/llvm/lib/Target/Sparc/SparcRegisterInfo.h @@ -19,7 +19,8 @@ #include "SparcGenRegisterInfo.inc" namespace llvm { -struct SparcRegisterInfo : public SparcGenRegisterInfo { + +struct SparcRegisterInfo final : public SparcGenRegisterInfo { SparcRegisterInfo(); /// Code Generation virtual methods... @@ -42,6 +43,7 @@ bool canRealignStack(const MachineFunction &MF) const override; + bool isCCArgumentReg(MachineFunction &MF, MCRegister Reg) const override; }; } // end namespace llvm diff --git a/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp b/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp --- a/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp +++ b/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp @@ -16,6 +16,7 @@ #include "SparcSubtarget.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -238,3 +239,98 @@ return false; } + +static bool CC_Sparc_Assign_Split_64_IsCCReg(MCPhysReg &RegA, unsigned &ValNo, + MVT &ValVT, MVT &LocVT, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + static const MCPhysReg RegList[] = {SP::I0, SP::I1, SP::I2, + SP::I3, SP::I4, SP::I5}; + + for (MCPhysReg RegB : RegList) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + + return false; +} + +static bool CC_Sparc64_Full_IsCCReg(MCPhysReg &RegA, unsigned &ValNo, + MVT &ValVT, MVT &LocVT, + ISD::ArgFlagsTy &ArgFlags, CCState &State) { + assert((LocVT == MVT::f32 || LocVT == MVT::f128 || + LocVT.getSizeInBits() == 64) && + "Can't handle non-64 bits locations"); + + // Stack space is allocated for all arguments starting from [%fp+BIAS+128]. + unsigned size = (LocVT == MVT::f128) ? 16 : 8; + Align alignment = (LocVT == MVT::f128) ? Align(16) : Align(8); + unsigned Offset = State.AllocateStack(size, alignment); + unsigned Reg = 0; + + if (LocVT == MVT::i64 && Offset < 6 * 8) + // Promote integers to %i0-%i5. + Reg = SP::I0 + Offset / 8; + else if (LocVT == MVT::f64 && Offset < 16 * 8) + // Promote doubles to %d0-%d30. (Which LLVM calls D0-D15). + Reg = SP::D0 + Offset / 8; + else if (LocVT == MVT::f32 && Offset < 16 * 8) + // Promote floats to %f1, %f3, ... + Reg = SP::F1 + Offset / 4; + else if (LocVT == MVT::f128 && Offset < 16 * 8) + // Promote long doubles to %q0-%q28. (Which LLVM calls Q0-Q7). + Reg = SP::Q0 + Offset / 16; + + // Promote to register when possible, otherwise use the stack slot. + if (Reg) + return State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, Reg); + + // This argument goes on the stack in an 8-byte slot. + // When passing floats, LocVT is smaller than 8 bytes. Adjust the offset to + // the right-aligned float. The first 4 bytes of the stack slot are undefined. + if (LocVT == MVT::f32) + Offset += 4; + + return State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, Offset); +} + +static bool CC_Sparc64_Half_IsCCReg(MCPhysReg &RegA, unsigned &ValNo, + MVT &ValVT, MVT &LocVT, + ISD::ArgFlagsTy &ArgFlags, CCState &State) { + assert(LocVT.getSizeInBits() == 32 && "Can't handle non-32 bits locations"); + unsigned Offset = State.AllocateStack(4, Align(4)); + + if (LocVT == MVT::f32 && Offset < 16 * 8) + return State.getTargetRegisterInfo().isSuperOrSubRegisterEq( + RegA, SP::F0 + Offset / 4); + + if (LocVT == MVT::i32 && Offset < 6 * 8) + return State.getTargetRegisterInfo().isSuperOrSubRegisterEq( + RegA, SP::I0 + Offset / 8); + + return State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, Offset); +} + +static bool CC_Sparc_Assign_SRet_IsCCReg(MCPhysReg &, unsigned &, MVT &, MVT &, + ISD::ArgFlagsTy &, CCState &) { + return false; +} + +#define CC_CHECK_REGS_ONLY +#include "SparcGenCallingConv.inc" + +bool SparcRegisterInfo::isCCArgumentReg(MachineFunction &MF, + MCRegister Reg) const { + const Function &F = MF.getFunction(); + const TargetRegisterClass *RC = getMinimalPhysRegClass(Reg); + + SmallVector RVLocs; + CCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, RVLocs, F.getContext()); + MVT VT = MVT(*legalclasstypes_begin(*RC)); + ISD::ArgFlagsTy ArgFlags; + ArgFlags.setInReg(); + + if (MF.getSubtarget().is64Bit()) + return CC_Sparc64_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + + return CC_Sparc32_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); +} diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -1279,6 +1279,7 @@ // Calling conventions //===----------------------------------------------------------------------===// +#define CC_ASSIGN_REGS_ONLY #include "SystemZGenCallingConv.inc" const MCPhysReg *SystemZTargetLowering::getScratchRegisters( diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h --- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h +++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h @@ -131,7 +131,7 @@ ~SystemZELFRegisters() = default; }; -struct SystemZRegisterInfo : public SystemZGenRegisterInfo { +struct SystemZRegisterInfo final : public SystemZGenRegisterInfo { public: SystemZRegisterInfo(unsigned int RA); @@ -170,13 +170,12 @@ int SPAdj, unsigned FIOperandNum, RegScavenger *RS) const override; + bool isCCArgumentReg(MachineFunction &MF, MCRegister Reg) const override; + /// SrcRC and DstRC will be morphed into NewRC if this returns true. - bool shouldCoalesce(MachineInstr *MI, - const TargetRegisterClass *SrcRC, - unsigned SubReg, - const TargetRegisterClass *DstRC, - unsigned DstSubReg, - const TargetRegisterClass *NewRC, + bool shouldCoalesce(MachineInstr *MI, const TargetRegisterClass *SrcRC, + unsigned SubReg, const TargetRegisterClass *DstRC, + unsigned DstSubReg, const TargetRegisterClass *NewRC, LiveIntervals &LIS) const override; Register getFrameRegister(const MachineFunction &MF) const override; diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp --- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "SystemZRegisterInfo.h" +#include "SystemZCallingConv.h" #include "SystemZInstrInfo.h" #include "SystemZSubtarget.h" #include "llvm/ADT/SmallSet.h" @@ -465,3 +466,25 @@ return RC; } +bool SystemZRegisterInfo::isCCArgumentReg(MachineFunction &MF, + MCRegister RegA) const { + const SystemZSubtarget &Subtarget = MF.getSubtarget(); + const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); + + if (Subtarget.isTargetELF()) { + for (const MCPhysReg RegB : llvm::concat( + SystemZ::ELFArgGPRs, SystemZ::ELFArgFPRs)) + if (TRI->isSuperOrSubRegisterEq(RegA, RegB)) + return true; + } else if (Subtarget.isTargetXPLINK64()) { + for (const MCPhysReg RegB : llvm::concat( + SystemZ::XPLINK64ArgGPRs, SystemZ::XPLINK64ArgFPRs, + SystemZ::XPLINK64ArgVRs)) + if (TRI->isSuperOrSubRegisterEq(RegA, RegB)) + return true; + } else { + llvm_unreachable("Unknown Calling Convention!"); + } + + return false; +} diff --git a/llvm/lib/Target/VE/VEISelLowering.cpp b/llvm/lib/Target/VE/VEISelLowering.cpp --- a/llvm/lib/Target/VE/VEISelLowering.cpp +++ b/llvm/lib/Target/VE/VEISelLowering.cpp @@ -42,6 +42,7 @@ // Calling Convention Implementation //===----------------------------------------------------------------------===// +#define CC_ASSIGN_REGS_ONLY #include "VEGenCallingConv.inc" CCAssignFn *getReturnCC(CallingConv::ID CallConv) { diff --git a/llvm/lib/Target/VE/VERegisterInfo.h b/llvm/lib/Target/VE/VERegisterInfo.h --- a/llvm/lib/Target/VE/VERegisterInfo.h +++ b/llvm/lib/Target/VE/VERegisterInfo.h @@ -19,8 +19,8 @@ #include "VEGenRegisterInfo.inc" namespace llvm { -struct VERegisterInfo : public VEGenRegisterInfo { -public: + +struct VERegisterInfo final : public VEGenRegisterInfo { VERegisterInfo(); /// Code Generation virtual methods... @@ -40,6 +40,8 @@ RegScavenger *RS = nullptr) const override; Register getFrameRegister(const MachineFunction &MF) const override; + + bool isCCArgumentReg(MachineFunction &MF, MCRegister Reg) const override; }; } // namespace llvm diff --git a/llvm/lib/Target/VE/VERegisterInfo.cpp b/llvm/lib/Target/VE/VERegisterInfo.cpp --- a/llvm/lib/Target/VE/VERegisterInfo.cpp +++ b/llvm/lib/Target/VE/VERegisterInfo.cpp @@ -15,6 +15,7 @@ #include "VESubtarget.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -198,3 +199,29 @@ Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const { return VE::SX9; } + +#define CC_CHECK_REGS_ONLY +#include "VEGenCallingConv.inc" + +bool VERegisterInfo::isCCArgumentReg(MachineFunction &MF, + MCRegister Reg) const { + const Function &F = MF.getFunction(); + const TargetRegisterClass *RC = getMinimalPhysRegClass(Reg); + + CallingConv::ID CC = F.getCallingConv(); + bool IsVarArg = F.isVarArg(); + + SmallVector RVLocs; + CCState CCInfo(CC, IsVarArg, MF, RVLocs, F.getContext()); + MVT VT = MVT(*legalclasstypes_begin(*RC)); + ISD::ArgFlagsTy ArgFlags; + ArgFlags.setInReg(); + + if (IsVarArg) + return CC_VE2_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + + if (CC == CallingConv::Fast) + return CC_VE_Fast_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); + + return CC_VE_C_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); +} diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h --- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h @@ -46,6 +46,10 @@ unsigned Kind = 0) const override; // This does not apply to wasm. const uint32_t *getNoPreservedMask() const override { return nullptr; } + + bool isCCArgumentReg(MachineFunction &, MCRegister) const override { + return false; + } }; } // end namespace llvm diff --git a/llvm/lib/Target/X86/X86CallingConv.h b/llvm/lib/Target/X86/X86CallingConv.h --- a/llvm/lib/Target/X86/X86CallingConv.h +++ b/llvm/lib/Target/X86/X86CallingConv.h @@ -27,6 +27,10 @@ bool CC_X86(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State); +// Methods to determine if a register belongs to the calling convention. +bool CC_X86_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, MVT LocVT, + ISD::ArgFlagsTy ArgFlags, CCState &State); + } // End llvm namespace #endif diff --git a/llvm/lib/Target/X86/X86CallingConv.cpp b/llvm/lib/Target/X86/X86CallingConv.cpp --- a/llvm/lib/Target/X86/X86CallingConv.cpp +++ b/llvm/lib/Target/X86/X86CallingConv.cpp @@ -340,5 +340,118 @@ return false; } +static bool CC_X86_64_Pointer_IsCCReg(MCPhysReg &, unsigned &, MVT &, MVT &, + ISD::ArgFlagsTy &, CCState &) { + return false; +} + +static bool CC_X86_Intr_IsCCReg(MCPhysReg &RegA, unsigned &ValNo, MVT &ValVT, + MVT &LocVT, ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + return false; +} + +static bool CC_X86_32_MCUInReg_IsCCReg(MCPhysReg &RegA, unsigned &ValNo, + MVT &ValVT, MVT &LocVT, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + for (MCPhysReg RegB : {X86::EAX, X86::EDX, X86::ECX}) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + + return false; +} + +static bool CC_X86_32_RegCall_Assign2Regs_IsCCReg(MCPhysReg &RegA, + unsigned &ValNo, MVT &ValVT, + MVT &LocVT, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + // List of GPR registers that are available to store values in regcall + // calling convention. + static const MCPhysReg RegList[] = {X86::EAX, X86::ECX, X86::EDX, X86::EDI, + X86::ESI}; + for (MCPhysReg RegB : RegList) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + + return false; +} + +static bool CC_X86_AnyReg_Error_IsCCReg(MCPhysReg &, unsigned &, MVT &, MVT &, + ISD::ArgFlagsTy &, CCState &) { + llvm_unreachable("The AnyReg calling convention is only supported by the " + "stackmap and patchpoint intrinsics."); + // gracefully fallback to X86 C calling convention on Release builds. + return false; +} + +static bool CC_X86_32_VectorCall_IsCCReg(MCPhysReg &RegA, unsigned &ValNo, + MVT &ValVT, MVT &LocVT, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + // On the second pass, go through the HVAs only. + if (ArgFlags.isSecArgPass()) { + if (ArgFlags.isHva()) + for (MCPhysReg RegB : CC_X86_VectorCallGetSSEs(ValVT)) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + + return false; + } + + // Process only vector types as defined by vectorcall spec: + // "A vector type is either a floating point type, for example, + // a float or double, or an SIMD vector type, for example, __m128 or __m256". + if (!(ValVT.isFloatingPoint() || + (ValVT.isVector() && ValVT.getSizeInBits() >= 128))) { + return false; + } + + if (ArgFlags.isHva()) + return false; // If this is an HVA - Stop the search. + + // Assign XMM register. + for (MCPhysReg RegB : CC_X86_VectorCallGetSSEs(ValVT)) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + + return false; +} + +static bool CC_X86_64_VectorCall_IsCCReg(MCPhysReg &RegA, unsigned &ValNo, + MVT &ValVT, MVT &LocVT, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + // On the second pass, go through the HVAs only. + if (ArgFlags.isSecArgPass()) { + if (ArgFlags.isHva()) + for (MCPhysReg RegB : CC_X86_VectorCallGetSSEs(ValVT)) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + + return true; + } + + // Process only vector types as defined by vectorcall spec: + // "A vector type is either a floating-point type, for example, + // a float or double, or an SIMD vector type, for example, __m128 or __m256". + if (!(ValVT.isFloatingPoint() || + (ValVT.isVector() && ValVT.getSizeInBits() >= 128))) + return State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, X86::R9); + + if (!ArgFlags.isHva() || ArgFlags.isHvaStart()) { + for (MCPhysReg RegB : CC_X86_64_VectorCallGetGPRs()) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + + for (MCPhysReg RegB : CC_X86_VectorCallGetSSEs(ValVT)) + if (State.getTargetRegisterInfo().isSuperOrSubRegisterEq(RegA, RegB)) + return true; + } + + return false; +} + // Provides entry points of CC_X86 and RetCC_X86. #include "X86GenCallingConv.inc" diff --git a/llvm/lib/Target/X86/X86RegisterInfo.h b/llvm/lib/Target/X86/X86RegisterInfo.h --- a/llvm/lib/Target/X86/X86RegisterInfo.h +++ b/llvm/lib/Target/X86/X86RegisterInfo.h @@ -115,10 +115,9 @@ /// register scavenger to determine what registers are free. BitVector getReservedRegs(const MachineFunction &MF) const override; - /// isArgumentReg - Returns true if Reg can be used as an argument to a - /// function. - bool isArgumentRegister(const MachineFunction &MF, - MCRegister Reg) const override; + /// isCCArgumentReg - Returns true if PhysReg is part of the calling + /// convention. + bool isCCArgumentReg(MachineFunction &MF, MCRegister Reg) const override; /// Returns true if PhysReg is a fixed register. bool isFixedRegister(const MachineFunction &MF, diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp --- a/llvm/lib/Target/X86/X86RegisterInfo.cpp +++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp @@ -618,8 +618,8 @@ return Reserved; } -bool X86RegisterInfo::isArgumentRegister(const MachineFunction &MF, - MCRegister Reg) const { +bool X86RegisterInfo::isCCArgumentReg(MachineFunction &MF, + MCRegister Reg) const { const X86Subtarget &ST = MF.getSubtarget(); const TargetRegisterInfo &TRI = *ST.getRegisterInfo(); auto IsSubReg = [&](MCRegister RegA, MCRegister RegB) { diff --git a/llvm/lib/Target/XCore/XCoreISelLowering.cpp b/llvm/lib/Target/XCore/XCoreISelLowering.cpp --- a/llvm/lib/Target/XCore/XCoreISelLowering.cpp +++ b/llvm/lib/Target/XCore/XCoreISelLowering.cpp @@ -1019,6 +1019,7 @@ // Calling Convention Implementation //===----------------------------------------------------------------------===// +#define CC_ASSIGN_REGS_ONLY #include "XCoreGenCallingConv.inc" //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/XCore/XCoreRegisterInfo.h b/llvm/lib/Target/XCore/XCoreRegisterInfo.h --- a/llvm/lib/Target/XCore/XCoreRegisterInfo.h +++ b/llvm/lib/Target/XCore/XCoreRegisterInfo.h @@ -20,8 +20,7 @@ namespace llvm { -struct XCoreRegisterInfo : public XCoreGenRegisterInfo { -public: +struct XCoreRegisterInfo final : public XCoreGenRegisterInfo { XCoreRegisterInfo(); /// Code Generation virtual methods... @@ -43,6 +42,8 @@ //! Return whether to emit frame moves static bool needsFrameMoves(const MachineFunction &MF); + + bool isCCArgumentReg(MachineFunction &MF, MCRegister Reg) const override; }; } // end namespace llvm diff --git a/llvm/lib/Target/XCore/XCoreRegisterInfo.cpp b/llvm/lib/Target/XCore/XCoreRegisterInfo.cpp --- a/llvm/lib/Target/XCore/XCoreRegisterInfo.cpp +++ b/llvm/lib/Target/XCore/XCoreRegisterInfo.cpp @@ -17,19 +17,20 @@ #include "XCoreSubtarget.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/CodeGen/TargetFrameLowering.h" #include "llvm/IR/Function.h" #include "llvm/IR/Type.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/CodeGen/TargetFrameLowering.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" @@ -321,3 +322,20 @@ return TFI->hasFP(MF) ? XCore::R10 : XCore::SP; } + +#define CC_CHECK_REGS_ONLY +#include "XCoreGenCallingConv.inc" + +bool XCoreRegisterInfo::isCCArgumentReg(MachineFunction &MF, + MCRegister Reg) const { + const Function &F = MF.getFunction(); + const TargetRegisterClass *RC = getMinimalPhysRegClass(Reg); + + SmallVector RVLocs; + CCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, RVLocs, F.getContext()); + MVT VT = MVT(*legalclasstypes_begin(*RC)); + ISD::ArgFlagsTy ArgFlags; + ArgFlags.setInReg(); + + return CC_XCore_IsCCReg(Reg, 0, VT, VT, ArgFlags, CCInfo); +} diff --git a/llvm/unittests/CodeGen/MFCommon.inc b/llvm/unittests/CodeGen/MFCommon.inc --- a/llvm/unittests/CodeGen/MFCommon.inc +++ b/llvm/unittests/CodeGen/MFCommon.inc @@ -67,6 +67,10 @@ void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, unsigned FIOperandNum, RegScavenger *RS = nullptr) const override {} + + bool isCCArgumentReg(MachineFunction &, MCRegister) const override { + return false; + } }; class BogusSubtarget : public TargetSubtargetInfo { diff --git a/llvm/utils/TableGen/CallingConvEmitter.cpp b/llvm/utils/TableGen/CallingConvEmitter.cpp --- a/llvm/utils/TableGen/CallingConvEmitter.cpp +++ b/llvm/utils/TableGen/CallingConvEmitter.cpp @@ -29,15 +29,21 @@ private: void EmitCallingConv(Record *CC, raw_ostream &O); void EmitAction(Record *Action, unsigned Indent, raw_ostream &O); + void EmitCCRegisterQuery(Record *CC, raw_ostream &O); + void EmitQueryAction(Record *Action, unsigned Indent, raw_ostream &O); unsigned Counter; }; } // End anonymous namespace void CallingConvEmitter::run(raw_ostream &O) { std::vector CCs = Records.getAllDerivedDefinitions("CallingConv"); + if (CCs.empty()) + return; // Emit prototypes for all of the non-custom CC's so that they can forward ref // each other. + O << "#ifndef CC_CHECK_REGS_ONLY\n"; + Records.startTimer("Emit prototypes"); for (Record *CC : CCs) { if (!CC->getValueAsBit("Custom")) { @@ -62,8 +68,46 @@ if (!CC->getValueAsBit("Custom")) EmitCallingConv(CC, O); } -} + O << "#endif // !CC_CHECK_REGS_ONLY\n"; + + O << "\n#ifndef CC_ASSIGN_REGS_ONLY\n"; + + // Emit function to check if a register is part of the calling convention. + O << "// Function to determine if a register is part of the calling " + << "convention.\n\n"; + + for (Record *CC : CCs) { + if (!CC->getValueAsBit("Custom")) { + if (CC->getName().startswith("RetCC_") || + CC->getName().startswith("RetFastCC_")) + continue; + + unsigned Pad = CC->getName().size(); + if (CC->getValueAsBit("Entry")) { + O << "bool llvm::"; + Pad += 12; + } else { + O << "static bool "; + Pad += 13; + } + + O << CC->getName() << "_IsCCReg(MCPhysReg RegA, unsigned ValNo, " + << "MVT ValVT, MVT LocVT, ISD::ArgFlagsTy ArgFlags, " + << "CCState &State);\n"; + } + } + + // Emit each non-custom calling convention description in full. + Records.startTimer("Emit full descriptions"); + for (Record *CC : CCs) + if (!CC->getValueAsBit("Custom") && + !(CC->getName().startswith("RetCC_") || + CC->getName().startswith("RetFastCC_"))) + EmitCCRegisterQuery(CC, O); + + O << "#endif // !CC_ASSIGN_REGS_ONLY\n"; +} void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) { ListInit *CCActions = CC->getValueAsListInit("Actions"); @@ -288,6 +332,136 @@ } } +void CallingConvEmitter::EmitCCRegisterQuery(Record *CC, raw_ostream &O) { + ListInit *CCActions = CC->getValueAsListInit("Actions"); + Counter = 0; + + O << "\n\n"; + unsigned Pad = CC->getName().size(); + if (CC->getValueAsBit("Entry")) { + O << "bool llvm::"; + Pad += 12; + } else { + O << "static bool "; + Pad += 13; + } + O << CC->getName() << "_IsCCReg(MCPhysReg RegA, unsigned ValNo, MVT ValVT, " + << "MVT LocVT, ISD::ArgFlagsTy ArgFlags, CCState &State) {\n"; + + // Emit all of the actions, in order. + for (unsigned i = 0, e = CCActions->size(); i != e; ++i) { + O << "\n"; + EmitQueryAction(CCActions->getElementAsRecord(i), 2, O); + } + + O << "\n return false; // Register not part of CC.\n"; + O << "}\n"; +} + +void CallingConvEmitter::EmitQueryAction(Record *Action, unsigned Indent, + raw_ostream &O) { + std::string IndentStr = std::string(Indent, ' '); + + if (Action->isSubClassOf("CCPredicateAction")) { + O << IndentStr << "if ("; + + if (Action->isSubClassOf("CCIfType")) { + ListInit *VTs = Action->getValueAsListInit("VTs"); + for (unsigned i = 0, e = VTs->size(); i != e; ++i) { + Record *VT = VTs->getElementAsRecord(i); + if (i != 0) + O << " ||\n " << IndentStr; + O << "LocVT == " << getEnumName(getValueType(VT)); + } + } else if (Action->isSubClassOf("CCIf")) { + O << Action->getValueAsString("Predicate"); + } else { + errs() << *Action; + PrintFatalError(Action->getLoc(), "Unknown CCPredicateAction!"); + } + + O << ") {\n"; + EmitQueryAction(Action->getValueAsDef("SubAction"), Indent + 2, O); + O << IndentStr << "}\n"; + return; + } + + if (Action->isSubClassOf("CCDelegateTo")) { + Record *CC = Action->getValueAsDef("CC"); + O << IndentStr << "if (" << CC->getName() << "_IsCCReg(" + << "RegA, ValNo, ValVT, LocVT, ArgFlags, State))\n" + << IndentStr << " return true;\n"; + } else if (Action->isSubClassOf("CCAssignToReg")) { + ListInit *RegList = Action->getValueAsListInit("RegList"); + if (RegList->size() == 1) { + O << IndentStr << "if (State.getTargetRegisterInfo()" + << ".isSuperOrSubRegisterEq(RegA, " + << getQualifiedName(RegList->getElementAsRecord(0)) << "))\n" + << IndentStr << " return true;\n"; + } else { + O << IndentStr << "static const MCPhysReg RegList" << ++Counter + << "[] = {\n" + << IndentStr << " "; + + ListSeparator LS; + for (unsigned i = 0, e = RegList->size(); i != e; ++i) + O << LS << getQualifiedName(RegList->getElementAsRecord(i)); + O << "\n" << IndentStr << "};\n"; + + O << IndentStr << "for (MCPhysReg RegB : RegList" << Counter << ") {\n" + << IndentStr << " if (State.getTargetRegisterInfo()" + << ".isSuperOrSubRegisterEq(RegA, RegB)) {\n" + << IndentStr << " return true;\n" + << IndentStr << " }\n" + << IndentStr << "}\n"; + } + } else if (Action->isSubClassOf("CCAssignToRegWithShadow")) { + ListInit *RegList = Action->getValueAsListInit("RegList"); + + if (RegList->size() == 1) { + O << IndentStr << "if (State.getTargetRegisterInfo()" + << ".isSuperOrSubRegisterEq(RegA, " + << getQualifiedName(RegList->getElementAsRecord(0)) << "))\n" + << IndentStr << " return true;\n"; + } else { + O << IndentStr << "static const MCPhysReg RegList" << ++Counter + << "[] = {\n"; + O << IndentStr << " "; + + ListSeparator LS; + for (unsigned i = 0, e = RegList->size(); i != e; ++i) + O << LS << getQualifiedName(RegList->getElementAsRecord(i)); + O << "\n" << IndentStr << "};\n"; + + O << IndentStr << "for (MCPhysReg RegB : RegList" << Counter << ") {\n" + << IndentStr << " if (State.getTargetRegisterInfo()" + << ".isSuperOrSubRegisterEq(RegA, RegB)) {\n" + << IndentStr << " return true;\n" + << IndentStr << " }\n" + << IndentStr << "}\n"; + } + } else if (Action->isSubClassOf("CCPromoteToType") || + Action->isSubClassOf("CCPromoteToUpperBitsInType") || + Action->isSubClassOf("CCBitConvertToType") || + Action->isSubClassOf("CCTruncToType") || + Action->isSubClassOf("CCPassIndirect")) { + Record *DestTy = Action->getValueAsDef("DestTy"); + MVT::SimpleValueType DestVT = getValueType(DestTy); + O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n"; + } else if (Action->isSubClassOf("CCCustom")) { + O << IndentStr << "if (" << Action->getValueAsString("FuncName") + << "_IsCCReg(RegA, ValNo, ValVT, LocVT, ArgFlags, State))\n"; + O << IndentStr << " return true;\n"; + } else if (Action->isSubClassOf("CCAssignToStack") || + Action->isSubClassOf("CCAssignToStackWithShadow") || + Action->isSubClassOf("CCPassByVal")) { + // Do nothing. + } else { + errs() << *Action; + PrintFatalError(Action->getLoc(), "Unknown CCAction!"); + } +} + namespace llvm { void EmitCallingConv(RecordKeeper &RK, raw_ostream &OS) {