Index: llvm/lib/Target/SystemZ/SystemZISelLowering.cpp =================================================================== --- llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -1580,8 +1580,15 @@ SDValue ArgValue = OutVals[I]; if (VA.getLocInfo() == CCValAssign::Indirect) { - // Store the argument in a stack slot and pass its address. - SDValue SpillSlot = DAG.CreateStackTemporary(Outs[I].ArgVT); + // Store the argument in a stack slot and pass its address. Make sure + // that the full stack space is allocated for a promoted and split arg. + EVT OutVT = Outs[I].ArgVT; + Type *OrigArgType = CLI.Args[Outs[I].OrigArgIndex].Ty; + EVT OrigArgVT = getValueType(MF.getDataLayout(), OrigArgType); + if (OrigArgVT.getSizeInBits() > 64 && + getTypeAction(*DAG.getContext(), OrigArgVT) == TypePromoteInteger) + OutVT = getTypeToTransformTo(*DAG.getContext(), OrigArgVT); + SDValue SpillSlot = DAG.CreateStackTemporary(OutVT); int FI = cast(SpillSlot)->getIndex(); MemOpChains.push_back( DAG.getStore(Chain, DL, ArgValue, SpillSlot, Index: llvm/test/CodeGen/SystemZ/args-11.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/SystemZ/args-11.ll @@ -0,0 +1,54 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; Test outgoing promoted arguments that are split (and passed by reference). +; +; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s + +; The i96 arg is promoted to i128 and should get the full stack space. +declare void @fn1(i96) +define i32 @fn2() { +; CHECK-LABEL: fn2: +; CHECK: # %bb.0: +; CHECK-NEXT: stmg %r14, %r15, 112(%r15) +; CHECK-NEXT: .cfi_offset %r14, -48 +; CHECK-NEXT: .cfi_offset %r15, -40 +; CHECK-NEXT: aghi %r15, -184 +; CHECK-NEXT: .cfi_def_cfa_offset 344 +; CHECK-NEXT: mvhi 180(%r15), -1 +; CHECK-NEXT: mvghi 168(%r15), 0 +; CHECK-NEXT: la %r2, 160(%r15) +; CHECK-NEXT: mvghi 160(%r15), 0 +; CHECK-NEXT: brasl %r14, fn1@PLT +; CHECK-NEXT: l %r2, 180(%r15) +; CHECK-NEXT: lmg %r14, %r15, 296(%r15) +; CHECK-NEXT: br %r14 + %1 = alloca i32 + store i32 -1, i32* %1 + call void @fn1(i96 0) + %2 = load i32, i32* %1 + ret i32 %2 +} + +declare void @fn3(i136) +define i32 @fn4() { +; CHECK-LABEL: fn4: +; CHECK: # %bb.0: +; CHECK-NEXT: stmg %r14, %r15, 112(%r15) +; CHECK-NEXT: .cfi_offset %r14, -48 +; CHECK-NEXT: .cfi_offset %r15, -40 +; CHECK-NEXT: aghi %r15, -200 +; CHECK-NEXT: .cfi_def_cfa_offset 360 +; CHECK-NEXT: mvhi 196(%r15), -1 +; CHECK-NEXT: mvghi 176(%r15), 0 +; CHECK-NEXT: mvghi 168(%r15), 0 +; CHECK-NEXT: la %r2, 160(%r15) +; CHECK-NEXT: mvghi 160(%r15), 0 +; CHECK-NEXT: brasl %r14, fn3@PLT +; CHECK-NEXT: l %r2, 196(%r15) +; CHECK-NEXT: lmg %r14, %r15, 312(%r15) +; CHECK-NEXT: br %r14 + %1 = alloca i32 + store i32 -1, i32* %1 + call void @fn3(i136 0) + %2 = load i32, i32* %1 + ret i32 %2 +}