gandhi21299 updated this revision to Diff 336249. gandhi21299 added a comment.
- enclosing classes in PPCCallLowering,h within the llvm namespace Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D99812/new/ https://reviews.llvm.org/D99812 Files: llvm/lib/Target/PowerPC/GISel/PPCCallLowering.cpp llvm/lib/Target/PowerPC/GISel/PPCCallLowering.h llvm/lib/Target/PowerPC/PPCISelLowering.cpp llvm/lib/Target/PowerPC/PPCISelLowering.h llvm/test/CodeGen/PowerPC/GlobalISel/irtranslator-args-lowering.ll llvm/test/CodeGen/PowerPC/GlobalISel/irtranslator-ret.ll
Index: llvm/test/CodeGen/PowerPC/GlobalISel/irtranslator-ret.ll =================================================================== --- llvm/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 -} Index: llvm/test/CodeGen/PowerPC/GlobalISel/irtranslator-args-lowering.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/PowerPC/GlobalISel/irtranslator-args-lowering.ll @@ -0,0 +1,188 @@ +; 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: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) + ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY $x4 + ; CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) + ; CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY $x5 + ; CHECK: [[TRUNC2:%[0-9]+]]:_(s32) = 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: [[TRUNC4:%[0-9]+]]:_(s32) = G_TRUNC [[COPY4]](s64) + ; CHECK: [[COPY5:%[0-9]+]]:_(s64) = COPY $x8 + ; CHECK: [[TRUNC5:%[0-9]+]]:_(s32) = G_TRUNC [[COPY5]](s64) + ; CHECK: [[COPY6:%[0-9]+]]:_(s64) = COPY $x9 + ; CHECK: [[TRUNC6:%[0-9]+]]:_(s32) = G_TRUNC [[COPY6]](s64) + ; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<7 x s32>) = G_BUILD_VECTOR [[TRUNC]](s32), [[TRUNC1]](s32), [[TRUNC2]](s32), [[TRUNC3]](s32), [[TRUNC4]](s32), [[TRUNC5]](s32), [[TRUNC6]](s32) + ; CHECK: [[TRUNC7:%[0-9]+]]:_(<7 x s8>) = G_TRUNC [[BUILD_VECTOR]](<7 x s32>) + ; 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]+]]:_(s64) = COPY $f1 + ; CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) + ; 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]+]]:_(s64) = COPY $f1 + ; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) + ; 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 +} Index: llvm/lib/Target/PowerPC/PPCISelLowering.h =================================================================== --- llvm/lib/Target/PowerPC/PPCISelLowering.h +++ llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -1061,6 +1061,9 @@ HasNest(HasNest), NoMerge(NoMerge) {} }; + CCAssignFn *ccAssignFnForCall(CallingConv::ID CC, bool Return, + bool IsVarArg) const; + private: struct ReuseLoadInfo { SDValue Ptr; Index: llvm/lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -16710,3 +16710,16 @@ return SDValue(); } + +// TODO Extend this method by adding more calling convention support +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; + } +} Index: llvm/lib/Target/PowerPC/GISel/PPCCallLowering.h =================================================================== --- llvm/lib/Target/PowerPC/GISel/PPCCallLowering.h +++ llvm/lib/Target/PowerPC/GISel/PPCCallLowering.h @@ -35,6 +35,39 @@ bool lowerCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info) const override; }; + +class PPCIncomingValueHandler : public CallLowering::IncomingValueHandler { +public: + PPCIncomingValueHandler(MachineIRBuilder &MIRBuilder, + MachineRegisterInfo &MRI, CCAssignFn AssignFn) + : CallLowering::IncomingValueHandler(MIRBuilder, MRI, AssignFn) {} + + 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, + CCAssignFn AssignFn) + : PPCIncomingValueHandler(MIRBuilder, MRI, AssignFn) {} +}; + } // end namespace llvm #endif Index: llvm/lib/Target/PowerPC/GISel/PPCCallLowering.cpp =================================================================== --- llvm/lib/Target/PowerPC/GISel/PPCCallLowering.cpp +++ llvm/lib/Target/PowerPC/GISel/PPCCallLowering.cpp @@ -13,6 +13,8 @@ //===----------------------------------------------------------------------===// #include "PPCCallLowering.h" +#include "PPCISelLowering.h" +#include "llvm/CodeGen/GlobalISel/CallLowering.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #include "llvm/Support/Debug.h" @@ -36,18 +38,167 @@ return true; } +bool PPCCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, + CallLoweringInfo &Info) const { + return false; +} + +/** + * @brief Lower incoming arguments into generic MIR, this method is responsible + * for splitting aggregate arguments into multiple single value types as well + * as setting argument flags for each argument. This method depends on a + * calling convention selector to select the correct calling convention based + * on the F.getCallingConv(). Finally, FormalArgHandler takes care of the reg + * assignments. + * @param MIRBuilder + * @param F + * @param VRegs + * @param FLI + * @return whether or not the arguments assignment was successful + */ bool PPCCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, ArrayRef<ArrayRef<Register>> VRegs, FunctionLoweringInfo &FLI) const { + MachineFunction &MF = MIRBuilder.getMF(); + MachineBasicBlock &MBB = MIRBuilder.getMBB(); + MachineRegisterInfo &MRI = MF.getRegInfo(); + const auto &DL = F.getParent()->getDataLayout(); + const auto &TLI = *getTLI<PPCTargetLowering>(); + + // initialize instruction writer + if (!MBB.empty()) + MIRBuilder.setInstr(*MBB.begin()); + + // loop over each arg, set flags and split to single value types + SmallVector<ArgInfo, 8> InArgs; + unsigned I = 0; + for (const auto &Arg : F.args()) { + if (DL.getTypeStoreSize(Arg.getType()).isZero()) + continue; - // 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(); + ArgInfo OrigArg{VRegs[I], Arg.getType()}; + setArgFlags(OrigArg, I + AttributeList::FirstArgIndex, DL, F); + splitToValueTypes(OrigArg, InArgs, DL, F.getCallingConv()); + ++I; + } + + // select calling convention function pointer + CCAssignFn *AssignFn = + TLI.ccAssignFnForCall(F.getCallingConv(), false, F.isVarArg()); + + // insert necessary instructions for incoming arg values. + FormalArgHandler Handler(MIRBuilder, MRI, AssignFn); + return handleAssignments(MIRBuilder, InArgs, Handler, F.getCallingConv(), + F.isVarArg()); } -bool PPCCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, - CallLoweringInfo &Info) const { - return false; +//=== PPC Incoming value handler methods ----------------------------------===// + +/** + * @brief generates COPYs of values to registers and G_TRUNCs them whenever + * the bit widths mismatch. Formal arguments lowering depends on this method + * for argument value assignment to registers. + * @param ValVReg + * @param PhysReg + * @param VA + */ +void PPCIncomingValueHandler::assignValueToReg(Register ValVReg, + Register PhysReg, + CCValAssign &VA) { + markPhysRegUsed(PhysReg); + + switch (VA.getLocInfo()) { + default: { + // If we are copying the value from a physical register with the + // size larger than the size of the value itself - build the copy + // of the phys reg first and then build the truncation of that copy. + // The example of that would be copying from xmm0 to s32, for which + // case ValVT == LocVT == MVT::f32. If LocSize and ValSize are not equal + // we expect this to be handled in SExt/ZExt/AExt case. + unsigned PhysRegSize = + MRI.getTargetRegisterInfo()->getRegSizeInBits(PhysReg, MRI); + unsigned ValSize = VA.getValVT().getSizeInBits(); + unsigned LocSize = VA.getLocVT().getSizeInBits(); + if (PhysRegSize > ValSize && LocSize == ValSize) { + auto Copy = MIRBuilder.buildCopy(LLT::scalar(PhysRegSize), PhysReg); + MIRBuilder.buildTrunc(ValVReg, Copy); + return; + } + + MIRBuilder.buildCopy(ValVReg, PhysReg); + break; + } + 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; + } + } +} + +/** + * @brief Generate a load instruction to load value from the given address. + * @param ValVReg + * @param Addr + * @param Size + * @param MPO + * @param 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); + }; + + // if address is sign-extended or zero-extended, load into a 64-bit register + // and then truncate it + if (VA.getLocInfo() == CCValAssign::SExt or + VA.getLocInfo() == CCValAssign::ZExt) { + Size = 4; + auto LoadVReg = BuildLoad(MIRBuilder, MPO, Size, LLT::scalar(64), Addr); + MIRBuilder.buildTrunc(ValVReg, LoadVReg); + } + // otherwise, simply load the address into the destination register + else { + 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); + + // TODO get the bitwidth (second argument) from TargetMachine or machine info + auto AddrReg = MIRBuilder.buildFrameIndex(LLT::pointer(0, 64), FI); + + StackUsed = std::max(StackUsed, Size + Offset); + return AddrReg.getReg(0); +} + +//=== FormalArgHandler methods --------------------------------------------===// + +/** + * @brief mark incoming register values as live + * @param PhysReg + */ +void FormalArgHandler::markPhysRegUsed(unsigned PhysReg) { + MIRBuilder.getMRI()->addLiveIn(PhysReg); + MIRBuilder.getMBB().addLiveIn(PhysReg); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits