aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Lewycky <nicholas@mxc.ca>2012-10-02 22:45:06 +0000
committerNick Lewycky <nicholas@mxc.ca>2012-10-02 22:45:06 +0000
commitb09649b3356ab793e304ddd444206bf91000d7ee (patch)
treea25c4ac0836f73d2f6f511863aadd3f824157169
parent6c0c6d613ac3223fdf515c1616331bdeb2a4f1a4 (diff)
downloadexternal_llvm-b09649b3356ab793e304ddd444206bf91000d7ee.zip
external_llvm-b09649b3356ab793e304ddd444206bf91000d7ee.tar.gz
external_llvm-b09649b3356ab793e304ddd444206bf91000d7ee.tar.bz2
Make sure to put our sret argument into %rax on x86-64. Fixes PR13563!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165063 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/X86/X86FastISel.cpp18
-rw-r--r--test/CodeGen/X86/fast-isel-x86-64.ll13
2 files changed, 29 insertions, 2 deletions
diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp
index 83f2f6a..2a8bf81 100644
--- a/lib/Target/X86/X86FastISel.cpp
+++ b/lib/Target/X86/X86FastISel.cpp
@@ -710,6 +710,8 @@ bool X86FastISel::X86SelectStore(const Instruction *I) {
bool X86FastISel::X86SelectRet(const Instruction *I) {
const ReturnInst *Ret = cast<ReturnInst>(I);
const Function &F = *I->getParent()->getParent();
+ const X86MachineFunctionInfo *X86MFInfo =
+ FuncInfo.MF->getInfo<X86MachineFunctionInfo>();
if (!FuncInfo.CanLowerReturn)
return false;
@@ -724,8 +726,7 @@ bool X86FastISel::X86SelectRet(const Instruction *I) {
return false;
// Don't handle popping bytes on return for now.
- if (FuncInfo.MF->getInfo<X86MachineFunctionInfo>()
- ->getBytesToPopOnReturn() != 0)
+ if (X86MFInfo->getBytesToPopOnReturn() != 0)
return 0;
// fastcc with -tailcallopt is intended to provide a guaranteed
@@ -809,6 +810,19 @@ bool X86FastISel::X86SelectRet(const Instruction *I) {
MRI.addLiveOut(VA.getLocReg());
}
+ // The x86-64 ABI for returning structs by value requires that we copy
+ // the sret argument into %rax for the return. We saved the argument into
+ // a virtual register in the entry block, so now we copy the value out
+ // and into %rax.
+ if (Subtarget->is64Bit() && F.hasStructRetAttr()) {
+ unsigned Reg = X86MFInfo->getSRetReturnReg();
+ assert(Reg &&
+ "SRetReturnReg should have been set in LowerFormalArguments()!");
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY),
+ X86::RAX).addReg(Reg);
+ MRI.addLiveOut(X86::RAX);
+ }
+
// Now emit the RET.
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(X86::RET));
return true;
diff --git a/test/CodeGen/X86/fast-isel-x86-64.ll b/test/CodeGen/X86/fast-isel-x86-64.ll
index 85a70aa..cdfaf7f 100644
--- a/test/CodeGen/X86/fast-isel-x86-64.ll
+++ b/test/CodeGen/X86/fast-isel-x86-64.ll
@@ -291,3 +291,16 @@ entry:
}
declare void @foo22(i32)
+
+; PR13563
+define void @test23(i8* noalias sret %result) {
+ %a = alloca i8
+ %b = call i8* @foo23()
+ ret void
+; CHECK: test23:
+; CHECK: call
+; CHECK: movq %rdi, %rax
+; CHECK: ret
+}
+
+declare i8* @foo23()