diff options
author | Reid Kleckner <reid@kleckner.net> | 2015-05-26 16:09:22 +0800 |
---|---|---|
committer | Andrew Hsieh <andrewhsieh@google.com> | 2015-05-26 16:09:22 +0800 |
commit | 9e3f281960602294536cbe521c60e350b026d99a (patch) | |
tree | b2d7c0701f079b1688effbf1555ef479c6609240 | |
parent | 1c21fb62803a9f85d28d1eeaab9ecae30fd2ba90 (diff) | |
download | llvm-release_36.tar.gz |
[X86] Always return the sret parameter in eax/rax, even on 32-bitrelease_36
Summary:
This rule was always in the old SysV i386 ABI docs and the new ones that
H.J. Lu has put together, but we never noticed:
EAX scratch register; also used to return integer and pointer values
from functions; also stores the address of a returned struct or union
Fixes PR23491.
Reviewers: majnemer
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D9715
Change-Id: Iee9c022600e3df39560ad07b61ebce37501451c5
-rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 34 | ||||
-rw-r--r-- | test/CodeGen/X86/complex-fca.ll | 26 |
2 files changed, 30 insertions, 30 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 28475bded65..15b2394e4dc 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -2102,9 +2102,8 @@ X86TargetLowering::LowerReturn(SDValue Chain, RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); } - // The x86-64 ABIs require that for returning structs by value we copy + // All x86 ABIs require that for returning structs by value we copy // the sret argument into %rax/%eax (depending on ABI) for the return. - // 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() && @@ -2531,24 +2530,21 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, InVals.push_back(ArgValue); } - if (Subtarget->is64Bit() || Subtarget->isTargetKnownWindowsMSVC()) { - for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { - // The x86-64 ABIs require that for returning structs by value we copy - // the sret argument into %rax/%eax (depending on ABI) for the return. - // Win32 requires us to put the sret argument to %eax as well. - // Save the argument into a virtual register so that we can access it - // from the return points. - if (Ins[i].Flags.isSRet()) { - unsigned Reg = FuncInfo->getSRetReturnReg(); - if (!Reg) { - MVT PtrTy = getPointerTy(); - Reg = MF.getRegInfo().createVirtualRegister(getRegClassFor(PtrTy)); - FuncInfo->setSRetReturnReg(Reg); - } - SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[i]); - Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain); - break; + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + // All x86 ABIs require that for returning structs by value we copy the + // sret argument into %rax/%eax (depending on ABI) for the return. Save + // the argument into a virtual register so that we can access it from the + // return points. + if (Ins[i].Flags.isSRet()) { + unsigned Reg = FuncInfo->getSRetReturnReg(); + if (!Reg) { + MVT PtrTy = getPointerTy(); + Reg = MF.getRegInfo().createVirtualRegister(getRegClassFor(PtrTy)); + FuncInfo->setSRetReturnReg(Reg); } + SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[i]); + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain); + break; } } diff --git a/test/CodeGen/X86/complex-fca.ll b/test/CodeGen/X86/complex-fca.ll index 8ad38a4ee5c..78b27b7dc3f 100644 --- a/test/CodeGen/X86/complex-fca.ll +++ b/test/CodeGen/X86/complex-fca.ll @@ -1,17 +1,21 @@ -; RUN: llc < %s -march=x86 | grep mov | count 2 - -; Skip this on Windows as there is no ccosl and sret behaves differently. -; XFAIL: pc-win32 +; RUN: llc < %s -march=x86 | FileCheck %s define void @ccosl({ x86_fp80, x86_fp80 }* noalias sret %agg.result, { x86_fp80, x86_fp80 } %z) nounwind { entry: - %z8 = extractvalue { x86_fp80, x86_fp80 } %z, 0 - %z9 = extractvalue { x86_fp80, x86_fp80 } %z, 1 - %0 = fsub x86_fp80 0xK80000000000000000000, %z9 - %insert = insertvalue { x86_fp80, x86_fp80 } undef, x86_fp80 %0, 0 - %insert7 = insertvalue { x86_fp80, x86_fp80 } %insert, x86_fp80 %z8, 1 - call void @ccoshl({ x86_fp80, x86_fp80 }* noalias sret %agg.result, { x86_fp80, x86_fp80 } %insert7) nounwind - ret void + %z8 = extractvalue { x86_fp80, x86_fp80 } %z, 0 + %z9 = extractvalue { x86_fp80, x86_fp80 } %z, 1 + %0 = fsub x86_fp80 0xK80000000000000000000, %z9 + %insert = insertvalue { x86_fp80, x86_fp80 } undef, x86_fp80 %0, 0 + %insert7 = insertvalue { x86_fp80, x86_fp80 } %insert, x86_fp80 %z8, 1 + call void @ccoshl({ x86_fp80, x86_fp80 }* noalias sret %agg.result, { x86_fp80, x86_fp80 } %insert7) nounwind + ret void } +; CHECK-LABEL: ccosl: +; CHECK: movl {{[0-9]+}}(%esp), %[[sret_reg:[^ ]+]] +; CHECK: movl %[[sret_reg]], (%esp) +; CHECK: calll {{.*ccoshl.*}} +; CHECK: movl %[[sret_reg]], %eax +; CHECK: retl + declare void @ccoshl({ x86_fp80, x86_fp80 }* noalias sret, { x86_fp80, x86_fp80 }) nounwind |