aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2015-05-26 16:09:22 +0800
committerAndrew Hsieh <andrewhsieh@google.com>2015-05-26 16:09:22 +0800
commit9e3f281960602294536cbe521c60e350b026d99a (patch)
treeb2d7c0701f079b1688effbf1555ef479c6609240
parent1c21fb62803a9f85d28d1eeaab9ecae30fd2ba90 (diff)
downloadllvm-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.cpp34
-rw-r--r--test/CodeGen/X86/complex-fca.ll26
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