diff --git a/lib/Target/PowerPC/GISel/PPCCallLowering.cpp b/lib/Target/PowerPC/GISel/PPCCallLowering.cpp index e8f8cbfee6e..2fc2c8a213e 100644 --- a/lib/Target/PowerPC/GISel/PPCCallLowering.cpp +++ b/lib/Target/PowerPC/GISel/PPCCallLowering.cpp @@ -13,7 +13,13 @@ //===----------------------------------------------------------------------===// #include "PPCCallLowering.h" +#include "PPCISelLowering.h" +#include "PPCSubtarget.h" +#include "PPCTargetMachine.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/GlobalISel/CallLowering.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" +#include "llvm/CodeGen/TargetCallingConv.h" #include "llvm/Support/Debug.h" #define DEBUG_TYPE "ppc-call-lowering" @@ -36,18 +42,85 @@ bool PPCCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, return true; } -bool PPCCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, - const Function &F, - ArrayRef> VRegs, - FunctionLoweringInfo &FLI) const { - - // If VRegs is empty, then there are no formal arguments to lower and thus can - // always return true. If there are formal arguments, we currently do not - // handle them and thus return false. - return VRegs.empty(); -} - bool PPCCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info) const { return false; } + +bool PPCCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, + const Function &F, + ArrayRef> VRegs, + FunctionLoweringInfo &FLI) const { + MachineFunction &MF = MIRBuilder.getMF(); + MachineRegisterInfo &MRI = MF.getRegInfo(); + const auto &DL = F.getParent()->getDataLayout(); + auto &TLI = *getTLI(); + + // Loop over each arg, set flags and split to single value types + SmallVector SplitArgs; + unsigned I = 0; + for (const auto &Arg : F.args()) { + if (DL.getTypeStoreSize(Arg.getType()).isZero()) + continue; + + ArgInfo OrigArg{VRegs[I], Arg}; + setArgFlags(OrigArg, I + AttributeList::FirstArgIndex, DL, F); + splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv()); + ++I; + } + + CCAssignFn *AssignFn = + TLI.ccAssignFnForCall(F.getCallingConv(), false, F.isVarArg()); + IncomingValueAssigner ArgAssigner(AssignFn); + FormalArgHandler ArgHandler(MIRBuilder, MRI); + return determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs, + MIRBuilder, F.getCallingConv(), + F.isVarArg()); +} + +void PPCIncomingValueHandler::assignValueToReg(Register ValVReg, + Register PhysReg, + CCValAssign &VA) { + markPhysRegUsed(PhysReg); + IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA); +} + +void PPCIncomingValueHandler::assignValueToAddress(Register ValVReg, + Register Addr, uint64_t Size, + MachinePointerInfo &MPO, + CCValAssign &VA) { + assert((Size == 1 || Size == 2 || Size == 4 || Size == 8) && + "Unsupported size"); + + // define a lambda expression to load value + auto BuildLoad = [](MachineIRBuilder &MIRBuilder, MachinePointerInfo &MPO, + uint64_t Size, const DstOp &Res, Register Addr) { + MachineFunction &MF = MIRBuilder.getMF(); + auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, Size, + inferAlignFromPtrInfo(MF, MPO)); + return MIRBuilder.buildLoad(Res, Addr, *MMO); + }; + + BuildLoad(MIRBuilder, MPO, Size, ValVReg, Addr); +} + +Register PPCIncomingValueHandler::getStackAddress(uint64_t Size, int64_t Offset, + MachinePointerInfo &MPO, + ISD::ArgFlagsTy Flags) { + auto &MFI = MIRBuilder.getMF().getFrameInfo(); + const bool IsImmutable = !Flags.isByVal(); + int FI = MFI.CreateFixedObject(Size, Offset, IsImmutable); + MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); + + // Build Frame Index based on whether the machine is 32-bit or 64-bit + llvm::LLT FramePtr = LLT::pointer( + 0, MIRBuilder.getMF().getDataLayout().getPointerSizeInBits()); + MachineInstrBuilder AddrReg = MIRBuilder.buildFrameIndex(FramePtr, FI); + StackUsed = std::max(StackUsed, Size + Offset); + return AddrReg.getReg(0); +} + +void FormalArgHandler::markPhysRegUsed(unsigned PhysReg) { + MIRBuilder.getMRI()->addLiveIn(PhysReg); + MIRBuilder.getMBB().addLiveIn(PhysReg); +} diff --git a/lib/Target/PowerPC/GISel/PPCCallLowering.h b/lib/Target/PowerPC/GISel/PPCCallLowering.h index 5a449f4cab1..0d46374d41f 100644 --- a/lib/Target/PowerPC/GISel/PPCCallLowering.h +++ b/lib/Target/PowerPC/GISel/PPCCallLowering.h @@ -35,6 +35,38 @@ public: bool lowerCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info) const override; }; + +class PPCIncomingValueHandler : public CallLowering::IncomingValueHandler { +public: + PPCIncomingValueHandler(MachineIRBuilder &MIRBuilder, + MachineRegisterInfo &MRI) + : CallLowering::IncomingValueHandler(MIRBuilder, MRI) {} + + uint64_t StackUsed; + +private: + void assignValueToReg(Register ValVReg, Register PhysReg, + CCValAssign &VA) override; + + void assignValueToAddress(Register ValVReg, Register Addr, uint64_t Size, + MachinePointerInfo &MPO, CCValAssign &VA) override; + + Register getStackAddress(uint64_t Size, int64_t Offset, + MachinePointerInfo &MPO, + ISD::ArgFlagsTy Flags) override; + + virtual void markPhysRegUsed(unsigned PhysReg) = 0; +}; + +class FormalArgHandler : public PPCIncomingValueHandler { + + void markPhysRegUsed(unsigned PhysReg) override; + +public: + FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) + : PPCIncomingValueHandler(MIRBuilder, MRI) {} +}; + } // end namespace llvm #endif diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 6de883db09c..4e42c029fce 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -17360,3 +17360,14 @@ PPC::AddrMode PPCTargetLowering::SelectOptimalAddrMode(const SDNode *Parent, } return Mode; } + +CCAssignFn *PPCTargetLowering::ccAssignFnForCall(CallingConv::ID CC, + bool Return, + bool IsVarArg) const { + switch (CC) { + case CallingConv::Cold: + return (Return ? RetCC_PPC_Cold : CC_PPC64_ELF_FIS); + default: + return CC_PPC64_ELF_FIS; + } +} \ No newline at end of file diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h index e6f331dcb4d..fd9ec59845f 100644 --- a/lib/Target/PowerPC/PPCISelLowering.h +++ b/lib/Target/PowerPC/PPCISelLowering.h @@ -1116,6 +1116,9 @@ namespace llvm { HasNest(HasNest), NoMerge(NoMerge) {} }; + CCAssignFn *ccAssignFnForCall(CallingConv::ID CC, bool Return, + bool IsVarArg) const; + private: struct ReuseLoadInfo { SDValue Ptr; diff --git a/test/CodeGen/PowerPC/GlobalISel/irtranslator-args-lowering.ll b/test/CodeGen/PowerPC/GlobalISel/irtranslator-args-lowering.ll new file mode 100644 index 00000000000..4217f05cba7 --- /dev/null +++ b/test/CodeGen/PowerPC/GlobalISel/irtranslator-args-lowering.ll @@ -0,0 +1,181 @@ +; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -global-isel -verify-machineinstrs -stop-after=irtranslator < %s | FileCheck %s + +%struct.A = type { i8, float, i32, i32, i32 } + +define void @f() { + ; CHECK-LABEL: name: f + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: BLR8 implicit $lr8, implicit $rm + ret void +} + +define void @foo1(i32 %x){ + ; CHECK-LABEL: name: foo1 + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: liveins: $x3 + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x3 + ; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) + ; CHECK: BLR8 implicit $lr8, implicit $rm + ret void +} + +define void @foo2(i64 %x){ + ; CHECK-LABEL: name: foo2 + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: liveins: $x3 + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x3 + ; CHECK: BLR8 implicit $lr8, implicit $rm + ret void +} + +define void @foo3(<7 x i8> %x) { + ; CHECK-LABEL: name: foo3 + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: liveins: $x3, $x4, $x5, $x6, $x7, $x8, $x9 + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x3 + ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY $x4 + ; CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY $x5 + ; CHECK: [[COPY3:%[0-9]+]]:_(s64) = COPY $x6 + ; CHECK: [[COPY4:%[0-9]+]]:_(s64) = COPY $x7 + ; CHECK: [[COPY5:%[0-9]+]]:_(s64) = COPY $x8 + ; CHECK: [[COPY6:%[0-9]+]]:_(s64) = COPY $x9 + ; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<7 x s64>) = G_BUILD_VECTOR [[COPY]](s64), [[COPY1]](s64), [[COPY2]](s64), [[COPY3]](s64), [[COPY4]](s64), [[COPY5]](s64), [[COPY6]](s64) + ; CHECK: [[TRUNC7:%[0-9]+]]:_(<7 x s8>) = G_TRUNC [[BUILD_VECTOR]](<7 x s64>) + ; CHECK: BLR8 implicit $lr8, implicit $rm + ret void +} + + + +define void @foo_notrunc(<7 x i64> %x) { + ; CHECK-LABEL: name: foo_notrunc + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: liveins: $x3, $x4, $x5, $x6, $x7, $x8, $x9 + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x3 + ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY $x4 + ; CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY $x5 + ; CHECK: [[COPY3:%[0-9]+]]:_(s64) = COPY $x6 + ; CHECK: [[COPY4:%[0-9]+]]:_(s64) = COPY $x7 + ; CHECK: [[COPY5:%[0-9]+]]:_(s64) = COPY $x8 + ; CHECK: [[COPY6:%[0-9]+]]:_(s64) = COPY $x9 + ; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<7 x s64>) = G_BUILD_VECTOR [[COPY]](s64), [[COPY1]](s64), [[COPY2]](s64), [[COPY3]](s64), [[COPY4]](s64), [[COPY5]](s64), [[COPY6]](s64) + ; CHECK: BLR8 implicit $lr8, implicit $rm + ret void +} + +define void @foo_pt(<7 x i8>* %x) { + ; CHECK-LABEL: name: foo_pt + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: liveins: $x3 + ; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x3 + ; CHECK: BLR8 implicit $lr8, implicit $rm + ret void +} + +define dso_local void @foo_struct(%struct.A %a) #0 { + ; CHECK-LABEL: name: foo_struct + ; CHECK: bb.1.entry: + ; CHECK: liveins: $f1, $x3, $x4, $x5, $x6 + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x3 + ; CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s64) + ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY $f1 + ; CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY $x4 + ; CHECK: [[TRUNC2:%[0-9]+]]:_(s32) = G_TRUNC [[COPY2]](s64) + ; CHECK: [[COPY3:%[0-9]+]]:_(s64) = COPY $x5 + ; CHECK: [[TRUNC3:%[0-9]+]]:_(s32) = G_TRUNC [[COPY3]](s64) + ; CHECK: [[COPY4:%[0-9]+]]:_(s64) = COPY $x6 + ; CHECK: [[TRUNC4:%[0-9]+]]:_(s32) = G_TRUNC [[COPY4]](s64) + ; CHECK: BLR8 implicit $lr8, implicit $rm +entry: + ret void +} + +define void @foo_int(i32* %x) { + ; CHECK-LABEL: name: foo_int + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: liveins: $x3 + ; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x3 + ; CHECK: BLR8 implicit $lr8, implicit $rm + ret void +} + +define void @foo(float* %x) { + ; CHECK-LABEL: name: foo + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: liveins: $x3 + ; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x3 + ; CHECK: BLR8 implicit $lr8, implicit $rm + ret void +} + +define void @foo_multiple(i1 %a, i8 %b, i16 %c, i32 %d, i64 %e, i128 %f){ + ; CHECK-LABEL: name: foo_multiple + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: liveins: $x3, $x4, $x5, $x6, $x7, $x8, $x9 + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x3 + ; CHECK: [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[COPY]](s64) + ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY $x4 + ; CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s64) + ; CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY $x5 + ; CHECK: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[COPY2]](s64) + ; CHECK: [[COPY3:%[0-9]+]]:_(s64) = COPY $x6 + ; CHECK: [[TRUNC3:%[0-9]+]]:_(s32) = G_TRUNC [[COPY3]](s64) + ; CHECK: [[COPY4:%[0-9]+]]:_(s64) = COPY $x7 + ; CHECK: [[COPY5:%[0-9]+]]:_(s64) = COPY $x8 + ; CHECK: [[COPY6:%[0-9]+]]:_(s64) = COPY $x9 + ; CHECK: [[MV:%[0-9]+]]:_(s128) = G_MERGE_VALUES [[COPY5]](s64), [[COPY6]](s64) + ; CHECK: BLR8 implicit $lr8, implicit $rm + ret void +} + +define void @foo_multiple_same_ty(i64 %x, i64 %y, i64 %z){ + ; CHECK-LABEL: name: foo_multiple_same_ty + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: liveins: $x3, $x4, $x5 + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x3 + ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY $x4 + ; CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY $x5 + ; CHECK: BLR8 implicit $lr8, implicit $rm + ret void +} + +define void @foo_float(float %x) { + ; CHECK-LABEL: name: foo_float + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: liveins: $f1 + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $f1 + ; CHECK: BLR8 implicit $lr8, implicit $rm + ret void +} + +define void @foo_dbl(double %x) { + ; CHECK-LABEL: name: foo_dbl + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: liveins: $f1 + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $f1 + ; CHECK: BLR8 implicit $lr8, implicit $rm + ret void +} + +define void @foo_array([7 x i8] %x) { + ; CHECK-LABEL: name: foo_array + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: liveins: $x3, $x4, $x5, $x6, $x7, $x8, $x9 + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x3 + ; CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s64) + ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY $x4 + ; CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s64) + ; CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY $x5 + ; CHECK: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[COPY2]](s64) + ; CHECK: [[COPY3:%[0-9]+]]:_(s64) = COPY $x6 + ; CHECK: [[TRUNC3:%[0-9]+]]:_(s8) = G_TRUNC [[COPY3]](s64) + ; CHECK: [[COPY4:%[0-9]+]]:_(s64) = COPY $x7 + ; CHECK: [[TRUNC4:%[0-9]+]]:_(s8) = G_TRUNC [[COPY4]](s64) + ; CHECK: [[COPY5:%[0-9]+]]:_(s64) = COPY $x8 + ; CHECK: [[TRUNC5:%[0-9]+]]:_(s8) = G_TRUNC [[COPY5]](s64) + ; CHECK: [[COPY6:%[0-9]+]]:_(s64) = COPY $x9 + ; CHECK: [[TRUNC6:%[0-9]+]]:_(s8) = G_TRUNC [[COPY6]](s64) + ; CHECK: BLR8 implicit $lr8, implicit $rm + ret void +} diff --git a/test/CodeGen/PowerPC/GlobalISel/irtranslator-ret.ll b/test/CodeGen/PowerPC/GlobalISel/irtranslator-ret.ll deleted file mode 100644 index 86f27a126d5..00000000000 --- a/test/CodeGen/PowerPC/GlobalISel/irtranslator-ret.ll +++ /dev/null @@ -1,7 +0,0 @@ -; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -global-isel -verify-machineinstrs -stop-after=irtranslator < %s | FileCheck %s - -; CHECK: name: f -; CHECK: BLR8 -define void @f() { - ret void -}