From c4ae8cbc5d7fae1d3007b43ecd5df7a2d953a0a0 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Thu, 5 Feb 2015 18:09:05 +0000 Subject: [PATCH] X86 ABI fix for return values > 24 bytes. The return value's address must be returned in %rax. i.e. the callee needs to copy the sret argument (%rdi) into the return value (%rax). This probably won't manifest as a bug when the caller is LLVM-compiled code. But it is an ABI guarantee and tools expect it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228321 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelLowering.cpp | 17 +++++++++-------- test/CodeGen/X86/sret-implicit.ll | 10 ++++++++++ test/CodeGen/X86/vselect.ll | 1 + 3 files changed, 20 insertions(+), 8 deletions(-) create mode 100644 test/CodeGen/X86/sret-implicit.ll diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 7f0718b2708..fa19e7d0635 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -2107,14 +2107,15 @@ X86TargetLowering::LowerReturn(SDValue Chain, // Win32 requires us to put the sret argument to %eax as well. // We saved the argument into a virtual register in the entry block, // so now we copy the value out and into %rax/%eax. - if (DAG.getMachineFunction().getFunction()->hasStructRetAttr() && - (Subtarget->is64Bit() || Subtarget->isTargetKnownWindowsMSVC())) { - MachineFunction &MF = DAG.getMachineFunction(); - X86MachineFunctionInfo *FuncInfo = MF.getInfo(); - unsigned Reg = FuncInfo->getSRetReturnReg(); - assert(Reg && - "SRetReturnReg should have been set in LowerFormalArguments()."); - SDValue Val = DAG.getCopyFromReg(Chain, dl, Reg, getPointerTy()); + // + // Checking Function.hasStructRetAttr() here is insufficient because the IR + // may not have an explicit sret argument. If FuncInfo.CanLowerReturn is + // false, then an sret argument may be implicitly inserted in the SelDAG. In + // either case FuncInfo->setSRetReturnReg() will have been called. + if (unsigned SRetReg = FuncInfo->getSRetReturnReg()) { + assert((Subtarget->is64Bit() || Subtarget->isTargetKnownWindowsMSVC()) && + "No need for an sret register"); + SDValue Val = DAG.getCopyFromReg(Chain, dl, SRetReg, getPointerTy()); unsigned RetValReg = (Subtarget->is64Bit() && !Subtarget->isTarget64BitILP32()) ? diff --git a/test/CodeGen/X86/sret-implicit.ll b/test/CodeGen/X86/sret-implicit.ll new file mode 100644 index 00000000000..3fade1de0cf --- /dev/null +++ b/test/CodeGen/X86/sret-implicit.ll @@ -0,0 +1,10 @@ +; RUN: llc -mtriple=x86_64-apple-darwin8 < %s | FileCheck %s +; RUN: llc -mtriple=x86_64-pc-linux < %s | FileCheck %s + +; CHECK-LABEL: return32 +; CHECK-DAG: movq $0, (%rdi) +; CHECK-DAG: movq %rdi, %rax +; CHECK: retq +define i256 @return32() { + ret i256 0 +} diff --git a/test/CodeGen/X86/vselect.ll b/test/CodeGen/X86/vselect.ll index c1e9329859c..2e3d7f5428f 100644 --- a/test/CodeGen/X86/vselect.ll +++ b/test/CodeGen/X86/vselect.ll @@ -275,6 +275,7 @@ define <16 x double> @select_illegal(<16 x double> %a, <16 x double> %b) { ; CHECK-NEXT: movaps %xmm2, 32(%rdi) ; CHECK-NEXT: movaps %xmm1, 16(%rdi) ; CHECK-NEXT: movaps %xmm0, (%rdi) +; CHECK-NEXT: movq %rdi, %rax ; CHECK-NEXT: retq %sel = select <16 x i1> , <16 x double> %a, <16 x double> %b ret <16 x double> %sel -- 2.34.1