aboutsummaryrefslogtreecommitdiffstats
path: root/test/CodeGen/ARM/struct_byval.ll
blob: d7b9b477ec1efb9ed01f5420b25c1e337ca57a0f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
; RUN: llc < %s -mtriple=armv7-apple-ios6.0 | FileCheck %s
; RUN: llc < %s -mtriple=thumbv7-apple-ios6.0 | FileCheck %s -check-prefix=THUMB
; RUN: llc < %s -mtriple=armv7-unknown-nacl-gnueabi | FileCheck %s -check-prefix=NACL
; RUN: llc < %s -mtriple=armv5-none-linux-gnueabi | FileCheck %s -check-prefix=NOMOVT

; NOMOVT-NOT: movt

; rdar://9877866
%struct.SmallStruct = type { i32, [8 x i32], [37 x i8] }
%struct.LargeStruct = type { i32, [1001 x i8], [300 x i32] }

define i32 @f() nounwind ssp {
entry:
; CHECK-LABEL: f:
; CHECK: ldr
; CHECK: str
; CHECK-NOT:bne
; THUMB-LABEL: f:
; THUMB: ldr
; THUMB: str
; THUMB-NOT:bne
  %st = alloca %struct.SmallStruct, align 4
  %call = call i32 @e1(%struct.SmallStruct* byval %st)
  ret i32 0
}

; Generate a loop for large struct byval
define i32 @g() nounwind ssp {
entry:
; CHECK-LABEL: g:
; CHECK: ldr
; CHECK: sub
; CHECK: str
; CHECK: bne
; THUMB-LABEL: g:
; THUMB: ldr
; THUMB: sub
; THUMB: str
; THUMB: bne
; NACL-LABEL: g:
; Ensure that use movw instead of constpool for the loop trip count. But don't
; match the __stack_chk_guard movw
; NACL: movw r{{[1-9]}}, #
; NACL: ldr
; NACL: sub
; NACL: str
; NACL: bne
  %st = alloca %struct.LargeStruct, align 4
  %call = call i32 @e2(%struct.LargeStruct* byval %st)
  ret i32 0
}

; Generate a loop using NEON instructions
define i32 @h() nounwind ssp {
entry:
; CHECK-LABEL: h:
; CHECK: vld1
; CHECK: sub
; CHECK: vst1
; CHECK: bne
; THUMB-LABEL: h:
; THUMB: vld1
; THUMB: sub
; THUMB: vst1
; THUMB: bne
; NACL: movw r{{[1-9]}}, #
; NACL: vld1
; NACL: sub
; NACL: vst1
; NACL: bne
  %st = alloca %struct.LargeStruct, align 16
  %call = call i32 @e3(%struct.LargeStruct* byval align 16 %st)
  ret i32 0
}

declare i32 @e1(%struct.SmallStruct* nocapture byval %in) nounwind
declare i32 @e2(%struct.LargeStruct* nocapture byval %in) nounwind
declare i32 @e3(%struct.LargeStruct* nocapture byval align 16 %in) nounwind

; rdar://12442472
; We can't do tail call since address of s is passed to the callee and part of
; s is in caller's local frame.
define void @f3(%struct.SmallStruct* nocapture byval %s) nounwind optsize {
; CHECK-LABEL: f3
; CHECK: bl _consumestruct
; THUMB-LABEL: f3
; THUMB: blx _consumestruct
entry:
  %0 = bitcast %struct.SmallStruct* %s to i8*
  tail call void @consumestruct(i8* %0, i32 80) optsize
  ret void
}

define void @f4(%struct.SmallStruct* nocapture byval %s) nounwind optsize {
; CHECK-LABEL: f4
; CHECK: bl _consumestruct
; THUMB-LABEL: f4
; THUMB: blx _consumestruct
entry:
  %addr = getelementptr inbounds %struct.SmallStruct, %struct.SmallStruct* %s, i32 0, i32 0
  %0 = bitcast i32* %addr to i8*
  tail call void @consumestruct(i8* %0, i32 80) optsize
  ret void
}

; We can do tail call here since s is in the incoming argument area.
define void @f5(i32 %a, i32 %b, i32 %c, i32 %d, %struct.SmallStruct* nocapture byval %s) nounwind optsize {
; CHECK-LABEL: f5
; CHECK: b _consumestruct
; THUMB-LABEL: f5
; THUMB: b.w _consumestruct
entry:
  %0 = bitcast %struct.SmallStruct* %s to i8*
  tail call void @consumestruct(i8* %0, i32 80) optsize
  ret void
}

define void @f6(i32 %a, i32 %b, i32 %c, i32 %d, %struct.SmallStruct* nocapture byval %s) nounwind optsize {
; CHECK-LABEL: f6
; CHECK: b _consumestruct
; THUMB-LABEL: f6
; THUMB: b.w _consumestruct
entry:
  %addr = getelementptr inbounds %struct.SmallStruct, %struct.SmallStruct* %s, i32 0, i32 0
  %0 = bitcast i32* %addr to i8*
  tail call void @consumestruct(i8* %0, i32 80) optsize
  ret void
}

declare void @consumestruct(i8* nocapture %structp, i32 %structsize) nounwind

; PR17309
%struct.I.8 = type { [10 x i32], [3 x i8] }

declare void @use_I(%struct.I.8* byval)
define void @test_I_16() {
; CHECK-LABEL: test_I_16
; CHECK: ldrb
; CHECK: strb
; THUMB-LABEL: test_I_16
; THUMB: ldrb
; THUMB: strb
entry:
  call void @use_I(%struct.I.8* byval align 16 undef)
  ret void
}