diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -3878,7 +3878,8 @@ /// stack slot (instead of being passed in registers). ArgOffset, /// AvailableFPRs, and AvailableVRs must hold the current argument /// position, and will be updated to account for this argument. -static bool CalculateStackSlotUsed(EVT ArgVT, EVT OrigVT, ISD::ArgFlagsTy Flags, +static bool CalculateStackSlotUsed(const PPCSubtarget &Subtarget, EVT ArgVT, + EVT OrigVT, ISD::ArgFlagsTy Flags, unsigned PtrByteSize, unsigned LinkageSize, unsigned ParamAreaSize, unsigned &ArgOffset, unsigned &AvailableFPRs, @@ -3919,7 +3920,13 @@ --AvailableVRs; return false; } - } + } else if (Subtarget.isPPC64() && Subtarget.isELFv2ABI() && + Flags.getByValSize() >= 8) + // For 64-bit ELF v2, passing by value object whose size is no less than 8 + // bytes will be copied to parameter save area. This is for compatibility + // for other compiler which requires byval parameters to be stored in + // caller's parameter save area. + return true; return UseMemory; } @@ -4262,7 +4269,7 @@ if (Ins[i].Flags.isNest()) continue; - if (CalculateStackSlotUsed(Ins[i].VT, Ins[i].ArgVT, Ins[i].Flags, + if (CalculateStackSlotUsed(Subtarget, Ins[i].VT, Ins[i].ArgVT, Ins[i].Flags, PtrByteSize, LinkageSize, ParamAreaSize, NumBytes, AvailableFPRs, AvailableVRs)) HasParameterArea = true; @@ -4723,9 +4730,9 @@ for (const ISD::OutputArg& Param : Outs) { if (Param.Flags.isNest()) continue; - if (CalculateStackSlotUsed(Param.VT, Param.ArgVT, Param.Flags, PtrByteSize, - LinkageSize, ParamAreaSize, NumBytes, - AvailableFPRs, AvailableVRs)) + if (CalculateStackSlotUsed(Subtarget, Param.VT, Param.ArgVT, Param.Flags, + PtrByteSize, LinkageSize, ParamAreaSize, + NumBytes, AvailableFPRs, AvailableVRs)) return true; } return false; @@ -5961,9 +5968,10 @@ unsigned NumBytesTmp = NumBytes; for (unsigned i = 0; i != NumOps; ++i) { if (Outs[i].Flags.isNest()) continue; - if (CalculateStackSlotUsed(Outs[i].VT, Outs[i].ArgVT, Outs[i].Flags, - PtrByteSize, LinkageSize, ParamAreaSize, - NumBytesTmp, AvailableFPRs, AvailableVRs)) + if (CalculateStackSlotUsed(Subtarget, Outs[i].VT, Outs[i].ArgVT, + Outs[i].Flags, PtrByteSize, LinkageSize, + ParamAreaSize, NumBytesTmp, AvailableFPRs, + AvailableVRs)) HasParameterArea = true; } } diff --git a/llvm/test/CodeGen/PowerPC/byval.ll b/llvm/test/CodeGen/PowerPC/byval.ll --- a/llvm/test/CodeGen/PowerPC/byval.ll +++ b/llvm/test/CodeGen/PowerPC/byval.ll @@ -1,4 +1,3 @@ -; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -verify-machineinstrs < %s | FileCheck %s target datalayout = "e-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512" @@ -9,15 +8,15 @@ declare dso_local i32 @foo1(%struct* byval(%struct) %var) declare dso_local void @foo(%struct* %var) -; FIXME: for the byval parameter %x, now the memory for local variable and -; for parameter save area are overlap. +; for the byval parameter %x, make sure the memory for local variable and +; for parameter save area are not overlap. ; For the below case, -; the local variable space is r1 + 40 ~ r1 + 76 +; the local variable space is r1 + 104 ~ r1 + 140 ; the parameter save area is r1 + 32 ~ r1 + 68 define dso_local i32 @bar() { ; CHECK-LABEL: bar: -; CHECK: addi 30, 1, 40 +; CHECK: addi 30, 1, 104 ; CHECK: li 3, 16 ; CHECK: lxvd2x 0, 30, 3 ; CHECK: li 3, 48 @@ -25,7 +24,7 @@ ; CHECK: li 3, 32 ; CHECK: lxvd2x 0, 0, 30 ; CHECK: stxvd2x 0, 1, 3 -; CHECK: lwz 3, 72(1) +; CHECK: lwz 3, 136(1) ; CHECK: stw 3, 64(1) entry: %x = alloca %struct, align 4