From: Manman Ren Date: Tue, 26 Apr 2016 18:08:06 +0000 (+0000) Subject: Swift Calling Convention: use %RAX for sret. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1c3f65a18cad4d46e8683e47430694c8d8f2ccbe;p=platform%2Fupstream%2Fllvm.git Swift Calling Convention: use %RAX for sret. We don't need to copy the sret argument into %rax upon return. rdar://25671494 llvm-svn: 267579 --- diff --git a/llvm/lib/Target/X86/X86CallingConv.td b/llvm/lib/Target/X86/X86CallingConv.td index ed17b1d..263a207 100644 --- a/llvm/lib/Target/X86/X86CallingConv.td +++ b/llvm/lib/Target/X86/X86CallingConv.td @@ -303,6 +303,10 @@ def CC_X86_64_C : CallingConv<[ // A SwiftError is passed in R12. CCIfSwiftError>>, + // For Swift Calling Convention, pass sret in %RAX. + CCIfCC<"CallingConv::Swift", + CCIfSRet>>>, + // The first 6 integer arguments are passed in integer registers. CCIfType<[i32], CCAssignToReg<[EDI, ESI, EDX, ECX, R8D, R9D]>>, CCIfType<[i64], CCAssignToReg<[RDI, RSI, RDX, RCX, R8 , R9 ]>>, diff --git a/llvm/lib/Target/X86/X86FastISel.cpp b/llvm/lib/Target/X86/X86FastISel.cpp index 697bd8a..6614ac0 100644 --- a/llvm/lib/Target/X86/X86FastISel.cpp +++ b/llvm/lib/Target/X86/X86FastISel.cpp @@ -1121,11 +1121,14 @@ bool X86FastISel::X86SelectRet(const Instruction *I) { RetRegs.push_back(VA.getLocReg()); } + // Swift calling convention does not require we copy the sret argument + // into %rax/%eax for the return, and SRetReturnReg is not set for Swift. + // All x86 ABIs require that for returning structs by value we copy // the sret argument into %rax/%eax (depending on ABI) 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/%eax. - if (F.hasStructRetAttr()) { + if (F.hasStructRetAttr() && CC != CallingConv::Swift) { unsigned Reg = X86MFInfo->getSRetReturnReg(); assert(Reg && "SRetReturnReg should have been set in LowerFormalArguments()!"); diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 4d9d461..ad84460 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -2082,6 +2082,9 @@ X86TargetLowering::LowerReturn(SDValue Chain, RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); } + // Swift calling convention does not require we copy the sret argument + // into %rax/%eax for the return, and SRetReturnReg is not set for Swift. + // All x86 ABIs require that for returning structs by value we copy // the sret argument into %rax/%eax (depending on ABI) for the return. // We saved the argument into a virtual register in the entry block, @@ -2610,6 +2613,11 @@ SDValue X86TargetLowering::LowerFormalArguments( } for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + // Swift calling convention does not require we copy the sret argument + // into %rax/%eax for the return. We don't set SRetReturnReg for Swift. + if (CallConv == CallingConv::Swift) + continue; + // 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 diff --git a/llvm/test/CodeGen/X86/swift-return.ll b/llvm/test/CodeGen/X86/swift-return.ll index 99e4bd0..cd028d0 100644 --- a/llvm/test/CodeGen/X86/swift-return.ll +++ b/llvm/test/CodeGen/X86/swift-return.ll @@ -36,10 +36,9 @@ declare swiftcc { i16, i8 } @gen(i32) ; If we can't pass every return value in register, we will pass everything ; in memroy. The caller provides space for the return value and passes -; the address in %rdi. The first input argument will be in %rsi. +; the address in %rax. The first input argument will be in %rdi. ; CHECK-LABEL: test2: -; CHECK: leaq (%rsp), %rdi -; CHECK: movl %{{.*}}, %esi +; CHECK: leaq (%rsp), %rax ; CHECK: callq gen2 ; CHECK: movl (%rsp) ; CHECK-DAG: addl 4(%rsp) @@ -47,8 +46,7 @@ declare swiftcc { i16, i8 } @gen(i32) ; CHECK-DAG: addl 12(%rsp) ; CHECK-DAG: addl 16(%rsp) ; CHECK-O0-LABEL: test2: -; CHECK-O0-DAG: leaq (%rsp), %rdi -; CHECK-O0-DAG: movl {{.*}}, %esi +; CHECK-O0-DAG: leaq (%rsp), %rax ; CHECK-O0: callq gen2 ; CHECK-O0-DAG: movl (%rsp) ; CHECK-O0-DAG: movl 4(%rsp) @@ -80,22 +78,20 @@ entry: ret i32 %add3 } -; The address of the return value is passed in %rdi. -; On return, %rax will contain the adddress that has been passed in by the caller in %rdi. +; The address of the return value is passed in %rax. +; On return, we don't keep the address in %rax. ; CHECK-LABEL: gen2: -; CHECK: movl %esi, 16(%rdi) -; CHECK: movl %esi, 12(%rdi) -; CHECK: movl %esi, 8(%rdi) -; CHECK: movl %esi, 4(%rdi) -; CHECK: movl %esi, (%rdi) -; CHECK: movq %rdi, %rax +; CHECK: movl %edi, 16(%rax) +; CHECK: movl %edi, 12(%rax) +; CHECK: movl %edi, 8(%rax) +; CHECK: movl %edi, 4(%rax) +; CHECK: movl %edi, (%rax) ; CHECK-O0-LABEL: gen2: -; CHECK-O0-DAG: movl %esi, 16(%rdi) -; CHECK-O0-DAG: movl %esi, 12(%rdi) -; CHECK-O0-DAG: movl %esi, 8(%rdi) -; CHECK-O0-DAG: movl %esi, 4(%rdi) -; CHECK-O0-DAG: movl %esi, (%rdi) -; CHECK-O0-DAG: movq %rdi, %rax +; CHECK-O0-DAG: movl %edi, 16(%rax) +; CHECK-O0-DAG: movl %edi, 12(%rax) +; CHECK-O0-DAG: movl %edi, 8(%rax) +; CHECK-O0-DAG: movl %edi, 4(%rax) +; CHECK-O0-DAG: movl %edi, (%rax) define swiftcc { i32, i32, i32, i32, i32 } @gen2(i32 %key) { %Y = insertvalue { i32, i32, i32, i32, i32 } undef, i32 %key, 0 %Z = insertvalue { i32, i32, i32, i32, i32 } %Y, i32 %key, 1 @@ -199,3 +195,12 @@ define void @consume_i1_ret() { } declare swiftcc { i1, i1, i1, i1 } @produce_i1_ret() + +; CHECK-LABEL: foo: +; CHECK: movq %rdi, (%rax) +; CHECK-O0-LABEL: foo: +; CHECK-O0: movq %rdi, (%rax) +define swiftcc void @foo(i64* sret %agg.result, i64 %val) { + store i64 %val, i64* %agg.result + ret void +}