1+ // RUN: %clang_cc1 -triple=arm %s -emit-llvm -O3 -o - | FileCheck %s --check-prefix=CHECK-ARM
2+ // RUN: %clang_cc1 -triple=arm64 %s -emit-llvm -O3 -o - | FileCheck %s --check-prefix=CHECK-ARM64
3+ // RUN: %clang_cc1 -triple=i686 %s -emit-llvm -O3 -o - | FileCheck %s --check-prefix=CHECK-X86
4+ // RUN: %clang_cc1 -triple=x86_64 %s -emit-llvm -O3 -o - | FileCheck %s --check-prefix=CHECK-X64
5+
6+ // Sret tests
7+ struct Big {
8+ int a, b, c, d, e, f, g, h;
9+ };
10+
11+ struct Big F1 (signed short P0);
12+
13+ struct Big F2 (signed short P0) {
14+ signed short P1 = 20391 ;
15+ [[clang::musttail]] return F1 (P1);
16+ }
17+
18+ // CHECK-NOT: alloca
19+ // CHECK-ARM: musttail call arm_aapcscc void @_Z2F1s(ptr dead_on_unwind writable sret(%struct.Big) align 4 %agg.result, i16 noundef signext 20391)
20+ // CHECK-ARM64: musttail call void @_Z2F1s(ptr dead_on_unwind writable sret(%struct.Big) align 4 %agg.result, i16 noundef 20391)
21+ // CHECK-X86: musttail call void @_Z2F1s(ptr dead_on_unwind writable sret(%struct.Big) align 4 %agg.result, i16 noundef signext 20391)
22+ // CHECK-X64: musttail call void @_Z2F1s(ptr dead_on_unwind writable sret(%struct.Big) align 4 %agg.result, i16 noundef signext 20391)
23+
24+ struct ReallyBig {
25+ int a[100 ];
26+ };
27+
28+ // Indirect sret tests
29+ // Function pointer for testing indirect musttail call.
30+ struct FunctionPointers {
31+ ReallyBig (*F3)(int , int , int , int , float , double );
32+ ReallyBig (*F4)(int , int , int , char , float , double );
33+ };
34+
35+ struct ReallyBig F3 (int P0, int P1, int P2, int P3, float P4, double P5);
36+ struct ReallyBig F4 (int P0, int P1, int P2, char P3, float P4, double P5);
37+
38+ static struct FunctionPointers FP = {F3, F4};
39+
40+ struct ReallyBig F5 (int P0, int P1, int P2, int P3, float P4, double P5) {
41+ [[clang::musttail]] return FP.F3 (P0, P1, P2, P3, P4, P5);
42+ }
43+
44+ // CHECK-NOT: alloca
45+ // CHECK-ARM: musttail call arm_aapcscc void @_Z2F3iiiifd(ptr dead_on_unwind writable sret(%struct.ReallyBig) align 4 %agg.result, i32 noundef %P0, i32 noundef %P1, i32 noundef %P2, i32 noundef %P3, float noundef %P4, double noundef %P5)
46+ // CHECK-ARM64: musttail call void @_Z2F3iiiifd(ptr dead_on_unwind writable sret(%struct.ReallyBig) align 4 %agg.result, i32 noundef %P0, i32 noundef %P1, i32 noundef %P2, i32 noundef %P3, float noundef %P4, double noundef %P5)
47+ // CHECK-X86: musttail call void @_Z2F3iiiifd(ptr dead_on_unwind writable sret(%struct.ReallyBig) align 4 %agg.result, i32 noundef %P0, i32 noundef %P1, i32 noundef %P2, i32 noundef %P3, float noundef %P4, double noundef %P5)
48+ // CHECK-X64: musttail call void @_Z2F3iiiifd(ptr dead_on_unwind writable sret(%struct.ReallyBig) align 4 %agg.result, i32 noundef %P0, i32 noundef %P1, i32 noundef %P2, i32 noundef %P3, float noundef %P4, double noundef %P5)
49+
50+ struct ReallyBig F6 (int P0, int P1, int P2, char P3, float P4, double P5) {
51+ [[clang::musttail]] return FP.F4 (P0, P1, P2, P3, P4, P5);
52+ }
53+
54+ // Complex and BitInt. Special cases for sret.
55+ // CHECK-NOT: alloca
56+ // CHECK-ARM: musttail call arm_aapcscc void @_Z2F4iiicfd(ptr dead_on_unwind writable sret(%struct.ReallyBig) align 4 %agg.result, i32 noundef %P0, i32 noundef %P1, i32 noundef %P2, i8 noundef signext %P3, float noundef %P4, double noundef %P5)
57+ // CHECK-ARM64: musttail call void @_Z2F4iiicfd(ptr dead_on_unwind writable sret(%struct.ReallyBig) align 4 %agg.result, i32 noundef %P0, i32 noundef %P1, i32 noundef %P2, i8 noundef %P3, float noundef %P4, double noundef %P5)
58+ // CHECK-X86: musttail call void @_Z2F4iiicfd(ptr dead_on_unwind writable sret(%struct.ReallyBig) align 4 %agg.result, i32 noundef %P0, i32 noundef %P1, i32 noundef %P2, i8 noundef signext %P3, float noundef %P4, double noundef %P5)
59+ // CHECK-X64: musttail call void @_Z2F4iiicfd(ptr dead_on_unwind writable sret(%struct.ReallyBig) align 4 %agg.result, i32 noundef %P0, i32 noundef %P1, i32 noundef %P2, i8 noundef signext %P3, float noundef %P4, double noundef %P5)
60+
61+ double _Complex F7 (signed short P0);
62+
63+ double _Complex F8 (signed short P0) {
64+ signed short P1 = 20391 ;
65+ [[clang::musttail]] return F7 (P1);
66+ }
67+
68+ // CHECK-NOT: alloca
69+ // CHECK-ARM: musttail call arm_aapcscc void @_Z2F7s(ptr dead_on_unwind writable sret({ double, double }) align 8 %agg.result, i16 noundef signext 20391)
70+ // CHECK-ARM64: musttail call noundef { double, double } @_Z2F7s(i16 noundef 20391)
71+ // CHECK-X86: musttail call void @_Z2F7s(ptr dead_on_unwind writable sret({ double, double }) align 4 %agg.result, i16 noundef signext 20391)
72+ // CHECK-X64: musttail call noundef { double, double } @_Z2F7s(i16 noundef signext 20391)
73+
74+ signed _BitInt (100 ) F9(float P0, float P1, double P2, char P3);
75+
76+ signed _BitInt (100 ) F10(float P0, float P1, double P2, char P3) {
77+ [[clang::musttail]] return F9 (P0, P1, P2, P3);
78+ }
79+
80+ // CHECK-NOT: alloca
81+ // CHECK-ARM: musttail call arm_aapcscc void @_Z2F9ffdc(ptr dead_on_unwind writable sret(i128) align 8 %agg.result, float noundef %P0, float noundef %P1, double noundef %P2, i8 noundef signext %P3)
82+ // CHECK-ARM64: musttail call noundef i100 @_Z2F9ffdc(float noundef %P0, float noundef %P1, double noundef %P2, i8 noundef %P3)
83+ // CHECK-X86: musttail call void @_Z2F9ffdc(ptr dead_on_unwind writable sret(i128) align 4 %agg.result, float noundef %P0, float noundef %P1, double noundef %P2, i8 noundef signext %P3)
84+ // CHECK-X64: musttail call noundef { i64, i64 } @_Z2F9ffdc(float noundef %P0, float noundef %P1, double noundef %P2, i8 noundef signext %P3)
0 commit comments