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, i32* %a.addr
11  store i32 %b, i32* %b.addr
12  %tmp = load i32, i32* %a.addr
13  %tmp1 = load i32, i32* %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, i32* %ptr) nounwind {
38; THUMB-LABEL: test2:
39; ARM-LABEL: test2:
40
41b1:
42  %a = add i32 %tmp, 4096
43  store i32 %a, i32* %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, i32* %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, i32* %ptr
60  ret void
61
62; THUMB: orr {{.*}} #4
63; ARM: orr {{.*}} #4
64}
65
66define void @test3(i32 %tmp, i32* %ptr1, i16* %ptr2, i8* %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, i8* %ptr3
76  %a5 = zext i8 %a4 to i16
77  store i16 %a5, i16* %ptr2
78  %a6 = zext i16 %a5 to i32
79  store i32 %a6, i32* %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, i8* %ptr3
97  %b3 = sext i8 %b2 to i16
98  store i16 %b3, i16* %ptr2
99  %b4 = sext i16 %b3 to i32
100  store i32 %b4, i32* %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, i8* %ptr3
114  %c2 = load i16, i16* %ptr2
115  %c3 = load i32, i32* %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, i32* %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, i32* @test4g
142  %b = add i32 %a, 1
143  store i32 %b, i32* @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 r0, [r0]
153; THUMB: ldr r1, [r0]
154; THUMB: adds r1, #1
155; THUMB: str r1, [r0]
156
157; ARM-MACHO: {{(movw r0, :lower16:L_test4g\$non_lazy_ptr)|(ldr r0, .LCPI)}}
158; ARM-MACHO: {{(movt r0, :upper16:L_test4g\$non_lazy_ptr)?}}
159; ARM-MACHO: ldr r0, [r0]
160
161; ARM-ELF: movw r0, :lower16:test4g
162; ARM-ELF: movt r0, :upper16:test4g
163
164; ARM: ldr r1, [r0]
165; ARM: add r1, r1, #1
166; ARM: str r1, [r0]
167}
168
169; ARM: @urem_fold
170; THUMB: @urem_fold
171; ARM: and r0, r0, #31
172; THUMB: and r0, r0, #31
173define i32 @urem_fold(i32 %a) nounwind {
174  %rem = urem i32 %a, 32
175  ret i32 %rem
176}
177
178define i32 @trap_intrinsic() noreturn nounwind  {
179entry:
180; ARM: @trap_intrinsic
181; THUMB: @trap_intrinsic
182; ARM: trap
183; THUMB: trap
184  tail call void @llvm.trap( )
185  unreachable
186}
187
188declare void @llvm.trap() nounwind
189