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