1; RUN: llc < %s -mtriple=armv7-apple-ios6.0 | FileCheck %s
2; RUN: llc < %s -mtriple=thumbv7-apple-ios6.0 | FileCheck %s -check-prefix=THUMB
3
4; rdar://9877866
5%struct.SmallStruct = type { i32, [8 x i32], [37 x i8] }
6%struct.LargeStruct = type { i32, [1001 x i8], [300 x i32] }
7
8define i32 @f() nounwind ssp {
9entry:
10; CHECK-LABEL: f:
11; CHECK: ldr
12; CHECK: str
13; CHECK-NOT:bne
14; THUMB-LABEL: f:
15; THUMB: ldr
16; THUMB: str
17; THUMB-NOT:bne
18  %st = alloca %struct.SmallStruct, align 4
19  %call = call i32 @e1(%struct.SmallStruct* byval %st)
20  ret i32 0
21}
22
23; Generate a loop for large struct byval
24define i32 @g() nounwind ssp {
25entry:
26; CHECK-LABEL: g:
27; CHECK: ldr
28; CHECK: sub
29; CHECK: str
30; CHECK: bne
31; THUMB-LABEL: g:
32; THUMB: ldr
33; THUMB: sub
34; THUMB: str
35; THUMB: bne
36  %st = alloca %struct.LargeStruct, align 4
37  %call = call i32 @e2(%struct.LargeStruct* byval %st)
38  ret i32 0
39}
40
41; Generate a loop using NEON instructions
42define i32 @h() nounwind ssp {
43entry:
44; CHECK-LABEL: h:
45; CHECK: vld1
46; CHECK: sub
47; CHECK: vst1
48; CHECK: bne
49; THUMB-LABEL: h:
50; THUMB: vld1
51; THUMB: sub
52; THUMB: vst1
53; THUMB: bne
54  %st = alloca %struct.LargeStruct, align 16
55  %call = call i32 @e3(%struct.LargeStruct* byval align 16 %st)
56  ret i32 0
57}
58
59declare i32 @e1(%struct.SmallStruct* nocapture byval %in) nounwind
60declare i32 @e2(%struct.LargeStruct* nocapture byval %in) nounwind
61declare i32 @e3(%struct.LargeStruct* nocapture byval align 16 %in) nounwind
62
63; rdar://12442472
64; We can't do tail call since address of s is passed to the callee and part of
65; s is in caller's local frame.
66define void @f3(%struct.SmallStruct* nocapture byval %s) nounwind optsize {
67; CHECK-LABEL: f3
68; CHECK: bl _consumestruct
69; THUMB-LABEL: f3
70; THUMB: blx _consumestruct
71entry:
72  %0 = bitcast %struct.SmallStruct* %s to i8*
73  tail call void @consumestruct(i8* %0, i32 80) optsize
74  ret void
75}
76
77define void @f4(%struct.SmallStruct* nocapture byval %s) nounwind optsize {
78; CHECK-LABEL: f4
79; CHECK: bl _consumestruct
80; THUMB-LABEL: f4
81; THUMB: blx _consumestruct
82entry:
83  %addr = getelementptr inbounds %struct.SmallStruct* %s, i32 0, i32 0
84  %0 = bitcast i32* %addr to i8*
85  tail call void @consumestruct(i8* %0, i32 80) optsize
86  ret void
87}
88
89; We can do tail call here since s is in the incoming argument area.
90define void @f5(i32 %a, i32 %b, i32 %c, i32 %d, %struct.SmallStruct* nocapture byval %s) nounwind optsize {
91; CHECK-LABEL: f5
92; CHECK: b _consumestruct
93; THUMB-LABEL: f5
94; THUMB: b.w _consumestruct
95entry:
96  %0 = bitcast %struct.SmallStruct* %s to i8*
97  tail call void @consumestruct(i8* %0, i32 80) optsize
98  ret void
99}
100
101define void @f6(i32 %a, i32 %b, i32 %c, i32 %d, %struct.SmallStruct* nocapture byval %s) nounwind optsize {
102; CHECK-LABEL: f6
103; CHECK: b _consumestruct
104; THUMB-LABEL: f6
105; THUMB: b.w _consumestruct
106entry:
107  %addr = getelementptr inbounds %struct.SmallStruct* %s, i32 0, i32 0
108  %0 = bitcast i32* %addr to i8*
109  tail call void @consumestruct(i8* %0, i32 80) optsize
110  ret void
111}
112
113declare void @consumestruct(i8* nocapture %structp, i32 %structsize) nounwind
114
115; PR17309
116%struct.I.8 = type { [10 x i32], [3 x i8] }
117
118declare void @use_I(%struct.I.8* byval)
119define void @test_I_16() {
120; CHECK-LABEL: test_I_16
121; CHECK: ldrb
122; CHECK: strb
123; THUMB-LABEL: test_I_16
124; THUMB: ldrb
125; THUMB: strb
126entry:
127  call void @use_I(%struct.I.8* byval align 16 undef)
128  ret void
129}
130