summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Trick <atrick@apple.com>2015-02-05 18:09:05 +0000
committerAndrew Trick <atrick@apple.com>2015-02-05 18:09:05 +0000
commit7fc4583eda562daf9d3610d6e2623c60ca0690f6 (patch)
treeb40f3cb0a6c321722f4a7e9476e656603d1e349d
parentf297dbed487cd02514ee3e022c89dc2242475465 (diff)
downloadbcm5719-llvm-7fc4583eda562daf9d3610d6e2623c60ca0690f6.tar.gz
bcm5719-llvm-7fc4583eda562daf9d3610d6e2623c60ca0690f6.zip
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. llvm-svn: 228321
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp17
-rw-r--r--llvm/test/CodeGen/X86/sret-implicit.ll10
-rw-r--r--llvm/test/CodeGen/X86/vselect.ll1
3 files changed, 20 insertions, 8 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 7f0718b2708..fa19e7d0635 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/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<X86MachineFunctionInfo>();
- 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/llvm/test/CodeGen/X86/sret-implicit.ll b/llvm/test/CodeGen/X86/sret-implicit.ll
new file mode 100644
index 00000000000..3fade1de0cf
--- /dev/null
+++ b/llvm/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/llvm/test/CodeGen/X86/vselect.ll b/llvm/test/CodeGen/X86/vselect.ll
index c1e9329859c..2e3d7f5428f 100644
--- a/llvm/test/CodeGen/X86/vselect.ll
+++ b/llvm/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> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 false, i1 false, i1 false, i1 false, i1 false, i1 false, i1 false, i1 false>, <16 x double> %a, <16 x double> %b
ret <16 x double> %sel
OpenPOWER on IntegriCloud