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
5 ; Very basic fast-isel functionality.
6 define i32 @test0(i32 %a, i32 %b) nounwind {
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
18 ; Check truncate to bool
19 define void @test1(i32 %tmp) nounwind {
21 %tobool = trunc i32 %tmp to i1
22 br i1 %tobool, label %if.then, label %if.end
24 if.then: ; preds = %entry
25 call void @test1(i32 0)
28 if.end: ; preds = %if.then, %entry
36 ; Check some simple operations with immediates
37 define void @test2(i32 %tmp, i32* %ptr) nounwind {
42 %a = add i32 %tmp, 4096
43 store i32 %a, i32* %ptr
46 ; THUMB: add.w {{.*}} #4096
47 ; ARM: add {{.*}} #4096
50 %b = add i32 %tmp, 4095
51 store i32 %b, i32* %ptr
53 ; THUMB: addw {{.*}} #4095
54 ; ARM: movw {{.*}} #4095
59 store i32 %c, i32* %ptr
62 ; THUMB: orr {{.*}} #4
66 define void @test3(i32 %tmp, i32* %ptr1, i16* %ptr2, i8* %ptr3) nounwind {
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
84 ; THUMB: and{{.*}}, #255
89 ; ARM: and{{.*}}, #255
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
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
125 ; THUMB: and{{.*}}, #255
131 ; ARM: and{{.*}}, #255
137 ; Check loads/stores with globals
138 @test4g = external global i32
140 define void @test4() {
141 %a = load i32, i32* @test4g
143 store i32 %b, i32* @test4g
147 ; Note that relocations are either movw/movt or constant pool
148 ; loads. Different platforms will select different approaches.
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: str [[REG1]], {{\[}}[[REG]]]
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 [[REG:r[0-9]+]], [r0]
161 ; ARM-ELF: movw [[REG:r[0-9]+]], :lower16:test4g
162 ; ARM-ELF: movt [[REG]], :upper16:test4g
164 ; ARM: ldr [[REG1:r[0-9]+]], {{\[}}[[REG]]]
165 ; ARM: add [[REG2:r[0-9]+]], [[REG1]], #1
166 ; ARM: str [[REG2]], {{\[}}[[REG]]]
171 ; ARM: and r0, r0, #31
172 ; THUMB: and r0, r0, #31
173 define i32 @urem_fold(i32 %a) nounwind {
174 %rem = urem i32 %a, 32
178 define i32 @trap_intrinsic() noreturn nounwind {
180 ; ARM: @trap_intrinsic
181 ; THUMB: @trap_intrinsic
184 tail call void @llvm.trap( )
188 declare void @llvm.trap() nounwind