1; RUN: llc -mtriple=mips-linux-gnu -relocation-model=static < %s \
2; RUN:   | FileCheck --check-prefixes=ALL,O32,O32-BE %s
3; RUN: llc -mtriple=mipsel-linux-gnu -relocation-model=static < %s \
4; RUN:   | FileCheck --check-prefixes=ALL,O32,O32-LE %s
5
6; RUN-TODO: llc -mtriple=mips64-linux-gnu -relocation-model=static -target-abi o32 < %s \
7; RUN-TODO:   | FileCheck --check-prefixes=ALL,O32 %s
8; RUN-TODO: llc -mtriple=mips64el-linux-gnu -relocation-model=static -target-abi o32 < %s \
9; RUN-TODO:   | FileCheck --check-prefixes=ALL,O32 %s
10
11; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=static -target-abi n32 < %s \
12; RUN:   | FileCheck --check-prefixes=ALL,N32,N32-BE %s
13; RUN: llc -mtriple=mips64el-linux-gnu -relocation-model=static -target-abi n32 < %s \
14; RUN:   | FileCheck --check-prefixes=ALL,N32,N32-LE %s
15
16; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=static -target-abi n64 < %s \
17; RUN:   | FileCheck --check-prefixes=ALL,N64,N64-BE %s
18; RUN: llc -mtriple=mips64el-linux-gnu -relocation-model=static -target-abi n64 < %s \
19; RUN:   | FileCheck --check-prefixes=ALL,N64,N64-LE %s
20
21; Test struct returns for all ABI's and byte orders.
22
23@struct_byte = global {i8} zeroinitializer
24@struct_2byte = global {i8,i8} zeroinitializer
25@struct_3xi16 = global {[3 x i16]} zeroinitializer
26@struct_6xi32 = global {[6 x i32]} zeroinitializer
27@struct_128xi16 = global {[128 x i16]} zeroinitializer
28
29declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i1)
30
31define inreg {i8} @ret_struct_i8() nounwind {
32entry:
33        %0 = load volatile {i8}, {i8}* @struct_byte
34        ret {i8} %0
35}
36
37; ALL-LABEL: ret_struct_i8:
38; O32-DAG:           lui [[R1:\$[0-9]+]], %hi(struct_byte)
39; O32-DAG:           lbu $2, %lo(struct_byte)([[R1]])
40
41; N32-LE-DAG:        lui [[R1:\$[0-9]+]], %hi(struct_byte)
42; N32-LE-DAG:        lb $2, %lo(struct_byte)([[R1]])
43
44; N32-BE-DAG:        lui [[R1:\$[0-9]+]], %hi(struct_byte)
45; N32-BE-DAG:        lb [[R2:\$[0-9]+]], %lo(struct_byte)([[R1]])
46; N32-BE-DAG:        dsll $2, [[R2]], 56
47
48; N64-LE-DAG:        lb $2, %lo(struct_byte)(${{[0-9]+}})
49
50; N64-BE-DAG:        lb [[R1:\$[0-9]+]], %lo(struct_byte)(${{[0-9]+}})
51; N64-BE-DAG:        dsll $2, [[R1]], 56
52
53; This test is based on the way clang currently lowers {i8,i8} to {i16}.
54; FIXME: It should probably work for without any lowering too but this doesn't
55;        work as expected. Each member gets mapped to a register rather than
56;        packed into a single register.
57define inreg {i16} @ret_struct_i16() nounwind {
58entry:
59        %retval = alloca {i8,i8}, align 1
60        %0 = bitcast {i8,i8}* %retval to i8*
61        call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* getelementptr inbounds ({i8,i8}, {i8,i8}* @struct_2byte, i32 0, i32 0), i64 2, i1 false)
62        %1 = bitcast {i8,i8}* %retval to {i16}*
63        %2 = load volatile {i16}, {i16}* %1
64        ret {i16} %2
65}
66
67; ALL-LABEL: ret_struct_i16:
68; O32-DAG:           lui [[R1:\$[0-9]+]], %hi(struct_2byte)
69; O32-DAG:           lhu [[R2:\$[0-9]+]], %lo(struct_2byte)([[R1]])
70; O32-DAG:           sh  [[R2]], 0([[SP:\$sp]])
71; O32-DAG:           lhu $2, 0([[SP:\$sp]])
72
73; N32-LE-DAG:        lui [[R1:\$[0-9]+]], %hi(struct_2byte)
74; N32-LE-DAG:        lhu [[R2:\$[0-9]+]], %lo(struct_2byte)([[R1]])
75; N32-LE-DAG:        sh  [[R2]], 8([[SP:\$sp]])
76; N32-LE-DAG:        lh  $2, 8([[SP:\$sp]])
77
78; N32-BE-DAG:        lui [[R1:\$[0-9]+]], %hi(struct_2byte)
79; N32-BE-DAG:        lhu [[R2:\$[0-9]+]], %lo(struct_2byte)([[R1]])
80; N32-BE-DAG:        sh  [[R2]], 8([[SP:\$sp]])
81; N32-BE-DAG:        lh  [[R3:\$[0-9]+]], 8([[SP:\$sp]])
82; N32-BE-DAG:        dsll $2, [[R3]], 48
83
84; N64-LE-DAG:        daddiu $[[R0:[0-9]+]], ${{[0-9]+}}, %hi(struct_2byte)
85; N64-LE-DAG:        dsll [[R1:\$[0-9]]], $[[R0]], 16
86; N64-LE-DAG:        lhu [[R2:\$[0-9]+]], %lo(struct_2byte)([[R1]])
87; N64-LE-DAG:        sh  [[R2]], 8([[SP:\$sp]])
88; N64-LE-DAG:        lh  $2, 8([[SP:\$sp]])
89
90; N64-BE-DAG:        daddiu $[[R0:[0-9]+]], ${{[0-9]+}}, %hi(struct_2byte)
91; N64-BE-DAG:        dsll $[[R1:[0-9]]], $[[R0]], 16
92; N64-BE-DAG:        lhu [[R2:\$[0-9]+]], %lo(struct_2byte)($[[R1]])
93; N64-BE-DAG:        sh  [[R2]], 8([[SP:\$sp]])
94; N64-BE-DAG:        lh  [[R3:\$[0-9]+]], 8([[SP:\$sp]])
95; N64-BE-DAG:        dsll $2, [[R3]], 48
96
97; Ensure that structures bigger than 32-bits but smaller than 64-bits are
98; also returned in the upper bits on big endian targets. Previously, these were
99; missed by the CCPromoteToType and the shift didn't happen.
100define inreg {i48} @ret_struct_3xi16() nounwind {
101entry:
102        %0 = load volatile i48, i48* bitcast ({[3 x i16]}* @struct_3xi16 to i48*), align 2
103        %1 = insertvalue {i48} undef, i48 %0, 0
104        ret {i48} %1
105}
106
107; ALL-LABEL: ret_struct_3xi16:
108
109; O32-BE-DAG:        lui [[PTR_HI:\$[0-9]+]], %hi(struct_3xi16)
110; O32-BE-DAG:        addiu [[PTR_LO:\$[0-9]+]], [[PTR_HI]], %lo(struct_3xi16)
111; O32-BE-DAG:        lhu [[R1:\$[0-9]+]], 4([[PTR_LO]])
112; O32-BE-DAG:        lw [[R2:\$[0-9]+]], %lo(struct_3xi16)([[PTR_HI]])
113; O32-BE-DAG:        sll [[R3:\$[0-9]+]], [[R2]], 16
114; O32-BE-DAG:        or  $3, [[R1]], [[R3]]
115; O32-BE-DAG:        srl $2, [[R2]], 16
116
117; O32-LE-DAG:        lui [[PTR_HI:\$[0-9]+]], %hi(struct_3xi16)
118; O32-LE-DAG:        addiu [[PTR_LO:\$[0-9]+]], [[PTR_HI]], %lo(struct_3xi16)
119; O32-LE-DAG:        lhu $3, 4([[PTR_LO]])
120; O32-LE-DAG:        lw $2, %lo(struct_3xi16)([[PTR_HI]])
121
122; N32-LE-DAG:        lui [[PTR_HI:\$[0-9]+]], %hi(struct_3xi16)
123; N32-LE-DAG:        addiu [[PTR_LO:\$[0-9]+]], [[PTR_HI]], %lo(struct_3xi16)
124; N32-LE-DAG:        lh [[R1:\$[0-9]+]], 4([[PTR_LO]])
125; N32-LE-DAG:        lwu [[R2:\$[0-9]+]], %lo(struct_3xi16)([[PTR_HI]])
126; N32-LE-DAG:        dsll [[R3:\$[0-9]+]], [[R1]], 32
127; N32-LE-DAG:        or $2, [[R2]], [[R3]]
128
129; N32-BE-DAG:        lui [[PTR_HI:\$[0-9]+]], %hi(struct_3xi16)
130; N32-BE-DAG:        addiu [[PTR_LO:\$[0-9]+]], [[PTR_HI]], %lo(struct_3xi16)
131; N32-BE-DAG:        lw [[R1:\$[0-9]+]], %lo(struct_3xi16)([[PTR_HI]])
132; N32-BE-DAG:        dsll [[R2:\$[0-9]+]], [[R1]], 16
133; N32-BE-DAG:        lhu [[R3:\$[0-9]+]], 4([[PTR_LO]])
134; N32-BE-DAG:        or [[R4:\$[0-9]+]], [[R3]], [[R2]]
135; N32-BE-DAG:        dsll $2, [[R4]], 16
136
137; N64-LE-DAG:        daddiu [[PTR:\$[0-9]+]], [[R0:\$[0-9]+]], %lo(struct_3xi16)
138; N64-LE-DAG:        lh [[R1:\$[0-9]+]], 4([[PTR]])
139; N64-LE-DAG:        lwu [[R2:\$[0-9]+]], %lo(struct_3xi16)([[R0]])
140; N64-LE-DAG:        dsll [[R3:\$[0-9]+]], [[R1]], 32
141; N64-LE-DAG:        or $2, [[R2]], [[R3]]
142
143; N64-BE-DAG:        daddiu [[PTR:\$[0-9]+]], [[R0:\$[0-9]+]], %lo(struct_3xi16)
144; N64-BE-DAG:        lw [[R1:\$[0-9]+]], %lo(struct_3xi16)([[R0]])
145; N64-BE-DAG:        dsll [[R2:\$[0-9]+]], [[R1]], 16
146; N64-BE-DAG:        lhu [[R3:\$[0-9]+]], 4([[PTR]])
147; N64-BE-DAG:        or [[R4:\$[0-9]+]], [[R3]], [[R2]]
148; N64-BE-DAG:        dsll $2, [[R4]], 16
149
150; Ensure that large structures (>128-bit) are returned indirectly.
151; We pick an extremely large structure so we don't have to match inlined memcpy's.
152define void @ret_struct_128xi16({[128 x i16]}* sret({[128 x i16]}) %returnval) {
153entry:
154        %0 = bitcast {[128 x i16]}* %returnval to i8*
155        call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 2 %0, i8* align 2 bitcast ({[128 x i16]}* @struct_128xi16 to i8*), i64 256, i1 false)
156        ret void
157}
158
159; ALL-LABEL: ret_struct_128xi16:
160
161; sret pointer is already in $4
162; O32-DAG:        lui [[PTR:\$[0-9]+]], %hi(struct_128xi16)
163; O32-DAG:        addiu $5, [[PTR]], %lo(struct_128xi16)
164; O32:            jal memcpy
165
166; sret pointer is already in $4
167; N32-DAG:        lui [[PTR_HI:\$[0-9]+]], %hi(struct_128xi16)
168; N32-DAG:        addiu [[PTR:\$[0-9]+]], [[PTR_HI]], %lo(struct_128xi16)
169; N32:            jal memcpy
170
171; sret pointer is already in $4
172; N64-DAG:        lui ${{[0-9]}}, %highest(struct_128xi16)
173; N64:            jal memcpy
174
175; Ensure that large structures (>128-bit) are returned indirectly.
176; This will generate inlined memcpy's anyway so pick the smallest large
177; structure
178; This time we let the backend lower the sret argument.
179define {[6 x i32]} @ret_struct_6xi32() {
180entry:
181        %0 = load volatile {[6 x i32]}, {[6 x i32]}* @struct_6xi32, align 2
182        ret {[6 x i32]} %0
183}
184
185; ALL-LABEL: ret_struct_6xi32:
186
187; sret pointer is already in $4
188; O32-DAG:        lui [[PTR_HI:\$[0-9]+]], %hi(struct_6xi32)
189; O32-DAG:        addiu [[PTR:\$[0-9]+]], [[PTR_HI]], %lo(struct_6xi32)
190; O32-DAG:        lw [[T0:\$[0-9]+]], %lo(struct_6xi32)([[PTR]])
191; O32-DAG:        lw [[T1:\$[0-9]+]], 4([[PTR]])
192; O32-DAG:        lw [[T2:\$[0-9]+]], 8([[PTR]])
193; O32-DAG:        lw [[T3:\$[0-9]+]], 12([[PTR]])
194; O32-DAG:        lw [[T4:\$[0-9]+]], 16([[PTR]])
195; O32-DAG:        lw [[T5:\$[0-9]+]], 20([[PTR]])
196; O32-DAG:        sw [[T0]], 0($4)
197; O32-DAG:        sw [[T1]], 4($4)
198; O32-DAG:        sw [[T2]], 8($4)
199; O32-DAG:        sw [[T3]], 12($4)
200; O32-DAG:        sw [[T4]], 16($4)
201; O32-DAG:        sw [[T5]], 20($4)
202
203; FIXME: This signext isn't necessary. Like integers, pointers are
204;        but unlike integers, pointers cannot have the signext attribute.
205;        In this case we don't have anywhere to put the signext either since
206;        the sret argument is invented by the backend.
207; N32-DAG:        sll [[RET_PTR:\$[0-9]+]], $4, 0
208; N32-DAG:        lui [[PTR_HI:\$[0-9]+]], %hi(struct_6xi32)
209; N32-DAG:        addiu [[PTR:\$[0-9]+]], [[PTR_HI]], %lo(struct_6xi32)
210; N32-DAG:        lw [[T0:\$[0-9]+]], %lo(struct_6xi32)([[PTR]])
211; N32-DAG:        lw [[T1:\$[0-9]+]], 4([[PTR]])
212; N32-DAG:        lw [[T2:\$[0-9]+]], 8([[PTR]])
213; N32-DAG:        lw [[T3:\$[0-9]+]], 12([[PTR]])
214; N32-DAG:        lw [[T4:\$[0-9]+]], 16([[PTR]])
215; N32-DAG:        lw [[T5:\$[0-9]+]], 20([[PTR]])
216; N32-DAG:        sw [[T0]], 0([[RET_PTR]])
217; N32-DAG:        sw [[T1]], 4([[RET_PTR]])
218; N32-DAG:        sw [[T2]], 8([[RET_PTR]])
219; N32-DAG:        sw [[T3]], 12([[RET_PTR]])
220; N32-DAG:        sw [[T4]], 16([[RET_PTR]])
221; N32-DAG:        sw [[T5]], 20([[RET_PTR]])
222
223; sret pointer is already in $4
224; N64-DAG:        lui [[PTR_HI:\$[0-9]+]], %highest(struct_6xi32)
225; N64-DAG:        daddiu [[PTR:\$[0-9]+]], [[PTR_HI]], %lo(struct_6xi32)
226; N64-DAG:        lw [[T1:\$[0-9]+]], 4([[PTR]])
227; N64-DAG:        lw [[T2:\$[0-9]+]], 8([[PTR]])
228; N64-DAG:        lw [[T3:\$[0-9]+]], 12([[PTR]])
229; N64-DAG:        lw [[T4:\$[0-9]+]], 16([[PTR]])
230; N64-DAG:        lw [[T5:\$[0-9]+]], 20([[PTR]])
231; N64-DAG:        lw [[T0:\$[0-9]+]], %lo(struct_6xi32)([[PTR_HI]])
232; N64-DAG:        sw [[T0]], 0($4)
233; N64-DAG:        sw [[T1]], 4($4)
234; N64-DAG:        sw [[T2]], 8($4)
235; N64-DAG:        sw [[T3]], 12($4)
236; N64-DAG:        sw [[T4]], 16($4)
237; N64-DAG:        sw [[T5]], 20($4)
238