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. 62 name: defaultMapping 63 isSSA: true 64 # CHECK: registers: 65 # CHECK-NEXT: - { id: 0, class: gpr } 66 registers: 67 - { id: 0, class: _ } 68 body: | 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. 79 name: defaultMappingVector 80 isSSA: true 81 # CHECK: registers: 82 # CHECK-NEXT: - { id: 0, class: fpr } 83 registers: 84 - { id: 0, class: _ } 85 body: | 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. 96 name: defaultMapping1Repair 97 isSSA: 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 } 102 registers: 103 - { id: 0, class: _ } 104 - { id: 1, class: _ } 105 body: | 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. 116 name: defaultMapping2Repairs 117 isSSA: 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 } 123 registers: 124 - { id: 0, class: _ } 125 - { id: 1, class: _ } 126 body: | 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. 142 name: defaultMappingDefRepair 143 isSSA: 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 } 148 registers: 149 - { id: 0, class: _ } 150 - { id: 1, class: fpr } 151 body: | 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. 163 name: phiPropagation 164 isSSA: true 165 tracksRegLiveness: 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 } 172 registers: 173 - { id: 0, class: gpr32 } 174 - { id: 1, class: gpr64sp } 175 - { id: 2, class: gpr32 } 176 - { id: 3, class: _ } 177 - { id: 4, class: _ } 178 body: | 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. 200 name: defaultMappingUseRepairPhysReg 201 isSSA: 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 } 206 registers: 207 - { id: 0, class: _ } 208 - { id: 1, class: _ } 209 body: | 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. 221 name: defaultMappingDefRepairPhysReg 222 isSSA: true 223 # CHECK: registers: 224 # CHECK-NEXT: - { id: 0, class: gpr } 225 # CHECK-NEXT: - { id: 1, class: gpr } 226 registers: 227 - { id: 0, class: _ } 228 body: | 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. 241 name: greedyMappingOr 242 isSSA: 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 257 registers: 258 - { id: 0, class: _ } 259 - { id: 1, class: _ } 260 - { id: 2, class: _ } 261 body: | 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. 287 name: greedyMappingOrWithConstraints 288 isSSA: 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 303 registers: 304 - { id: 0, class: _ } 305 - { id: 1, class: _ } 306 - { id: 2, class: fpr } 307 body: | 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