[x86] Make the new vector shuffle legality test on by default, which
[oota-llvm.git] / test / CodeGen / X86 / win32_sret.ll
index 8c413f4481e6575c95609b141e37b6bdd981bc71..8728712cece49b7e785770b0b34f49f554bbfd24 100644 (file)
@@ -2,9 +2,11 @@
 ; some setups (e.g., Atom) from affecting the output.
 ; RUN: llc < %s -mcpu=core2 -mtriple=i686-pc-win32 | FileCheck %s -check-prefix=WIN32
 ; RUN: llc < %s -mcpu=core2 -mtriple=i686-pc-mingw32 | FileCheck %s -check-prefix=MINGW_X86
+; RUN: llc < %s -mcpu=core2 -mtriple=i686-pc-cygwin | FileCheck %s -check-prefix=CYGWIN
 ; RUN: llc < %s -mcpu=core2 -mtriple=i386-pc-linux | FileCheck %s -check-prefix=LINUX
 ; RUN: llc < %s -mcpu=core2 -O0 -mtriple=i686-pc-win32 | FileCheck %s -check-prefix=WIN32
 ; RUN: llc < %s -mcpu=core2 -O0 -mtriple=i686-pc-mingw32 | FileCheck %s -check-prefix=MINGW_X86
+; RUN: llc < %s -mcpu=core2 -O0 -mtriple=i686-pc-cygwin | FileCheck %s -check-prefix=CYGWIN
 ; RUN: llc < %s -mcpu=core2 -O0 -mtriple=i386-pc-linux | FileCheck %s -check-prefix=LINUX
 
 ; The SysV ABI used by most Unixes and Mingw on x86 specifies that an sret pointer
@@ -16,13 +18,16 @@ entry:
 ; WIN32-LABEL:      _sret1:
 ; WIN32:      movb $42, (%eax)
 ; WIN32-NOT:  popl %eax
-; WIN32:    {{ret$}}
+; WIN32:    {{retl$}}
 
 ; MINGW_X86-LABEL:  _sret1:
-; MINGW_X86:  ret $4
+; MINGW_X86:  {{retl$}}
+
+; CYGWIN-LABEL:     _sret1:
+; CYGWIN:     retl $4
 
 ; LINUX-LABEL:      sret1:
-; LINUX:      ret $4
+; LINUX:      retl $4
 
   store i8 42, i8* %x, align 4
   ret void
@@ -33,13 +38,16 @@ entry:
 ; WIN32-LABEL:      _sret2:
 ; WIN32:      movb {{.*}}, (%eax)
 ; WIN32-NOT:  popl %eax
-; WIN32:    {{ret$}}
+; WIN32:    {{retl$}}
 
 ; MINGW_X86-LABEL:  _sret2:
-; MINGW_X86:  ret $4
+; MINGW_X86:  {{retl$}}
+
+; CYGWIN-LABEL:     _sret2:
+; CYGWIN:     retl $4
 
 ; LINUX-LABEL:      sret2:
-; LINUX:      ret $4
+; LINUX:      retl $4
 
   store i8 %y, i8* %x
   ret void
@@ -51,13 +59,16 @@ entry:
 ; WIN32:      movb $42, (%eax)
 ; WIN32-NOT:  movb $13, (%eax)
 ; WIN32-NOT:  popl %eax
-; WIN32:    {{ret$}}
+; WIN32:    {{retl$}}
 
 ; MINGW_X86-LABEL:  _sret3:
-; MINGW_X86:  ret $4
+; MINGW_X86:  {{retl$}}
+
+; CYGWIN-LABEL:     _sret3:
+; CYGWIN:     retl $4
 
 ; LINUX-LABEL:      sret3:
-; LINUX:      ret $4
+; LINUX:      retl $4
 
   store i8 42, i8* %x
   store i8 13, i8* %y
@@ -72,13 +83,16 @@ entry:
 ; WIN32-LABEL:     _sret4:
 ; WIN32:     movl $42, (%eax)
 ; WIN32-NOT: popl %eax
-; WIN32:   {{ret$}}
+; WIN32:   {{retl$}}
 
 ; MINGW_X86-LABEL: _sret4:
-; MINGW_X86: ret $4
+; MINGW_X86: {{retl$}}
+
+; CYGWIN-LABEL:    _sret4:
+; CYGWIN:    retl $4
 
 ; LINUX-LABEL:     sret4:
-; LINUX:     ret $4
+; LINUX:     retl $4
 
   %x = getelementptr inbounds %struct.S4* %agg.result, i32 0, i32 0
   store i32 42, i32* %x, align 4
@@ -98,6 +112,7 @@ entry:
   ret void
 ; WIN32-LABEL:     {{^}}"?foo@C5@@QAE?AUS5@@XZ":
 ; MINGW_X86-LABEL: {{^}}"?foo@C5@@QAE?AUS5@@XZ":
+; CYGWIN-LABEL:    {{^}}"?foo@C5@@QAE?AUS5@@XZ":
 ; LINUX-LABEL:     {{^}}"?foo@C5@@QAE?AUS5@@XZ":
 
 ; The address of the return structure is passed as an implicit parameter.
@@ -105,7 +120,7 @@ entry:
 ; should match both 4(%esp) and 8(%esp).
 ; WIN32:     {{[48]}}(%esp), %eax
 ; WIN32:     movl $42, (%eax)
-; WIN32:     ret $4
+; WIN32:     retl $4
 }
 
 define void @call_foo5() {
@@ -115,6 +130,7 @@ entry:
   call x86_thiscallcc void @"\01?foo@C5@@QAE?AUS5@@XZ"(%struct.S5* sret %s, %class.C5* %c)
 ; WIN32-LABEL:      {{^}}_call_foo5:
 ; MINGW_X86-LABEL:  {{^}}_call_foo5:
+; CYGWIN-LABEL:     {{^}}_call_foo5:
 ; LINUX-LABEL:      {{^}}call_foo5:
 
 
@@ -126,7 +142,7 @@ entry:
 ; The this pointer goes to ECX.
 ; WIN32-NEXT: leal {{[0-9]+}}(%esp), %ecx
 ; WIN32-NEXT: calll "?foo@C5@@QAE?AUS5@@XZ"
-; WIN32:      ret
+; WIN32:      retl
   ret void
 }
 
@@ -135,6 +151,7 @@ entry:
 define void @test6_f(%struct.test6* %x) nounwind {
 ; WIN32-LABEL: _test6_f:
 ; MINGW_X86-LABEL: _test6_f:
+; CYGWIN-LABEL: _test6_f:
 ; LINUX-LABEL: test6_f:
 
 ; The %x argument is moved to %ecx. It will be the this pointer.
@@ -145,6 +162,9 @@ define void @test6_f(%struct.test6* %x) nounwind {
 ; MINGW_X86: movl    8(%ebp), %eax
 ; MINGW_X86: movl    %eax, (%e{{([a-d]x)|(sp)}})
 
+; CYGWIN: movl    8(%ebp), %eax
+; CYGWIN: movl    %eax, (%e{{([a-d]x)|(sp)}})
+
 ; The sret pointer is (%esp)
 ; WIN32:          leal    8(%esp), %[[REG:e[a-d]x]]
 ; WIN32-NEXT:     movl    %[[REG]], (%e{{([a-d]x)|(sp)}})
@@ -153,8 +173,71 @@ define void @test6_f(%struct.test6* %x) nounwind {
 ; MINGW_X86-NEXT: leal    8(%esp), %ecx
 ; MINGW_X86-NEXT: calll   _test6_g
 
+; CYGWIN-NEXT: leal    8(%esp), %ecx
+; CYGWIN-NEXT: calll   _test6_g
+
   %tmp = alloca %struct.test6, align 4
   call x86_thiscallcc void @test6_g(%struct.test6* sret %tmp, %struct.test6* %x)
   ret void
 }
 declare x86_thiscallcc void @test6_g(%struct.test6* sret, %struct.test6*)
+
+; Flipping the parameters at the IR level generates the same code.
+%struct.test7 = type { i32, i32, i32 }
+define void @test7_f(%struct.test7* %x) nounwind {
+; WIN32-LABEL: _test7_f:
+; MINGW_X86-LABEL: _test7_f:
+; CYGWIN-LABEL: _test7_f:
+; LINUX-LABEL: test7_f:
+
+; The %x argument is moved to %ecx on all OSs. It will be the this pointer.
+; WIN32:      movl    8(%ebp), %ecx
+; MINGW_X86:  movl    8(%ebp), %ecx
+; CYGWIN:     movl    8(%ebp), %ecx
+
+; The sret pointer is (%esp)
+; WIN32:          leal    8(%esp), %[[REG:e[a-d]x]]
+; WIN32-NEXT:     movl    %[[REG]], (%e{{([a-d]x)|(sp)}})
+; MINGW_X86:      leal    8(%esp), %[[REG:e[a-d]x]]
+; MINGW_X86-NEXT: movl    %[[REG]], (%e{{([a-d]x)|(sp)}})
+; CYGWIN:         leal    8(%esp), %[[REG:e[a-d]x]]
+; CYGWIN-NEXT:    movl    %[[REG]], (%e{{([a-d]x)|(sp)}})
+
+  %tmp = alloca %struct.test7, align 4
+  call x86_thiscallcc void @test7_g(%struct.test7* %x, %struct.test7* sret %tmp)
+  ret void
+}
+
+define x86_thiscallcc void @test7_g(%struct.test7* %in, %struct.test7* sret %out) {
+  %s = getelementptr %struct.test7* %in, i32 0, i32 0
+  %d = getelementptr %struct.test7* %out, i32 0, i32 0
+  %v = load i32* %s
+  store i32 %v, i32* %d
+  call void @clobber_eax()
+  ret void
+
+; Make sure we return the second parameter in %eax.
+; WIN32-LABEL: _test7_g:
+; WIN32: calll _clobber_eax
+; WIN32: movl {{.*}}, %eax
+; WIN32: retl
+}
+
+declare void @clobber_eax()
+
+; Test what happens if the first parameter has to be split by codegen.
+; Realistically, no frontend will generate code like this, but here it is for
+; completeness.
+define void @test8_f(i64 inreg %a, i64* sret %out) {
+  store i64 %a, i64* %out
+  call void @clobber_eax()
+  ret void
+
+; WIN32-LABEL: _test8_f:
+; WIN32: movl {{[0-9]+}}(%esp), %[[out:[a-z]+]]
+; WIN32-DAG: movl %edx, 4(%[[out]])
+; WIN32-DAG: movl %eax, (%[[out]])
+; WIN32: calll _clobber_eax
+; WIN32: movl {{.*}}, %eax
+; WIN32: retl
+}