xref: /llvm-project/llvm/test/CodeGen/ARM/fast-isel.ll (revision bed1c7f061aa12417aa081e334afdba45767b938)
1; RUN: llc < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=ARM --check-prefix=ARM-MACHO
2; RUN: llc < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-linux-gnueabi -verify-machineinstrs | FileCheck %s --check-prefix=ARM --check-prefix=ARM-ELF
3; RUN: llc < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=THUMB
4
5; Very basic fast-isel functionality.
6define i32 @test0(i32 %a, i32 %b) nounwind {
7entry:
8  %a.addr = alloca i32, align 4
9  %b.addr = alloca i32, align 4
10  store i32 %a, ptr %a.addr
11  store i32 %b, ptr %b.addr
12  %tmp = load i32, ptr %a.addr
13  %tmp1 = load i32, ptr %b.addr
14  %add = add nsw i32 %tmp, %tmp1
15  ret i32 %add
16}
17
18; Check truncate to bool
19define void @test1(i32 %tmp) nounwind {
20entry:
21%tobool = trunc i32 %tmp to i1
22br i1 %tobool, label %if.then, label %if.end
23
24if.then:                                          ; preds = %entry
25call void @test1(i32 0)
26br label %if.end
27
28if.end:                                           ; preds = %if.then, %entry
29ret void
30; ARM-LABEL: test1:
31; ARM: tst r0, #1
32; THUMB-LABEL: test1:
33; THUMB: tst.w r0, #1
34}
35
36; Check some simple operations with immediates
37define void @test2(i32 %tmp, ptr %ptr) nounwind {
38; THUMB-LABEL: test2:
39; ARM-LABEL: test2:
40
41b1:
42  %a = add i32 %tmp, 4096
43  store i32 %a, ptr %ptr
44  br label %b2
45
46; THUMB: add.w {{.*}} #4096
47; ARM: add {{.*}} #4096
48
49b2:
50  %b = add i32 %tmp, 4095
51  store i32 %b, ptr %ptr
52  br label %b3
53; THUMB: addw {{.*}} #4095
54; ARM: movw {{.*}} #4095
55; ARM: add
56
57b3:
58  %c = or i32 %tmp, 4
59  store i32 %c, ptr %ptr
60  ret void
61
62; THUMB: orr {{.*}} #4
63; ARM: orr {{.*}} #4
64}
65
66define void @test3(i32 %tmp, ptr %ptr1, ptr %ptr2, ptr %ptr3) nounwind {
67; THUMB-LABEL: test3:
68; ARM-LABEL: test3:
69
70bb1:
71  %a1 = trunc i32 %tmp to i16
72  %a2 = trunc i16 %a1 to i8
73  %a3 = trunc i8 %a2 to i1
74  %a4 = zext i1 %a3 to i8
75  store i8 %a4, ptr %ptr3
76  %a5 = zext i8 %a4 to i16
77  store i16 %a5, ptr %ptr2
78  %a6 = zext i16 %a5 to i32
79  store i32 %a6, ptr %ptr1
80  br label %bb2
81
82; THUMB: and
83; THUMB: strb
84; THUMB: and{{.*}}, #255
85; THUMB: strh
86; THUMB: uxth
87; ARM: and
88; ARM: strb
89; ARM: and{{.*}}, #255
90; ARM: strh
91; ARM: uxth
92
93bb2:
94  %b1 = trunc i32 %tmp to i16
95  %b2 = trunc i16 %b1 to i8
96  store i8 %b2, ptr %ptr3
97  %b3 = sext i8 %b2 to i16
98  store i16 %b3, ptr %ptr2
99  %b4 = sext i16 %b3 to i32
100  store i32 %b4, ptr %ptr1
101  br label %bb3
102
103; THUMB: strb
104; THUMB: sxtb
105; THUMB: strh
106; THUMB: sxth
107; ARM: strb
108; ARM: sxtb
109; ARM: strh
110; ARM: sxth
111
112bb3:
113  %c1 = load i8, ptr %ptr3
114  %c2 = load i16, ptr %ptr2
115  %c3 = load i32, ptr %ptr1
116  %c4 = zext i8 %c1 to i32
117  %c5 = sext i16 %c2 to i32
118  %c6 = add i32 %c4, %c5
119  %c7 = sub i32 %c3, %c6
120  store i32 %c7, ptr %ptr1
121  ret void
122
123; THUMB: ldrb
124; THUMB: ldrh
125; THUMB: and{{.*}}, #255
126; THUMB: sxth
127; THUMB: add
128; THUMB: sub
129; ARM: ldrb
130; ARM: ldrh
131; ARM: and{{.*}}, #255
132; ARM: sxth
133; ARM: add
134; ARM: sub
135}
136
137; Check loads/stores with globals
138@test4g = external global i32
139
140define void @test4() {
141  %a = load i32, ptr @test4g
142  %b = add i32 %a, 1
143  store i32 %b, ptr @test4g
144  ret void
145
146
147; Note that relocations are either movw/movt or constant pool
148; loads. Different platforms will select different approaches.
149
150; THUMB: {{(movw r0, :lower16:L_test4g\$non_lazy_ptr)|(ldr.n r0, .LCPI)}}
151; THUMB: {{(movt r0, :upper16:L_test4g\$non_lazy_ptr)?}}
152; THUMB: ldr [[REG:r[0-9]+]], [r0]
153; THUMB: ldr [[REG1:r[0-9]+]], [[[REG]]]
154; THUMB: adds [[REG1]], #1
155; THUMB: {{(movw r1, :lower16:L_test4g\$non_lazy_ptr)|(ldr.n r0, .LCPI)}}
156; THUMB: {{(movt r1, :upper16:L_test4g\$non_lazy_ptr)?}}
157; THUMB: ldr [[REG2:r[0-9]+]], [r1]
158; THUMB: str [[REG1]], [[[REG2]]]
159
160; ARM-MACHO: {{(movw r0, :lower16:L_test4g\$non_lazy_ptr)|(ldr r0, .LCPI)}}
161; ARM-MACHO: {{(movt r0, :upper16:L_test4g\$non_lazy_ptr)?}}
162; ARM-MACHO: ldr [[REG:r[0-9]+]], [r0]
163
164; ARM-ELF: movw [[REG:r[0-9]+]], :lower16:test4g
165; ARM-ELF: movt [[REG]], :upper16:test4g
166
167; ARM: ldr [[REG1:r[0-9]+]], [[[REG]]]
168; ARM: add [[REG2:r[0-9]+]], [[REG1]], #1
169
170; ARM-MACHO: {{(movw r1, :lower16:L_test4g\$non_lazy_ptr)|(ldr r0, .LCPI)}}
171; ARM-MACHO: {{(movt r1, :upper16:L_test4g\$non_lazy_ptr)?}}
172; ARM-MACHO: ldr [[REG3:r[0-9]+]], [r1]
173
174; ARM-ELF: movw [[REG3:r[0-9]+]], :lower16:test4g
175; ARM-ELF: movt [[REG3]], :upper16:test4g
176
177; ARM: str [[REG2]], [[[REG3]]]
178}
179
180; ARM: @urem_fold
181; THUMB: @urem_fold
182; ARM: and r0, r0, #31
183; THUMB: and r0, r0, #31
184define i32 @urem_fold(i32 %a) nounwind {
185  %rem = urem i32 %a, 32
186  ret i32 %rem
187}
188
189define i32 @trap_intrinsic() noreturn nounwind  {
190entry:
191; ARM: @trap_intrinsic
192; THUMB: @trap_intrinsic
193; ARM: trap
194; THUMB: trap
195  tail call void @llvm.trap( )
196  unreachable
197}
198
199declare void @llvm.trap() nounwind
200