From: Diana Picus Date: Thu, 2 Feb 2017 14:01:00 +0000 (+0000) Subject: [ARM] GlobalISel: Lower pointer args and returns X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c53d2b802ea4bcfe513b54fa06907183b1470eee;p=llvm [ARM] GlobalISel: Lower pointer args and returns It is important to change the ArgInfo's type from pointer to integer, otherwise the CC assign function won't know what to do. Instead of hacking it up, we use ComputeValueVTs and introduce some of the helpers that we will need later on for lowering more complex types. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@293889 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/ARM/ARMCallLowering.cpp b/lib/Target/ARM/ARMCallLowering.cpp index c5b49ef70fd..f37d6d7b1d0 100644 --- a/lib/Target/ARM/ARMCallLowering.cpp +++ b/lib/Target/ARM/ARMCallLowering.cpp @@ -19,6 +19,7 @@ #include "ARMISelLowering.h" #include "ARMSubtarget.h" +#include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" @@ -74,6 +75,25 @@ struct FuncReturnHandler : public CallLowering::ValueHandler { }; } // End anonymous namespace. +void ARMCallLowering::splitToValueTypes(const ArgInfo &OrigArg, + SmallVectorImpl &SplitArgs, + const DataLayout &DL, + MachineRegisterInfo &MRI) const { + const ARMTargetLowering &TLI = *getTLI(); + LLVMContext &Ctx = OrigArg.Ty->getContext(); + + SmallVector SplitVTs; + SmallVector Offsets; + ComputeValueVTs(TLI, DL, OrigArg.Ty, SplitVTs, &Offsets, 0); + + assert(SplitVTs.size() == 1 && "Unsupported type"); + + // Even if there is no splitting to do, we still want to replace the original + // type (e.g. pointer type -> integer). + SplitArgs.emplace_back(OrigArg.Reg, SplitVTs[0].getTypeForEVT(Ctx), + OrigArg.Flags, OrigArg.IsFixed); +} + /// Lower the return value for the already existing \p Ret. This assumes that /// \p MIRBuilder's insertion point is correct. bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder, @@ -91,14 +111,16 @@ bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder, if (!isSupportedType(DL, TLI, Val->getType())) return false; - CCAssignFn *AssignFn = - TLI.CCAssignFnForReturn(F.getCallingConv(), F.isVarArg()); - + SmallVector SplitVTs; ArgInfo RetInfo(VReg, Val->getType()); setArgFlags(RetInfo, AttributeSet::ReturnIndex, DL, F); + splitToValueTypes(RetInfo, SplitVTs, DL, MF.getRegInfo()); + + CCAssignFn *AssignFn = + TLI.CCAssignFnForReturn(F.getCallingConv(), F.isVarArg()); FuncReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret, AssignFn); - return handleAssignments(MIRBuilder, RetInfo, RetHandler); + return handleAssignments(MIRBuilder, SplitVTs, RetHandler); } bool ARMCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, @@ -179,7 +201,8 @@ bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, if (F.isVarArg()) return false; - auto DL = MIRBuilder.getMF().getDataLayout(); + auto &MF = MIRBuilder.getMF(); + auto DL = MF.getDataLayout(); auto &TLI = *getTLI(); if (TLI.getSubtarget()->isThumb()) @@ -198,7 +221,7 @@ bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, for (auto &Arg : Args) { ArgInfo AInfo(VRegs[Idx], Arg.getType()); setArgFlags(AInfo, Idx + 1, DL, F); - ArgInfos.push_back(AInfo); + splitToValueTypes(AInfo, ArgInfos, DL, MF.getRegInfo()); Idx++; } diff --git a/lib/Target/ARM/ARMCallLowering.h b/lib/Target/ARM/ARMCallLowering.h index 6a1b886b501..7c3b3ddec74 100644 --- a/lib/Target/ARM/ARMCallLowering.h +++ b/lib/Target/ARM/ARMCallLowering.h @@ -37,6 +37,12 @@ public: private: bool lowerReturnVal(MachineIRBuilder &MIRBuilder, const Value *Val, unsigned VReg, MachineInstrBuilder &Ret) const; + + /// Split an argument into one or more arguments that the CC lowering can cope + /// with (e.g. replace pointers with integers). + void splitToValueTypes(const ArgInfo &OrigArg, + SmallVectorImpl &SplitArgs, + const DataLayout &DL, MachineRegisterInfo &MRI) const; }; } // End of namespace llvm #endif diff --git a/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll b/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll index a20a108d8a9..fa17271b547 100644 --- a/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll +++ b/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll @@ -134,3 +134,41 @@ entry: %sum = add i8 %p2, %p4 ret i8 %sum } + +define i16 @test_ptr_arg(i16* %p) { +; CHECK-LABEL: name: test_ptr_arg +; CHECK: liveins: %r0 +; CHECK: [[VREGP:%[0-9]+]](p0) = COPY %r0 +; CHECK: [[VREGV:%[0-9]+]](s16) = G_LOAD [[VREGP]](p0) +entry: + %v = load i16, i16* %p + ret i16 %v +} + +define i32* @test_ptr_ret(i32** %p) { +; Test pointer returns and pointer-to-pointer arguments +; CHECK-LABEL: name: test_ptr_ret +; CHECK: liveins: %r0 +; CHECK: [[VREGP:%[0-9]+]](p0) = COPY %r0 +; CHECK: [[VREGV:%[0-9]+]](p0) = G_LOAD [[VREGP]](p0) +; CHECK: %r0 = COPY [[VREGV]] +; CHECK: BX_RET 14, _, implicit %r0 +entry: + %v = load i32*, i32** %p + ret i32* %v +} + +define i32 @test_ptr_arg_on_stack(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32* %p) { +; CHECK-LABEL: name: test_ptr_arg_on_stack +; CHECK: fixedStack: +; CHECK: id: [[P:[0-9]+]]{{.*}}offset: 0{{.*}}size: 4 +; CHECK: liveins: %r0, %r1, %r2, %r3 +; CHECK: [[FIP:%[0-9]+]]{{.*}} = G_FRAME_INDEX %fixed-stack.[[P]] +; CHECK: [[VREGP:%[0-9]+]](p0) = G_LOAD [[FIP]](p0) +; CHECK: [[VREGV:%[0-9]+]](s32) = G_LOAD [[VREGP]](p0) +; CHECK: %r0 = COPY [[VREGV]] +; CHECK: BX_RET 14, _, implicit %r0 +entry: + %v = load i32, i32* %p + ret i32 %v +} diff --git a/test/CodeGen/ARM/GlobalISel/arm-isel.ll b/test/CodeGen/ARM/GlobalISel/arm-isel.ll index f5b706e7d21..2b44cd20830 100644 --- a/test/CodeGen/ARM/GlobalISel/arm-isel.ll +++ b/test/CodeGen/ARM/GlobalISel/arm-isel.ll @@ -110,3 +110,32 @@ entry: %sum = add i8 %p2, %p4 ret i8 %sum } + +define i32 @test_ptr_arg_in_reg(i32* %p) { +; CHECK-LABEL: test_ptr_arg_in_reg: +; CHECK: ldr r0, [r0] +; CHECK: bx lr +entry: + %v = load i32, i32* %p + ret i32 %v +} + +define i32 @test_ptr_arg_on_stack(i32 %f0, i32 %f1, i32 %f2, i32 %f3, i32* %p) { +; CHECK-LABEL: test_ptr_arg_on_stack: +; CHECK: mov r0, sp +; CHECK: ldr r0, [r0] +; CHECK: ldr r0, [r0] +; CHECK: bx lr +entry: + %v = load i32, i32* %p + ret i32 %v +} + +define i8* @test_ptr_ret(i8** %p) { +; CHECK-LABEL: test_ptr_ret: +; CHECK: ldr r0, [r0] +; CHECK: bx lr +entry: + %v = load i8*, i8** %p + ret i8* %v +}