diff options
-rw-r--r-- | llvm/lib/Target/ARM/ARMCallLowering.cpp | 35 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMCallLowering.h | 6 | ||||
-rw-r--r-- | llvm/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll | 38 | ||||
-rw-r--r-- | llvm/test/CodeGen/ARM/GlobalISel/arm-isel.ll | 29 |
4 files changed, 102 insertions, 6 deletions
diff --git a/llvm/lib/Target/ARM/ARMCallLowering.cpp b/llvm/lib/Target/ARM/ARMCallLowering.cpp index c5b49ef70fd..f37d6d7b1d0 100644 --- a/llvm/lib/Target/ARM/ARMCallLowering.cpp +++ b/llvm/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<ArgInfo> &SplitArgs, + const DataLayout &DL, + MachineRegisterInfo &MRI) const { + const ARMTargetLowering &TLI = *getTLI<ARMTargetLowering>(); + LLVMContext &Ctx = OrigArg.Ty->getContext(); + + SmallVector<EVT, 4> SplitVTs; + SmallVector<uint64_t, 4> 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<ArgInfo, 4> 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<ARMTargetLowering>(); 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/llvm/lib/Target/ARM/ARMCallLowering.h b/llvm/lib/Target/ARM/ARMCallLowering.h index 6a1b886b501..7c3b3ddec74 100644 --- a/llvm/lib/Target/ARM/ARMCallLowering.h +++ b/llvm/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<ArgInfo> &SplitArgs, + const DataLayout &DL, MachineRegisterInfo &MRI) const; }; } // End of namespace llvm #endif diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll b/llvm/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll index a20a108d8a9..fa17271b547 100644 --- a/llvm/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll +++ b/llvm/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/llvm/test/CodeGen/ARM/GlobalISel/arm-isel.ll b/llvm/test/CodeGen/ARM/GlobalISel/arm-isel.ll index f5b706e7d21..2b44cd20830 100644 --- a/llvm/test/CodeGen/ARM/GlobalISel/arm-isel.ll +++ b/llvm/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 +} |