blob: b318c7642566013e0c7a2f04c383b0a94559e9d5 [file] [log] [blame]
Sam Parker9a2a89d2019-01-23 09:11:49 +00001; RUN: llc -mtriple=thumbv8m.main %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-V8M
2; RUN: llc -mtriple=armv8 %s -o - | FileCheck %s --check-prefix=CHECK-V8
3
4; CHECK-LABEL: pre_inc_ldr
5; CHECK: ldr{{.*}}, [r0, #4]!
6define i32* @pre_inc_ldr(i32* %base, i32 %a) {
7 %addr = getelementptr i32, i32* %base, i32 1
8 %ld = load i32, i32* %addr
9 %addr.1 = getelementptr i32, i32* %base, i32 2
10 %res = add i32 %ld, %a
11 store i32 %res, i32* %addr.1
12 ret i32* %addr
13}
14
15; CHECK-LABEL: pre_dec_ldr
16; CHECK: ldr{{.*}}, [r0, #-4]!
17define i32* @pre_dec_ldr(i32* %base, i32 %a) {
18 %addr = getelementptr i32, i32* %base, i32 -1
19 %ld = load i32, i32* %addr
20 %addr.1 = getelementptr i32, i32* %base, i32 2
21 %res = add i32 %ld, %a
22 store i32 %res, i32* %addr.1
23 ret i32* %addr
24}
25
26; CHECK-LABEL: post_inc_ldr
27; CHECK: ldr{{.*}}, [r0], #4
28define i32* @post_inc_ldr(i32* %base, i32* %addr.2, i32 %a) {
29 %addr = getelementptr i32, i32* %base, i32 0
30 %ld = load i32, i32* %addr
31 %addr.1 = getelementptr i32, i32* %base, i32 1
32 %res = add i32 %ld, %a
33 store i32 %res, i32* %addr.2
34 ret i32* %addr.1
35}
36
37; CHECK-LABEL: post_dec_ldr
38; CHECK: ldr{{.*}}, [r0], #-4
39define i32* @post_dec_ldr(i32* %base, i32* %addr.2, i32 %a) {
40 %addr = getelementptr i32, i32* %base, i32 0
41 %ld = load i32, i32* %addr
42 %addr.1 = getelementptr i32, i32* %base, i32 -1
43 %res = add i32 %ld, %a
44 store i32 %res, i32* %addr.2
45 ret i32* %addr.1
46}
47
48; CHECK-LABEL: pre_inc_str
49; CHECK: str{{.*}}, [r0, #4]!
50define i32* @pre_inc_str(i32* %base, i32 %a, i32 %b) {
51 %addr.1 = getelementptr i32, i32* %base, i32 1
52 %res = add i32 %a, %b
53 store i32 %res, i32* %addr.1
54 ret i32* %addr.1
55}
56
57; CHECK-LABEL: pre_dec_str
58; CHECK: str{{.*}}, [r0, #-4]!
59define i32* @pre_dec_str(i32* %base, i32 %a, i32 %b) {
60 %res = add i32 %a, %b
61 %addr.1 = getelementptr i32, i32* %base, i32 -1
62 store i32 %res, i32* %addr.1
63 ret i32* %addr.1
64}
65
66; CHECK-LABEL: post_inc_str
67; CHECK: str{{.*}}, [r0], #4
68define i32* @post_inc_str(i32* %base, i32 %a, i32 %b) {
69 %addr.1 = getelementptr i32, i32* %base, i32 1
70 %res = add i32 %a, %b
71 store i32 %res, i32* %base
72 ret i32* %addr.1
73}
74
75; CHECK-LABEL: post_dec_str
76; CHECK: str{{.*}}, [r0], #-4
77define i32* @post_dec_str(i32* %base, i32 %a, i32 %b) {
78 %addr.1 = getelementptr i32, i32* %base, i32 -1
79 %res = add i32 %a, %b
80 store i32 %res, i32* %base
81 ret i32* %addr.1
82}
83
84; TODO: Generate ldrd
85; CHECK-LABEL: pre_inc_ldrd
86; CHECK: ldr{{.*}}, #4]!
87define i32* @pre_inc_ldrd(i32* %base) {
88 %addr = getelementptr i32, i32* %base, i32 1
89 %addr.1 = getelementptr i32, i32* %base, i32 2
90 %addr.2 = getelementptr i32, i32* %base, i32 3
91 %ld = load i32, i32* %addr
92 %ld.1 = load i32, i32* %addr.1
93 %res = add i32 %ld, %ld.1
94 store i32 %res, i32* %addr.2
95 ret i32* %addr
96}
97
98; TODO: Generate ldrd
99; CHECK-LABEL: pre_dec_ldrd
100; CHECK: ldr{{.*}}, #-4]!
101define i32* @pre_dec_ldrd(i32* %base) {
102 %addr = getelementptr i32, i32* %base, i32 -1
103 %addr.1 = getelementptr i32, i32* %base, i32 -2
104 %addr.2 = getelementptr i32, i32* %base, i32 -3
105 %ld = load i32, i32* %addr
106 %ld.1 = load i32, i32* %addr.1
107 %res = add i32 %ld, %ld.1
108 store i32 %res, i32* %addr.2
109 ret i32* %addr
110}
111
112; TODO: Generate post inc
113; CHECK-LABEL: post_inc_ldrd
114; CHECK-V8M: ldrd{{.*}}, [r0]
115; CHECK-V8: ldm
116; CHECK: add{{.*}}, #8
117define i32* @post_inc_ldrd(i32* %base, i32* %addr.3) {
118 %addr = getelementptr i32, i32* %base, i32 0
119 %ld = load i32, i32* %addr
120 %addr.1 = getelementptr i32, i32* %base, i32 1
121 %ld.1 = load i32, i32* %addr.1
122 %addr.2 = getelementptr i32, i32* %base, i32 2
123 %res = add i32 %ld, %ld.1
124 store i32 %res, i32* %addr.3
125 ret i32* %addr.2
126}
127
128; CHECK-LABEL: pre_inc_str_multi
129; CHECK: str{{.*}}, #8]!
130define i32* @pre_inc_str_multi(i32* %base) {
131 %addr = getelementptr i32, i32* %base, i32 0
132 %addr.1 = getelementptr i32, i32* %base, i32 1
133 %ld = load i32, i32* %addr
134 %ld.1 = load i32, i32* %addr.1
135 %res = add i32 %ld, %ld.1
136 %addr.2 = getelementptr i32, i32* %base, i32 2
137 store i32 %res, i32* %addr.2
138 ret i32* %addr.2
139}
140
141; CHECK-LABEL: pre_dec_str_multi
142; CHECK: str{{.*}}, #-4]!
143define i32* @pre_dec_str_multi(i32* %base) {
144 %addr = getelementptr i32, i32* %base, i32 0
145 %addr.1 = getelementptr i32, i32* %base, i32 1
146 %ld = load i32, i32* %addr
147 %ld.1 = load i32, i32* %addr.1
148 %res = add i32 %ld, %ld.1
149 %addr.2 = getelementptr i32, i32* %base, i32 -1
150 store i32 %res, i32* %addr.2
151 ret i32* %addr.2
152}
153
154; CHECK-LABEL: illegal_pre_inc_store_1
155; CHECK-NOT: str{{.*}} ]!
156define i32* @illegal_pre_inc_store_1(i32* %base) {
157entry:
158 %ptr.to.use = getelementptr i32, i32* %base, i32 2
159 %ptr.to.store = ptrtoint i32* %base to i32
160 store i32 %ptr.to.store, i32* %ptr.to.use, align 4
161 ret i32* %ptr.to.use
162}
163
164; TODO: The mov should be unecessary
165; CHECK-LABEL: legal_pre_inc_store_needs_copy_1
166; CHECK: add{{.*}}, #8
167; CHECK-NOT: str{{.*}}]!
168; CHECK: mov
169define i32* @legal_pre_inc_store_needs_copy_1(i32* %base) {
170entry:
171 %ptr.to.use = getelementptr i32, i32* %base, i32 2
172 %ptr.to.store = ptrtoint i32* %ptr.to.use to i32
173 store i32 %ptr.to.store, i32* %ptr.to.use, align 4
174 ret i32* %ptr.to.use
175}
176
177; CHECK-LABEL: legal_pre_inc_store_needs_copy_2
178; CHECK-NOT: mov
179; CHECK-NOT: str{{.*}}]!
180define i32* @legal_pre_inc_store_needs_copy_2(i32 %base) {
181entry:
182 %ptr = inttoptr i32 %base to i32*
183 %ptr.to.use = getelementptr i32, i32* %ptr, i32 2
184 store i32 %base, i32* %ptr.to.use, align 4
185 ret i32* %ptr.to.use
186}