Index: lib/Target/Mips/MipsISelLowering.h =================================================================== --- lib/Target/Mips/MipsISelLowering.h +++ lib/Target/Mips/MipsISelLowering.h @@ -573,13 +573,13 @@ MipsCCState &State) const; /// passByValArg - Pass a byval argument in registers or on stack. - void passByValArg(SDValue Chain, const SDLoc &DL, - std::deque> &RegsToPass, - SmallVectorImpl &MemOpChains, SDValue StackPtr, - MachineFrameInfo &MFI, SelectionDAG &DAG, SDValue Arg, - unsigned FirstReg, unsigned LastReg, - const ISD::ArgFlagsTy &Flags, bool isLittle, - const CCValAssign &VA) const; + SDValue passByValArg(SDValue Chain, const SDLoc &DL, + std::deque> &RegsToPass, + SmallVectorImpl &MemOpChains, + SDValue StackPtr, MachineFrameInfo &MFI, + SelectionDAG &DAG, SDValue Arg, unsigned FirstReg, + unsigned LastReg, const ISD::ArgFlagsTy &Flags, + bool isLittle, const CCValAssign &VA) const; /// writeVarArgRegs - Write variable function arguments passed in registers /// to the stack. Also create a stack frame object for the first variable Index: lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- lib/Target/Mips/MipsISelLowering.cpp +++ lib/Target/Mips/MipsISelLowering.cpp @@ -2992,16 +2992,6 @@ if (IsTailCall) ++NumTailCalls; - // Chain is the output chain of the last Load/Store or CopyToReg node. - // ByValChain is the output chain of the last Memcpy node created for copying - // byval arguments to the stack. - unsigned StackAlignment = TFL->getStackAlignment(); - NextStackOffset = alignTo(NextStackOffset, StackAlignment); - SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, DL, true); - - if (!IsTailCall) - Chain = DAG.getCALLSEQ_START(Chain, NextStackOffset, 0, DL); - SDValue StackPtr = DAG.getCopyFromReg(Chain, DL, ABI.IsN64() ? Mips::SP_64 : Mips::SP, getPointerTy(DAG.getDataLayout())); @@ -3030,7 +3020,7 @@ assert(ByValIdx < CCInfo.getInRegsParamsCount()); assert(!IsTailCall && "Do not tail-call optimize if there is a byval argument."); - passByValArg(Chain, DL, RegsToPass, MemOpChains, StackPtr, MFI, DAG, Arg, + Chain = passByValArg(Chain, DL, RegsToPass, MemOpChains, StackPtr, MFI, DAG, Arg, FirstByValReg, LastByValReg, Flags, Subtarget.isLittle(), VA); CCInfo.nextInRegsParam(); @@ -3122,6 +3112,16 @@ EVT Ty = Callee.getValueType(); bool GlobalOrExternal = false, IsCallReloc = false; + // Chain is the output chain of the last Load/Store or CopyToReg node. + // ByValChain is the output chain of the last Memcpy node created for copying + // byval arguments to the stack. + unsigned StackAlignment = TFL->getStackAlignment(); + NextStackOffset = alignTo(NextStackOffset, StackAlignment); + SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, DL, true); + + if (!IsTailCall) + Chain = DAG.getCALLSEQ_START(Chain, NextStackOffset, 0, DL); + // The long-calls feature is ignored in case of PIC. // While we do not support -mshared / -mno-shared properly, // ignore long-calls in case of -mabicalls too. @@ -4095,7 +4095,7 @@ } // Copy byVal arg to registers and stack. -void MipsTargetLowering::passByValArg( +SDValue MipsTargetLowering::passByValArg( SDValue Chain, const SDLoc &DL, std::deque> &RegsToPass, SmallVectorImpl &MemOpChains, SDValue StackPtr, @@ -4128,7 +4128,7 @@ // Return if the struct has been fully copied. if (ByValSizeInBytes == OffsetInBytes) - return; + return Chain; // Copy the remainder of the byval argument with sub-word loads and shifts. if (LeftoverBytes) { @@ -4173,7 +4173,7 @@ unsigned ArgReg = ArgRegs[FirstReg + I]; RegsToPass.push_back(std::make_pair(ArgReg, Val)); - return; + return Chain; } } @@ -4183,12 +4183,13 @@ DAG.getConstant(OffsetInBytes, DL, PtrTy)); SDValue Dst = DAG.getNode(ISD::ADD, DL, PtrTy, StackPtr, DAG.getIntPtrConstant(VA.getLocMemOffset(), DL)); - Chain = DAG.getMemcpy(Chain, DL, Dst, Src, - DAG.getConstant(MemCpySize, DL, PtrTy), - Alignment, /*isVolatile=*/false, /*AlwaysInline=*/false, - /*isTailCall=*/false, - MachinePointerInfo(), MachinePointerInfo()); + Chain = DAG.getMemcpy( + Chain, DL, Dst, Src, DAG.getConstant(MemCpySize, DL, PtrTy), Alignment, + /*isVolatile=*/false, /*AlwaysInline=*/false, + /*isTailCall=*/false, MachinePointerInfo(), MachinePointerInfo()); MemOpChains.push_back(Chain); + + return Chain; } void MipsTargetLowering::writeVarArgRegs(std::vector &OutChains, Index: test/CodeGen/Mips/callseq_order.ll =================================================================== --- test/CodeGen/Mips/callseq_order.ll +++ test/CodeGen/Mips/callseq_order.ll @@ -0,0 +1,55 @@ +; RUN: llc -mtriple=mipsel-linux-gnu -o /dev/null \ +; RUN: -verify-machineinstrs -stop-before=expand-isel-pseudos \ +; RUN: -debug-only=isel %s 2>&1 | FileCheck %s +; RUN: llc -mtriple=mips64el-linux-gnu -o /dev/null \ +; RUN: -verify-machineinstrs -stop-before=expand-isel-pseudos \ +; RUN: -debug-only=isel %s 2>&1 | FileCheck %s +; RUN: llc -mtriple=mips-linux-gnu -o /dev/null \ +; RUN: -verify-machineinstrs -stop-before=expand-isel-pseudos \ +; RUN: -debug-only=isel %s 2>&1 | FileCheck %s +; RUN: llc -mtriple=mips64-linux-gnu -o /dev/null \ +; RUN: -verify-machineinstrs -stop-before=expand-isel-pseudos \ +; RUN: -debug-only=isel %s 2>&1 | FileCheck %s + + +%struct.Str1 = type { [64 x i32] } + +@s1 = common global %struct.Str1 zeroinitializer, align 4 + +define void @foo1() { +entry: + call void @bar1(%struct.Str1* byval align 4 @s1) + ret void + ; CHECK-LABEL: *** MachineFunction at end of ISel *** + ; CHECK-LABEL: # Machine code for function foo1: IsSSA, TracksLiveness + ; CHECK: ADJCALLSTACKDOWN + ; CHECK: JAL + ; CHECK: ADJCALLSTACKUP + ; CHECK: ADJCALLSTACKDOWN + ; CHECK: JAL + ; CHECK: ADJCALLSTACKUP + ; CHECK-LABEL: # End machine code for function foo1. +} + +declare void @bar1(%struct.Str1* byval align 4) + +define void @foo2() { +entry: + call void @bar2(%struct.Str1* byval align 4 @s1, %struct.Str1* byval align 4 @s1) + ret void + ; CHECK-LABEL: *** MachineFunction at end of ISel *** + ; CHECK-LABEL: # Machine code for function foo2: IsSSA, TracksLiveness + ; CHECK: ADJCALLSTACKDOWN + ; CHECK: JAL + ; CHECK: ADJCALLSTACKUP + ; CHECK: ADJCALLSTACKDOWN + ; CHECK: JAL + ; CHECK: ADJCALLSTACKUP + ; CHECK: ADJCALLSTACKDOWN + ; CHECK: JAL + ; CHECK: ADJCALLSTACKUP + ; CHECK-LABEL: # End machine code for function foo2. +} + +declare void @bar2(%struct.Str1* byval align 4, %struct.Str1* byval align 4) + Index: test/CodeGen/Mips/largeimmprinting.ll =================================================================== --- test/CodeGen/Mips/largeimmprinting.ll +++ test/CodeGen/Mips/largeimmprinting.ll @@ -1,8 +1,9 @@ -; RUN: llc -march=mipsel -relocation-model=pic < %s | FileCheck %s -check-prefix=32 -; RUN: llc -march=mips64el -mcpu=mips4 -target-abi=n64 -relocation-model=pic < %s | \ -; RUN: FileCheck %s -check-prefix=64 -; RUN: llc -march=mips64el -mcpu=mips64 -target-abi=n64 -relocation-model=pic < %s | \ -; RUN: FileCheck %s -check-prefix=64 +; RUN: llc -march=mipsel -relocation-model=pic -verify-machineinstrs < %s | \ +; RUN: FileCheck %s -check-prefix=32 +; RUN: llc -march=mips64el -mcpu=mips4 -target-abi=n64 -relocation-model=pic \ +; RUN: -verify-machineinstrs < %s | FileCheck %s -check-prefix=64 +; RUN: llc -march=mips64el -mcpu=mips64 -target-abi=n64 -relocation-model=pic \ +; RUN: -verify-machineinstrs < %s | FileCheck %s -check-prefix=64 %struct.S1 = type { [65536 x i8] } Index: test/CodeGen/Mips/llvm-ir/mul.ll =================================================================== --- test/CodeGen/Mips/llvm-ir/mul.ll +++ test/CodeGen/Mips/llvm-ir/mul.ll @@ -268,7 +268,7 @@ ; MM64R6: daddu $2, $[[T1]], $[[T0]] ; MM64R6-DAG: dmul $3, $5, $7 - ; MM32: lw $25, %call16(__multi3)($16) + ; MM32: lw $25, %call16(__multi3) %r = mul i128 %a, %b ret i128 %r Index: test/CodeGen/Mips/llvm-ir/sdiv.ll =================================================================== --- test/CodeGen/Mips/llvm-ir/sdiv.ll +++ test/CodeGen/Mips/llvm-ir/sdiv.ll @@ -190,7 +190,7 @@ ; GP64-NOT-R6: ld $25, %call16(__divti3)($gp) ; 64R6: ld $25, %call16(__divti3)($gp) - ; MM32: lw $25, %call16(__divti3)($16) + ; MM32: lw $25, %call16(__divti3) ; MM64: ld $25, %call16(__divti3)($2) Index: test/CodeGen/Mips/llvm-ir/srem.ll =================================================================== --- test/CodeGen/Mips/llvm-ir/srem.ll +++ test/CodeGen/Mips/llvm-ir/srem.ll @@ -182,7 +182,7 @@ ; GP64-NOT-R6: ld $25, %call16(__modti3)($gp) ; 64R6: ld $25, %call16(__modti3)($gp) - ; MM32: lw $25, %call16(__modti3)($16) + ; MM32: lw $25, %call16(__modti3) ; MM64: ld $25, %call16(__modti3)($2) Index: test/CodeGen/Mips/llvm-ir/udiv.ll =================================================================== --- test/CodeGen/Mips/llvm-ir/udiv.ll +++ test/CodeGen/Mips/llvm-ir/udiv.ll @@ -152,7 +152,7 @@ ; GP64-NOT-R6: ld $25, %call16(__udivti3)($gp) ; 64-R6: ld $25, %call16(__udivti3)($gp) - ; MM32: lw $25, %call16(__udivti3)($16) + ; MM32: lw $25, %call16(__udivti3) ; MM64: ld $25, %call16(__udivti3)($2) Index: test/CodeGen/Mips/llvm-ir/urem.ll =================================================================== --- test/CodeGen/Mips/llvm-ir/urem.ll +++ test/CodeGen/Mips/llvm-ir/urem.ll @@ -208,7 +208,7 @@ ; GP64-NOT-R6: ld $25, %call16(__umodti3)($gp) ; 64R6: ld $25, %call16(__umodti3)($gp) - ; MM32: lw $25, %call16(__umodti3)($16) + ; MM32: lw $25, %call16(__umodti3) ; MM64: ld $25, %call16(__umodti3)($2)