• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# RUN: llc -O0 -run-pass=regbankselect -global-isel %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=FAST
2# RUN: llc -O0 -run-pass=regbankselect -global-isel %s -regbankselect-greedy -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=GREEDY
3# REQUIRES: global-isel
4
5--- |
6  ; ModuleID = 'generic-virtual-registers-type-error.mir'
7  target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
8  target triple = "aarch64-apple-ios"
9  define void @defaultMapping() {
10  entry:
11    ret void
12  }
13  define void @defaultMappingVector() {
14  entry:
15    ret void
16  }
17  define void @defaultMapping1Repair() {
18  entry:
19    ret void
20  }
21  define void @defaultMapping2Repairs() {
22  entry:
23    ret void
24  }
25  define void @defaultMappingDefRepair() {
26  entry:
27    ret void
28  }
29  define void @phiPropagation(i32* %src, i32* %dst, i1 %cond) {
30  entry:
31    %srcVal = load i32, i32* %src
32    br i1 %cond, label %end, label %then
33  then:
34    %res = add i32 %srcVal, 36
35    br label %end
36  end:
37    %toStore = phi i32 [ %srcVal, %entry ], [ %res, %then ]
38    store i32 %toStore, i32* %dst
39    ret void
40  }
41  define void @defaultMappingUseRepairPhysReg() {
42  entry:
43    ret void
44  }
45  define void @defaultMappingDefRepairPhysReg() {
46  entry:
47    ret void
48  }
49  define void @greedyMappingOr() {
50  entry:
51    ret void
52  }
53  define void @greedyMappingOrWithConstraints() {
54  entry:
55    ret void
56  }
57...
58
59---
60# Check that we assign a relevant register bank for %0.
61# Based on the type i32, this should be gpr.
62name:            defaultMapping
63isSSA:           true
64# CHECK:      registers:
65# CHECK-NEXT:   - { id: 0, class: gpr }
66registers:
67  - { id: 0, class: _ }
68body: |
69  bb.0.entry:
70    liveins: %x0
71    ; CHECK:      %0(32) = G_ADD i32 %x0
72    %0(32) = G_ADD i32 %x0, %x0
73...
74
75---
76# Check that we assign a relevant register bank for %0.
77# Based on the type <2 x i32>, this should be fpr.
78# FPR is used for both floating point and vector registers.
79name:            defaultMappingVector
80isSSA:           true
81# CHECK:      registers:
82# CHECK-NEXT:   - { id: 0, class: fpr }
83registers:
84  - { id: 0, class: _ }
85body: |
86  bb.0.entry:
87    liveins: %d0
88    ; CHECK:      %0(32) = G_ADD <2 x i32> %d0
89    %0(32) = G_ADD <2 x i32> %d0, %d0
90...
91
92---
93# Check that we repair the assignment for %0.
94# Indeed based on the source of the copy it should live
95# in FPR, but at the use, it should be GPR.
96name:            defaultMapping1Repair
97isSSA:           true
98# CHECK:      registers:
99# CHECK-NEXT:   - { id: 0, class: fpr }
100# CHECK-NEXT:   - { id: 1, class: gpr }
101# CHECK-NEXT:   - { id: 2, class: gpr }
102registers:
103  - { id: 0, class: _ }
104  - { id: 1, class: _ }
105body: |
106  bb.0.entry:
107    liveins: %s0, %x0
108    ; CHECK:           %0(32) = COPY %s0
109    ; CHECK-NEXT:      %2(32) = COPY %0
110    ; CHECK-NEXT:      %1(32) = G_ADD i32 %2, %x0
111    %0(32) = COPY %s0
112    %1(32) = G_ADD i32 %0, %x0
113...
114
115# Check that we repair the assignment for %0 differently for both uses.
116name:            defaultMapping2Repairs
117isSSA:           true
118# CHECK:      registers:
119# CHECK-NEXT:   - { id: 0, class: fpr }
120# CHECK-NEXT:   - { id: 1, class: gpr }
121# CHECK-NEXT:   - { id: 2, class: gpr }
122# CHECK-NEXT:   - { id: 3, class: gpr }
123registers:
124  - { id: 0, class: _ }
125  - { id: 1, class: _ }
126body: |
127  bb.0.entry:
128    liveins: %s0, %x0
129    ; CHECK:           %0(32) = COPY %s0
130    ; CHECK-NEXT:      %2(32) = COPY %0
131    ; CHECK-NEXT:      %3(32) = COPY %0
132    ; CHECK-NEXT:      %1(32) = G_ADD i32 %2, %3
133    %0(32) = COPY %s0
134    %1(32) = G_ADD i32 %0, %0
135...
136
137---
138# Check that we repair the definition of %1.
139# %1 is forced to be into FPR, but its definition actually
140# requires that it lives in GPR. Make sure regbankselect
141# fixes that.
142name:            defaultMappingDefRepair
143isSSA:           true
144# CHECK:      registers:
145# CHECK-NEXT:   - { id: 0, class: gpr }
146# CHECK-NEXT:   - { id: 1, class: fpr }
147# CHECK-NEXT:   - { id: 2, class: gpr }
148registers:
149  - { id: 0, class: _ }
150  - { id: 1, class: fpr }
151body: |
152  bb.0.entry:
153    liveins: %w0
154    ; CHECK:           %0(32) = COPY %w0
155    ; CHECK-NEXT:      %2(32) = G_ADD i32 %0, %w0
156    ; CHECK-NEXT:      %1(32) = COPY %2
157    %0(32) = COPY %w0
158    %1(32) = G_ADD i32 %0, %w0
159...
160
161---
162# Check that we are able to propagate register banks from phis.
163name:            phiPropagation
164isSSA:           true
165tracksRegLiveness:   true
166# CHECK:      registers:
167# CHECK-NEXT:   - { id: 0, class: gpr32 }
168# CHECK-NEXT:   - { id: 1, class: gpr64sp }
169# CHECK-NEXT:   - { id: 2, class: gpr32 }
170# CHECK-NEXT:   - { id: 3, class: gpr }
171# CHECK-NEXT:   - { id: 4, class: gpr }
172registers:
173  - { id: 0, class: gpr32 }
174  - { id: 1, class: gpr64sp }
175  - { id: 2, class: gpr32 }
176  - { id: 3, class: _ }
177  - { id: 4, class: _ }
178body: |
179  bb.0.entry:
180    successors: %bb.2.end, %bb.1.then
181    liveins: %x0, %x1, %w2
182
183    %0 = LDRWui killed %x0, 0 :: (load 4 from %ir.src)
184    %1 = COPY %x1
185    %2 = COPY %w2
186    TBNZW killed %2, 0, %bb.2.end
187
188  bb.1.then:
189    successors: %bb.2.end
190    %3(32) = G_ADD i32 %0, %0
191
192  bb.2.end:
193    %4(32) = PHI %0, %bb.0.entry, %3, %bb.1.then
194    STRWui killed %4, killed %1, 0 :: (store 4 into %ir.dst)
195    RET_ReallyLR
196...
197
198---
199# Make sure we can repair physical register uses as well.
200name:            defaultMappingUseRepairPhysReg
201isSSA:           true
202# CHECK:      registers:
203# CHECK-NEXT:   - { id: 0, class: gpr }
204# CHECK-NEXT:   - { id: 1, class: gpr }
205# CHECK-NEXT:   - { id: 2, class: gpr }
206registers:
207  - { id: 0, class: _ }
208  - { id: 1, class: _ }
209body: |
210  bb.0.entry:
211    liveins: %w0, %s0
212    ; CHECK:           %0(32) = COPY %w0
213    ; CHECK-NEXT:      %2(32) = COPY %s0
214    ; CHECK-NEXT:      %1(32) = G_ADD i32 %0, %2
215    %0(32) = COPY %w0
216    %1(32) = G_ADD i32 %0, %s0
217...
218
219---
220# Make sure we can repair physical register defs.
221name:            defaultMappingDefRepairPhysReg
222isSSA:           true
223# CHECK:      registers:
224# CHECK-NEXT:   - { id: 0, class: gpr }
225# CHECK-NEXT:   - { id: 1, class: gpr }
226registers:
227  - { id: 0, class: _ }
228body: |
229  bb.0.entry:
230    liveins: %w0
231    ; CHECK:           %0(32) = COPY %w0
232    ; CHECK-NEXT:      %1(32) = G_ADD i32 %0, %0
233    ; CHECK-NEXT:      %s0 = COPY %1
234    %0(32) = COPY %w0
235    %s0 = G_ADD i32 %0, %0
236...
237
238---
239# Check that the greedy mode is able to switch the
240# G_OR instruction from fpr to gpr.
241name:            greedyMappingOr
242isSSA:           true
243# CHECK:      registers:
244# CHECK-NEXT:  - { id: 0, class: gpr }
245# CHECK-NEXT:  - { id: 1, class: gpr }
246
247# Fast mode maps vector instruction on FPR.
248# FAST-NEXT:  - { id: 2, class: fpr }
249# Fast mode needs two extra copies.
250# FAST-NEXT:  - { id: 3, class: fpr }
251# FAST-NEXT:  - { id: 4, class: fpr }
252
253# Greedy mode coalesce the computation on the GPR register
254# because it is the cheapest.
255# GREEDY-NEXT:  - { id: 2, class: gpr }
256
257registers:
258  - { id: 0, class: _ }
259  - { id: 1, class: _ }
260  - { id: 2, class: _ }
261body: |
262  bb.0.entry:
263    liveins: %x0, %x1
264    ; CHECK: %0(64) = COPY %x0
265    ; CHECK-NEXT: %1(64) = COPY %x1
266
267
268    ; Fast mode tries to reuse the source of the copy for the destination.
269    ; Now, the default mapping says that %0 and %1 need to be in FPR.
270    ; The repairing code insert two copies to materialize that.
271    ; FAST-NEXT: %3(64) = COPY %0
272    ; FAST-NEXT: %4(64) = COPY %1
273    ; The mapping of G_OR is on FPR.
274    ; FAST-NEXT: %2(64) = G_OR <2 x i32> %3, %4
275
276    ; Greedy mode remapped the instruction on the GPR bank.
277    ; GREEDY-NEXT: %2(64) = G_OR <2 x i32> %0, %1
278    %0(64) = COPY %x0
279    %1(64) = COPY %x1
280    %2(64) = G_OR <2 x i32> %0, %1
281...
282
283---
284# Check that the greedy mode is able to switch the
285# G_OR instruction from fpr to gpr, while still honoring
286# %2 constraint.
287name:            greedyMappingOrWithConstraints
288isSSA:           true
289# CHECK:      registers:
290# CHECK-NEXT:  - { id: 0, class: gpr }
291# CHECK-NEXT:  - { id: 1, class: gpr }
292# CHECK-NEXT:  - { id: 2, class: fpr }
293
294# Fast mode maps vector instruction on FPR.
295# Fast mode needs two extra copies.
296# FAST-NEXT:  - { id: 3, class: fpr }
297# FAST-NEXT:  - { id: 4, class: fpr }
298
299# Greedy mode coalesce the computation on the GPR register because it
300# is the cheapest, but will need one extra copy to materialize %2 into a FPR.
301# GREEDY-NEXT:  - { id: 3, class: gpr }
302
303registers:
304  - { id: 0, class: _ }
305  - { id: 1, class: _ }
306  - { id: 2, class: fpr }
307body: |
308  bb.0.entry:
309    liveins: %x0, %x1
310    ; CHECK: %0(64) = COPY %x0
311    ; CHECK-NEXT: %1(64) = COPY %x1
312
313
314    ; Fast mode tries to reuse the source of the copy for the destination.
315    ; Now, the default mapping says that %0 and %1 need to be in FPR.
316    ; The repairing code insert two copies to materialize that.
317    ; FAST-NEXT: %3(64) = COPY %0
318    ; FAST-NEXT: %4(64) = COPY %1
319    ; The mapping of G_OR is on FPR.
320    ; FAST-NEXT: %2(64) = G_OR <2 x i32> %3, %4
321
322    ; Greedy mode remapped the instruction on the GPR bank.
323    ; GREEDY-NEXT: %3(64) = G_OR <2 x i32> %0, %1
324    ; We need to keep %2 into FPR because we do not know anything about it.
325    ; GREEDY-NEXT: %2(64) = COPY %3
326    %0(64) = COPY %x0
327    %1(64) = COPY %x1
328    %2(64) = G_OR <2 x i32> %0, %1
329...
330