1# RUN: llc -mtriple arm-- -run-pass=legalizer %s -o - | FileCheck %s
2# RUN: llc -mtriple thumbv7-- -run-pass=legalizer %s -o - | FileCheck %s
3--- |
4  define void @test_legal_loads_stores() { ret void }
5  define void @test_load_from_stack() { ret void }
6
7  define void @test_load_store_64_vfp() #0 { ret void }
8  define void @test_load_store_64_novfp() #1 { ret void }
9
10  define void @test_gep_s32() { ret void }
11  define void @test_gep_s16() { ret void }
12
13  attributes #0 = { "target-features"="+vfp2" }
14  attributes #1 = { "target-features"="-vfp2d16sp" }
15...
16---
17name:            test_legal_loads_stores
18# CHECK-LABEL: name: test_legal_loads_stores
19legalized:       false
20# CHECK: legalized: true
21regBankSelected: false
22selected:        false
23tracksRegLiveness: true
24registers:
25  - { id: 0, class: _ }
26  - { id: 1, class: _ }
27  - { id: 2, class: _ }
28  - { id: 3, class: _ }
29  - { id: 4, class: _ }
30  - { id: 5, class: _ }
31  - { id: 6, class: _ }
32body:             |
33  bb.0:
34    liveins: $r0
35
36    ; These are all legal, so we should find them unchanged in the output
37    ; CHECK-DAG: G_STORE {{%[0-9]+}}(s32), %0(p0)
38    ; CHECK-DAG: G_STORE {{%[0-9]+}}(s16), %0(p0)
39    ; CHECK-DAG: G_STORE {{%[0-9]+}}(s8), %0(p0)
40    ; CHECK-DAG: G_STORE {{%[0-9]+}}(s1), %0(p0)
41    ; CHECK-DAG: G_STORE {{%[0-9]+}}(p0), %0(p0)
42    ; CHECK-DAG: {{%[0-9]+}}:_(s32) = G_LOAD %0(p0)
43    ; CHECK-DAG: {{%[0-9]+}}:_(s16) = G_LOAD %0(p0)
44    ; CHECK-DAG: {{%[0-9]+}}:_(s8) = G_LOAD %0(p0)
45    ; CHECK-DAG: {{%[0-9]+}}:_(s1) = G_LOAD %0(p0)
46    ; CHECK-DAG: {{%[0-9]+}}:_(p0) = G_LOAD %0(p0)
47    %0(p0) = COPY $r0
48    %2(s32) = G_LOAD %0(p0) :: (load 4)
49    G_STORE %2(s32), %0(p0) :: (store 4)
50    %3(s16) = G_LOAD %0(p0) :: (load 2)
51    G_STORE %3(s16), %0(p0) :: (store 2)
52    %4(s8) = G_LOAD %0(p0) :: (load 1)
53    G_STORE %4(s8), %0(p0) :: (store 1)
54    %5(s1) = G_LOAD %0(p0) :: (load 1)
55    G_STORE %5(s1), %0(p0) :: (store 1)
56    %6(p0) = G_LOAD %0(p0) :: (load 4)
57    G_STORE %6(p0), %0(p0) :: (store 4)
58    BX_RET 14, $noreg
59...
60---
61name:            test_load_from_stack
62# CHECK-LABEL: name: test_load_from_stack
63legalized:       false
64# CHECK: legalized: true
65regBankSelected: false
66selected:        false
67tracksRegLiveness: true
68registers:
69  - { id: 0, class: _ }
70  - { id: 1, class: _ }
71  - { id: 2, class: _ }
72  - { id: 3, class: _ }
73fixedStack:
74  - { id: 0, offset: 0, size: 4, alignment: 4, isImmutable: true, isAliased: false }
75  - { id: 1, offset: 4, size: 4, alignment: 4, isImmutable: true, isAliased: false }
76  - { id: 2, offset: 8, size: 4, alignment: 4, isImmutable: true, isAliased: false }
77  # CHECK: id: [[FRAME_INDEX:[0-9]+]], type: default, offset: 8
78body:             |
79  bb.0:
80    liveins: $r0, $r1, $r2, $r3
81
82    ; This is legal, so we should find it unchanged in the output
83    ; CHECK: [[FIVREG:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[FRAME_INDEX]]
84    ; CHECK: {{%[0-9]+}}:_(s32) = G_LOAD [[FIVREG]](p0) :: (load 4)
85    %0(p0) = G_FRAME_INDEX %fixed-stack.2
86    %1(s32) = G_LOAD %0(p0) :: (load 4)
87    $r0 = COPY %1(s32)
88    BX_RET 14, $noreg, implicit $r0
89...
90---
91name:            test_load_store_64_vfp
92# CHECK-LABEL: name: test_load_store_64_vfp
93legalized:       false
94# CHECK: legalized: true
95regBankSelected: false
96selected:        false
97tracksRegLiveness: true
98registers:
99  - { id: 0, class: _ }
100  - { id: 1, class: _ }
101  - { id: 2, class: _ }
102body:             |
103  bb.0:
104    liveins: $r0
105
106    ; Can't use the VFP support for unaligned operations, we need to use 32-bits
107    ; operations instead.
108    ; CHECK: [[ADDR1:%[0-9]+]]:_(p0) = COPY $r0
109    ; CHECK-NEXT: [[V1:%[0-9]+]]:_(s32) = G_LOAD [[ADDR1]](p0) :: (load 4, align 1)
110    ; CHECK-NEXT: [[OFF:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
111    ; CHECK-NEXT: [[ADDR2:%[0-9]+]]:_(p0) = G_GEP [[ADDR1]], [[OFF]]
112    ; CHECK-NEXT: [[V2:%[0-9]+]]:_(s32) = G_LOAD [[ADDR2]](p0) :: (load 4, align 1)
113    ; CHECK-NEXT: G_STORE [[V1]](s32), [[ADDR1]](p0) :: (store 4, align 1)
114    ; CHECK-NEXT: [[ADDR2:%[0-9]+]]:_(p0) = G_GEP [[ADDR1]], [[OFF]]
115    ; CHECK-NEXT: G_STORE [[V2]](s32), [[ADDR2]](p0) :: (store 4, align 1)
116    %0(p0) = COPY $r0
117    %1(s64) = G_LOAD %0(p0) :: (load 8, align 1)
118    G_STORE %1(s64), %0(p0) :: (store 8, align 1)
119
120    ; For word-aligned we can use VFP operations.
121    ; CHECK: [[V:%[0-9]+]]:_(s64) = G_LOAD %0(p0) :: (load 8, align 4)
122    ; CHECK: G_STORE [[V]](s64), %0(p0) :: (store 8, align 4)
123    %2(s64) = G_LOAD %0(p0) :: (load 8, align 4)
124    G_STORE %2(s64), %0(p0) :: (store 8, align 4)
125
126    BX_RET 14, $noreg
127...
128---
129name:            test_load_store_64_novfp
130# CHECK-LABEL: name: test_load_store_64_novfp
131legalized:       false
132# CHECK: legalized: true
133regBankSelected: false
134selected:        false
135tracksRegLiveness: true
136registers:
137  - { id: 0, class: _ }
138  - { id: 1, class: _ }
139  - { id: 2, class: _ }
140body:             |
141  bb.0:
142    liveins: $r0
143
144    ; When we don't have VFP support, we need to use 32-bit operations.
145    ; CHECK: [[ADDR1:%[0-9]+]]:_(p0) = COPY $r0
146    ; CHECK-NEXT: [[V1:%[0-9]+]]:_(s32) = G_LOAD [[ADDR1]](p0) :: (load 4, align 1)
147    ; CHECK-NEXT: [[OFF:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
148    ; CHECK-NEXT: [[ADDR2:%[0-9]+]]:_(p0) = G_GEP [[ADDR1]], [[OFF]]
149    ; CHECK-NEXT: [[V2:%[0-9]+]]:_(s32) = G_LOAD [[ADDR2]](p0) :: (load 4, align 1)
150    ; CHECK-NEXT: G_STORE [[V1]](s32), [[ADDR1]](p0) :: (store 4, align 1)
151    ; CHECK-NEXT: [[ADDR2:%[0-9]+]]:_(p0) = G_GEP [[ADDR1]], [[OFF]]
152    ; CHECK-NEXT: G_STORE [[V2]](s32), [[ADDR2]](p0) :: (store 4, align 1)
153    %0(p0) = COPY $r0
154    %1(s64) = G_LOAD %0(p0) :: (load 8, align 1)
155    G_STORE %1(s64), %0(p0) :: (store 8, align 1)
156
157    ; CHECK: [[V1:%[0-9]+]]:_(s32) = G_LOAD [[ADDR1]](p0) :: (load 4)
158    ; CHECK-NEXT: [[ADDR2:%[0-9]+]]:_(p0) = G_GEP [[ADDR1]], [[OFF]]
159    ; CHECK-NEXT: [[V2:%[0-9]+]]:_(s32) = G_LOAD [[ADDR2]](p0) :: (load 4)
160    ; CHECK-NEXT: G_STORE [[V1]](s32), [[ADDR1]](p0) :: (store 4)
161    ; CHECK-NEXT: [[ADDR2:%[0-9]+]]:_(p0) = G_GEP [[ADDR1]], [[OFF]]
162    ; CHECK-NEXT: G_STORE [[V2]](s32), [[ADDR2]](p0) :: (store 4)
163    %2(s64) = G_LOAD %0(p0) :: (load 8, align 4)
164    G_STORE %2(s64), %0(p0) :: (store 8, align 4)
165
166    BX_RET 14, $noreg
167...
168---
169name:            test_gep_s32
170# CHECK-LABEL: name: test_gep_s32
171legalized:       false
172# CHECK: legalized: true
173regBankSelected: false
174selected:        false
175tracksRegLiveness: true
176registers:
177  - { id: 0, class: _ }
178  - { id: 1, class: _ }
179  - { id: 2, class: _ }
180body:             |
181  bb.0:
182    liveins: $r0, $r1
183
184    %0(p0) = COPY $r0
185    %1(s32) = COPY $r1
186
187    ; CHECK: {{%[0-9]+}}:_(p0) = G_GEP {{%[0-9]+}}, {{%[0-9]+}}(s32)
188    %2(p0) = G_GEP %0, %1(s32)
189
190    $r0 = COPY %2(p0)
191    BX_RET 14, $noreg, implicit $r0
192...
193---
194name:            test_gep_s16
195# CHECK-LABEL: name: test_gep_s16
196legalized:       false
197# CHECK: legalized: true
198regBankSelected: false
199selected:        false
200tracksRegLiveness: true
201registers:
202  - { id: 0, class: _ }
203  - { id: 1, class: _ }
204  - { id: 2, class: _ }
205body:             |
206  bb.0:
207    liveins: $r0
208
209    %0(p0) = COPY $r0
210    %1(s16) = G_LOAD %0(p0) :: (load 2)
211
212    ; CHECK-NOT: G_GEP {{%[0-9]+}}, {{%[0-9]+}}(s16)
213    ; CHECK: {{%[0-9]+}}:_(p0) = G_GEP {{%[0-9]+}}, {{%[0-9]+}}(s32)
214    ; CHECK-NOT: G_GEP {{%[0-9]+}}, {{%[0-9]+}}(s16)
215    %2(p0) = G_GEP %0, %1(s16)
216
217    $r0 = COPY %2(p0)
218    BX_RET 14, $noreg, implicit $r0
219...
220