1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=thumbv6m-none-eabi %s -o - | FileCheck %s --check-prefixes=CHECK-T1
3 ; RUN: llc -mtriple=thumbv7m-none-eabi %s -o - | FileCheck %s --check-prefixes=CHECK-T2
4 ; RUN: llc -mtriple=armv7a-none-eabi %s -o - | FileCheck %s --check-prefixes=CHECK-A
6 define i32 @test_add_i3(i1 %tst, i32 %a, i32 %b) {
7 ; CHECK-T1-LABEL: test_add_i3:
9 ; CHECK-T1-NEXT: .save {r4, lr}
10 ; CHECK-T1-NEXT: push {r4, lr}
11 ; CHECK-T1-NEXT: lsls r0, r0, #31
12 ; CHECK-T1-NEXT: bne .LBB0_2
13 ; CHECK-T1-NEXT: @ %bb.1:
14 ; CHECK-T1-NEXT: movs r0, #3
15 ; CHECK-T1-NEXT: bics r2, r0
16 ; CHECK-T1-NEXT: mov r4, r2
17 ; CHECK-T1-NEXT: b .LBB0_3
18 ; CHECK-T1-NEXT: .LBB0_2:
19 ; CHECK-T1-NEXT: mov r4, r1
20 ; CHECK-T1-NEXT: movs r0, #6
21 ; CHECK-T1-NEXT: bics r4, r0
22 ; CHECK-T1-NEXT: .LBB0_3:
23 ; CHECK-T1-NEXT: mov r0, r4
24 ; CHECK-T1-NEXT: bl foo
25 ; CHECK-T1-NEXT: adds r0, r4, #2
26 ; CHECK-T1-NEXT: pop {r4, pc}
28 ; CHECK-T2-LABEL: test_add_i3:
30 ; CHECK-T2-NEXT: .save {r4, lr}
31 ; CHECK-T2-NEXT: push {r4, lr}
32 ; CHECK-T2-NEXT: lsls r0, r0, #31
33 ; CHECK-T2-NEXT: bic r4, r2, #3
34 ; CHECK-T2-NEXT: it ne
35 ; CHECK-T2-NEXT: bicne r4, r1, #6
36 ; CHECK-T2-NEXT: mov r0, r4
37 ; CHECK-T2-NEXT: bl foo
38 ; CHECK-T2-NEXT: adds r0, r4, #2
39 ; CHECK-T2-NEXT: pop {r4, pc}
41 ; CHECK-A-LABEL: test_add_i3:
43 ; CHECK-A-NEXT: .save {r4, lr}
44 ; CHECK-A-NEXT: push {r4, lr}
45 ; CHECK-A-NEXT: bic r4, r2, #3
46 ; CHECK-A-NEXT: tst r0, #1
47 ; CHECK-A-NEXT: bicne r4, r1, #6
48 ; CHECK-A-NEXT: mov r0, r4
49 ; CHECK-A-NEXT: bl foo
50 ; CHECK-A-NEXT: orr r0, r4, #2
51 ; CHECK-A-NEXT: pop {r4, pc}
53 %tmp1 = and i32 %b, -4
54 %int = select i1 %tst, i32 %tmp, i32 %tmp1
56 ; Call to force %int into a register that isn't r0 so using the i3 form is a
58 call void @foo(i32 %int)
63 define i32 @test_add_i8(i32 %a, i32 %b, i1 %tst) {
64 ; CHECK-T1-LABEL: test_add_i8:
66 ; CHECK-T1-NEXT: lsls r2, r2, #31
67 ; CHECK-T1-NEXT: bne .LBB1_2
68 ; CHECK-T1-NEXT: @ %bb.1:
69 ; CHECK-T1-NEXT: ldr r0, .LCPI1_0
70 ; CHECK-T1-NEXT: ands r1, r0
71 ; CHECK-T1-NEXT: mov r0, r1
72 ; CHECK-T1-NEXT: adds r0, #12
73 ; CHECK-T1-NEXT: bx lr
74 ; CHECK-T1-NEXT: .LBB1_2:
75 ; CHECK-T1-NEXT: movs r1, #255
76 ; CHECK-T1-NEXT: bics r0, r1
77 ; CHECK-T1-NEXT: adds r0, #12
78 ; CHECK-T1-NEXT: bx lr
79 ; CHECK-T1-NEXT: .p2align 2
80 ; CHECK-T1-NEXT: @ %bb.3:
81 ; CHECK-T1-NEXT: .LCPI1_0:
82 ; CHECK-T1-NEXT: .long 4294966784 @ 0xfffffe00
84 ; CHECK-T2-LABEL: test_add_i8:
86 ; CHECK-T2-NEXT: movw r3, #511
87 ; CHECK-T2-NEXT: bics r1, r3
88 ; CHECK-T2-NEXT: lsls r2, r2, #31
89 ; CHECK-T2-NEXT: it ne
90 ; CHECK-T2-NEXT: bicne r1, r0, #255
91 ; CHECK-T2-NEXT: add.w r0, r1, #12
92 ; CHECK-T2-NEXT: bx lr
94 ; CHECK-A-LABEL: test_add_i8:
96 ; CHECK-A-NEXT: bfc r1, #0, #9
97 ; CHECK-A-NEXT: tst r2, #1
98 ; CHECK-A-NEXT: bicne r1, r0, #255
99 ; CHECK-A-NEXT: orr r0, r1, #12
100 ; CHECK-A-NEXT: bx lr
101 %tmp = and i32 %a, -256
102 %tmp1 = and i32 %b, -512
103 %int = select i1 %tst, i32 %tmp, i32 %tmp1
104 %res = or i32 %int, 12
108 define i32 @test_add_i12(i32 %a, i32 %b, i1 %tst) {
109 ; CHECK-T1-LABEL: test_add_i12:
111 ; CHECK-T1-NEXT: lsls r2, r2, #31
112 ; CHECK-T1-NEXT: bne .LBB2_2
113 ; CHECK-T1-NEXT: @ %bb.1:
114 ; CHECK-T1-NEXT: ldr r0, .LCPI2_1
115 ; CHECK-T1-NEXT: ands r1, r0
116 ; CHECK-T1-NEXT: mov r0, r1
117 ; CHECK-T1-NEXT: b .LBB2_3
118 ; CHECK-T1-NEXT: .LBB2_2:
119 ; CHECK-T1-NEXT: ldr r1, .LCPI2_0
120 ; CHECK-T1-NEXT: ands r0, r1
121 ; CHECK-T1-NEXT: .LBB2_3:
122 ; CHECK-T1-NEXT: ldr r1, .LCPI2_2
123 ; CHECK-T1-NEXT: adds r0, r0, r1
124 ; CHECK-T1-NEXT: bx lr
125 ; CHECK-T1-NEXT: .p2align 2
126 ; CHECK-T1-NEXT: @ %bb.4:
127 ; CHECK-T1-NEXT: .LCPI2_0:
128 ; CHECK-T1-NEXT: .long 4294963200 @ 0xfffff000
129 ; CHECK-T1-NEXT: .LCPI2_1:
130 ; CHECK-T1-NEXT: .long 4294959104 @ 0xffffe000
131 ; CHECK-T1-NEXT: .LCPI2_2:
132 ; CHECK-T1-NEXT: .long 854 @ 0x356
134 ; CHECK-T2-LABEL: test_add_i12:
136 ; CHECK-T2-NEXT: movw r3, #8191
137 ; CHECK-T2-NEXT: bics r1, r3
138 ; CHECK-T2-NEXT: movw r12, #4095
139 ; CHECK-T2-NEXT: lsls r2, r2, #31
140 ; CHECK-T2-NEXT: it ne
141 ; CHECK-T2-NEXT: bicne.w r1, r0, r12
142 ; CHECK-T2-NEXT: addw r0, r1, #854
143 ; CHECK-T2-NEXT: bx lr
145 ; CHECK-A-LABEL: test_add_i12:
147 ; CHECK-A-NEXT: bfc r1, #0, #13
148 ; CHECK-A-NEXT: bfc r0, #0, #12
149 ; CHECK-A-NEXT: tst r2, #1
150 ; CHECK-A-NEXT: moveq r0, r1
151 ; CHECK-A-NEXT: movw r1, #854
152 ; CHECK-A-NEXT: orr r0, r0, r1
153 ; CHECK-A-NEXT: bx lr
154 %tmp = and i32 %a, -4096
155 %tmp1 = and i32 %b, -8192
156 %int = select i1 %tst, i32 %tmp, i32 %tmp1
157 %res = or i32 %int, 854
161 define i32 @oradd(i32 %i, i32 %y) {
162 ; CHECK-T1-LABEL: oradd:
163 ; CHECK-T1: @ %bb.0: @ %entry
164 ; CHECK-T1-NEXT: lsls r0, r0, #1
165 ; CHECK-T1-NEXT: adds r0, r1, r0
166 ; CHECK-T1-NEXT: adds r0, r0, #1
167 ; CHECK-T1-NEXT: bx lr
169 ; CHECK-T2-LABEL: oradd:
170 ; CHECK-T2: @ %bb.0: @ %entry
171 ; CHECK-T2-NEXT: add.w r0, r1, r0, lsl #1
172 ; CHECK-T2-NEXT: adds r0, #1
173 ; CHECK-T2-NEXT: bx lr
175 ; CHECK-A-LABEL: oradd:
176 ; CHECK-A: @ %bb.0: @ %entry
177 ; CHECK-A-NEXT: add r0, r1, r0, lsl #1
178 ; CHECK-A-NEXT: add r0, r0, #1
179 ; CHECK-A-NEXT: bx lr
183 %add = add i32 %or, %y
187 define i32 @orgep(i32 %i, ptr %x, ptr %y) {
188 ; CHECK-T1-LABEL: orgep:
189 ; CHECK-T1: @ %bb.0: @ %entry
190 ; CHECK-T1-NEXT: lsls r0, r0, #3
191 ; CHECK-T1-NEXT: adds r0, r1, r0
192 ; CHECK-T1-NEXT: ldr r0, [r0, #4]
193 ; CHECK-T1-NEXT: bx lr
195 ; CHECK-T2-LABEL: orgep:
196 ; CHECK-T2: @ %bb.0: @ %entry
197 ; CHECK-T2-NEXT: add.w r0, r1, r0, lsl #3
198 ; CHECK-T2-NEXT: ldr r0, [r0, #4]
199 ; CHECK-T2-NEXT: bx lr
201 ; CHECK-A-LABEL: orgep:
202 ; CHECK-A: @ %bb.0: @ %entry
203 ; CHECK-A-NEXT: add r0, r1, r0, lsl #3
204 ; CHECK-A-NEXT: ldr r0, [r0, #4]
205 ; CHECK-A-NEXT: bx lr
208 %add = or i32 %mul, 1
209 %arrayidx = getelementptr inbounds i32, ptr %x, i32 %add
210 %0 = load i32, ptr %arrayidx, align 8
214 define i32 @orgeps(i32 %i, ptr %x, ptr %y) {
215 ; CHECK-T1-LABEL: orgeps:
216 ; CHECK-T1: @ %bb.0: @ %entry
217 ; CHECK-T1-NEXT: lsls r0, r0, #3
218 ; CHECK-T1-NEXT: adds r0, r1, r0
219 ; CHECK-T1-NEXT: ldr r1, [r0, #4]
220 ; CHECK-T1-NEXT: ldr r0, [r0, #8]
221 ; CHECK-T1-NEXT: adds r0, r0, r1
222 ; CHECK-T1-NEXT: bx lr
224 ; CHECK-T2-LABEL: orgeps:
225 ; CHECK-T2: @ %bb.0: @ %entry
226 ; CHECK-T2-NEXT: add.w r0, r1, r0, lsl #3
227 ; CHECK-T2-NEXT: ldrd r0, r1, [r0, #4]
228 ; CHECK-T2-NEXT: add r0, r1
229 ; CHECK-T2-NEXT: bx lr
231 ; CHECK-A-LABEL: orgeps:
232 ; CHECK-A: @ %bb.0: @ %entry
233 ; CHECK-A-NEXT: add r0, r1, r0, lsl #3
234 ; CHECK-A-NEXT: ldrd r0, r1, [r0, #4]
235 ; CHECK-A-NEXT: add r0, r1, r0
236 ; CHECK-A-NEXT: bx lr
239 %add = or i32 %mul, 1
240 %arrayidx = getelementptr inbounds i32, ptr %x, i32 %add
241 %0 = load i32, ptr %arrayidx, align 8
242 %add2 = add i32 %mul, 2
243 %arrayidx3 = getelementptr inbounds i32, ptr %x, i32 %add2
244 %1 = load i32, ptr %arrayidx3, align 8
245 %add4 = add i32 %1, %0
249 define i32 @multiuse(i32 %i, ptr %x, ptr %y) {
250 ; CHECK-T1-LABEL: multiuse:
251 ; CHECK-T1: @ %bb.0: @ %entry
252 ; CHECK-T1-NEXT: lsls r0, r0, #1
253 ; CHECK-T1-NEXT: adds r0, r0, #1
254 ; CHECK-T1-NEXT: lsls r2, r0, #2
255 ; CHECK-T1-NEXT: ldr r1, [r1, r2]
256 ; CHECK-T1-NEXT: adds r0, r0, r1
257 ; CHECK-T1-NEXT: bx lr
259 ; CHECK-T2-LABEL: multiuse:
260 ; CHECK-T2: @ %bb.0: @ %entry
261 ; CHECK-T2-NEXT: lsls r0, r0, #1
262 ; CHECK-T2-NEXT: adds r0, #1
263 ; CHECK-T2-NEXT: ldr.w r1, [r1, r0, lsl #2]
264 ; CHECK-T2-NEXT: add r0, r1
265 ; CHECK-T2-NEXT: bx lr
267 ; CHECK-A-LABEL: multiuse:
268 ; CHECK-A: @ %bb.0: @ %entry
269 ; CHECK-A-NEXT: mov r2, #1
270 ; CHECK-A-NEXT: orr r0, r2, r0, lsl #1
271 ; CHECK-A-NEXT: ldr r1, [r1, r0, lsl #2]
272 ; CHECK-A-NEXT: add r0, r0, r1
273 ; CHECK-A-NEXT: bx lr
276 %add = or i32 %mul, 1
277 %arrayidx = getelementptr inbounds i32, ptr %x, i32 %add
278 %0 = load i32, ptr %arrayidx, align 8
279 %r = add i32 %add, %0
283 declare void @foo(i32)