1# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py 2# RUN: llc -mtriple=aarch64-unknown-unknown -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s 3... 4--- 5name: shl_gep_sext_ldrwrow 6alignment: 4 7legalized: true 8regBankSelected: true 9tracksRegLiveness: true 10frameInfo: 11 maxAlignment: 1 12machineFunctionInfo: {} 13body: | 14 bb.0: 15 liveins: $w1, $x0 16 17 ; We should be able to fold a shift + extend into the pattern. 18 ; In this case, we should get a roW load with two 1s, representing a shift 19 ; plus sign extend. 20 21 ; CHECK-LABEL: name: shl_gep_sext_ldrwrow 22 ; CHECK: liveins: $w1, $x0 23 ; CHECK: %base:gpr64sp = COPY $x0 24 ; CHECK: %foo:gpr32 = COPY $w1 25 ; CHECK: %load:gpr32 = LDRWroW %base, %foo, 1, 1 :: (load 4) 26 ; CHECK: $w0 = COPY %load 27 ; CHECK: RET_ReallyLR implicit $w0 28 %base:gpr(p0) = COPY $x0 29 %foo:gpr(s32) = COPY $w1 30 %ext:gpr(s64) = G_SEXT %foo(s32) 31 %c:gpr(s64) = G_CONSTANT i64 2 32 %offset:gpr(s64) = G_SHL %ext, %c 33 %ptr:gpr(p0) = G_PTR_ADD %base, %offset(s64) 34 %load:gpr(s32) = G_LOAD %ptr(p0) :: (load 4) 35 $w0 = COPY %load(s32) 36 RET_ReallyLR implicit $w0 37... 38--- 39name: shl_gep_zext_ldrwrow 40alignment: 4 41legalized: true 42regBankSelected: true 43tracksRegLiveness: true 44frameInfo: 45 maxAlignment: 1 46machineFunctionInfo: {} 47body: | 48 bb.0: 49 liveins: $w1, $x0 50 51 ; We should be able to fold a shift + extend into the pattern. 52 ; In this case, we should get a roW load with a 0 representing a zero-extend 53 ; and a 1 representing a shift. 54 55 ; CHECK-LABEL: name: shl_gep_zext_ldrwrow 56 ; CHECK: liveins: $w1, $x0 57 ; CHECK: %base:gpr64sp = COPY $x0 58 ; CHECK: %foo:gpr32 = COPY $w1 59 ; CHECK: %load:gpr32 = LDRWroW %base, %foo, 0, 1 :: (load 4) 60 ; CHECK: $w0 = COPY %load 61 ; CHECK: RET_ReallyLR implicit $w0 62 %base:gpr(p0) = COPY $x0 63 %foo:gpr(s32) = COPY $w1 64 %ext:gpr(s64) = G_ZEXT %foo(s32) 65 %c:gpr(s64) = G_CONSTANT i64 2 66 %offset:gpr(s64) = G_SHL %ext, %c 67 %ptr:gpr(p0) = G_PTR_ADD %base, %offset(s64) 68 %load:gpr(s32) = G_LOAD %ptr(p0) :: (load 4) 69 $w0 = COPY %load(s32) 70 RET_ReallyLR implicit $w0 71... 72--- 73name: shl_gep_anyext_ldrwrow 74alignment: 4 75legalized: true 76regBankSelected: true 77tracksRegLiveness: true 78frameInfo: 79 maxAlignment: 1 80machineFunctionInfo: {} 81body: | 82 bb.0: 83 liveins: $w1, $x0 84 85 ; We should be able to fold a shift + extend into the pattern. 86 ; In this case, we should get a roW load with a 0 representing a zero-extend 87 ; and a 1 representing a shift. 88 89 ; CHECK-LABEL: name: shl_gep_anyext_ldrwrow 90 ; CHECK: liveins: $w1, $x0 91 ; CHECK: %base:gpr64sp = COPY $x0 92 ; CHECK: %foo:gpr32 = COPY $w1 93 ; CHECK: %load:gpr32 = LDRWroW %base, %foo, 0, 1 :: (load 4) 94 ; CHECK: $w0 = COPY %load 95 ; CHECK: RET_ReallyLR implicit $w0 96 %base:gpr(p0) = COPY $x0 97 %foo:gpr(s32) = COPY $w1 98 %ext:gpr(s64) = G_ANYEXT %foo(s32) 99 %c:gpr(s64) = G_CONSTANT i64 2 100 %offset:gpr(s64) = G_SHL %ext, %c 101 %ptr:gpr(p0) = G_PTR_ADD %base, %offset(s64) 102 %load:gpr(s32) = G_LOAD %ptr(p0) :: (load 4) 103 $w0 = COPY %load(s32) 104 RET_ReallyLR implicit $w0 105... 106--- 107name: mul_gep_sext_ldrwrow 108alignment: 4 109legalized: true 110regBankSelected: true 111tracksRegLiveness: true 112frameInfo: 113 maxAlignment: 1 114machineFunctionInfo: {} 115body: | 116 bb.0: 117 118 ; We should be able to do the same with multiplies as with shifts. 119 120 liveins: $w1, $x0 121 ; CHECK-LABEL: name: mul_gep_sext_ldrwrow 122 ; CHECK: liveins: $w1, $x0 123 ; CHECK: %base:gpr64sp = COPY $x0 124 ; CHECK: %foo:gpr32 = COPY $w1 125 ; CHECK: %load:gpr32 = LDRWroW %base, %foo, 1, 1 :: (load 4) 126 ; CHECK: $w0 = COPY %load 127 ; CHECK: RET_ReallyLR implicit $w0 128 %base:gpr(p0) = COPY $x0 129 %foo:gpr(s32) = COPY $w1 130 %ext:gpr(s64) = G_SEXT %foo(s32) 131 %c:gpr(s64) = G_CONSTANT i64 4 132 %offset:gpr(s64) = G_MUL %c, %ext 133 %ptr:gpr(p0) = G_PTR_ADD %base, %offset(s64) 134 %load:gpr(s32) = G_LOAD %ptr(p0) :: (load 4) 135 $w0 = COPY %load(s32) 136 RET_ReallyLR implicit $w0 137... 138--- 139name: mul_gep_zext_ldrwrow 140alignment: 4 141legalized: true 142regBankSelected: true 143tracksRegLiveness: true 144frameInfo: 145 maxAlignment: 1 146machineFunctionInfo: {} 147body: | 148 bb.0: 149 liveins: $w1, $x0 150 151 ; We should be able to do the same with multiplies as with shifts. 152 153 ; CHECK-LABEL: name: mul_gep_zext_ldrwrow 154 ; CHECK: liveins: $w1, $x0 155 ; CHECK: %base:gpr64sp = COPY $x0 156 ; CHECK: %foo:gpr32 = COPY $w1 157 ; CHECK: %load:gpr32 = LDRWroW %base, %foo, 0, 1 :: (load 4) 158 ; CHECK: $w0 = COPY %load 159 ; CHECK: RET_ReallyLR implicit $w0 160 %base:gpr(p0) = COPY $x0 161 %foo:gpr(s32) = COPY $w1 162 %ext:gpr(s64) = G_ZEXT %foo(s32) 163 %c:gpr(s64) = G_CONSTANT i64 4 164 %offset:gpr(s64) = G_MUL %c, %ext 165 %ptr:gpr(p0) = G_PTR_ADD %base, %offset(s64) 166 %load:gpr(s32) = G_LOAD %ptr(p0) :: (load 4) 167 $w0 = COPY %load(s32) 168 RET_ReallyLR implicit $w0 169... 170--- 171name: mul_gep_anyext_ldrwrow 172alignment: 4 173legalized: true 174regBankSelected: true 175tracksRegLiveness: true 176frameInfo: 177 maxAlignment: 1 178machineFunctionInfo: {} 179body: | 180 bb.0: 181 liveins: $w1, $x0 182 183 ; We should be able to do the same with multiplies as with shifts. 184 185 ; CHECK-LABEL: name: mul_gep_anyext_ldrwrow 186 ; CHECK: liveins: $w1, $x0 187 ; CHECK: %base:gpr64sp = COPY $x0 188 ; CHECK: %foo:gpr32 = COPY $w1 189 ; CHECK: %load:gpr32 = LDRWroW %base, %foo, 0, 1 :: (load 4) 190 ; CHECK: $w0 = COPY %load 191 ; CHECK: RET_ReallyLR implicit $w0 192 %base:gpr(p0) = COPY $x0 193 %foo:gpr(s32) = COPY $w1 194 %ext:gpr(s64) = G_ANYEXT %foo(s32) 195 %c:gpr(s64) = G_CONSTANT i64 4 196 %offset:gpr(s64) = G_MUL %c, %ext 197 %ptr:gpr(p0) = G_PTR_ADD %base, %offset(s64) 198 %load:gpr(s32) = G_LOAD %ptr(p0) :: (load 4) 199 $w0 = COPY %load(s32) 200 RET_ReallyLR implicit $w0 201... 202--- 203name: ldrdrow 204alignment: 4 205legalized: true 206regBankSelected: true 207tracksRegLiveness: true 208frameInfo: 209 maxAlignment: 1 210machineFunctionInfo: {} 211body: | 212 bb.0: 213 liveins: $w1, $x0, $d0 214 215 ; Verify that we can select LDRDroW. 216 217 ; CHECK-LABEL: name: ldrdrow 218 ; CHECK: liveins: $w1, $x0, $d0 219 ; CHECK: %base:gpr64sp = COPY $x0 220 ; CHECK: %foo:gpr32 = COPY $w1 221 ; CHECK: %load:fpr64 = LDRDroW %base, %foo, 1, 1 :: (load 8) 222 ; CHECK: $x0 = COPY %load 223 ; CHECK: RET_ReallyLR implicit $x0 224 %base:gpr(p0) = COPY $x0 225 %foo:gpr(s32) = COPY $w1 226 %ext:gpr(s64) = G_SEXT %foo(s32) 227 %c:gpr(s64) = G_CONSTANT i64 8 228 %offset:gpr(s64) = G_MUL %c, %ext 229 %ptr:gpr(p0) = G_PTR_ADD %base, %offset(s64) 230 %load:fpr(<2 x s32>) = G_LOAD %ptr(p0) :: (load 8) 231 $x0 = COPY %load(<2 x s32>) 232 RET_ReallyLR implicit $x0 233... 234--- 235name: ldrxrow 236alignment: 4 237legalized: true 238regBankSelected: true 239tracksRegLiveness: true 240frameInfo: 241 maxAlignment: 1 242machineFunctionInfo: {} 243body: | 244 bb.0: 245 liveins: $w1, $x0, $d0 246 247 ; Verify that we can select LDRXroW. 248 249 ; CHECK-LABEL: name: ldrxrow 250 ; CHECK: liveins: $w1, $x0, $d0 251 ; CHECK: %base:gpr64sp = COPY $x0 252 ; CHECK: %foo:gpr32 = COPY $w1 253 ; CHECK: %load:gpr64 = LDRXroW %base, %foo, 1, 1 :: (load 8) 254 ; CHECK: $x0 = COPY %load 255 ; CHECK: RET_ReallyLR implicit $x0 256 %base:gpr(p0) = COPY $x0 257 %foo:gpr(s32) = COPY $w1 258 %ext:gpr(s64) = G_SEXT %foo(s32) 259 %c:gpr(s64) = G_CONSTANT i64 8 260 %offset:gpr(s64) = G_MUL %c, %ext 261 %ptr:gpr(p0) = G_PTR_ADD %base, %offset(s64) 262 %load:gpr(s64) = G_LOAD %ptr(p0) :: (load 8) 263 $x0 = COPY %load(s64) 264 RET_ReallyLR implicit $x0 265... 266--- 267name: ldrbbrow 268alignment: 4 269legalized: true 270regBankSelected: true 271tracksRegLiveness: true 272frameInfo: 273 maxAlignment: 1 274machineFunctionInfo: {} 275body: | 276 bb.1.entry: 277 liveins: $x0, $w0, $w1 278 279 ; Verify that we can select LDRBBroW. Note that there is no shift here, 280 ; but we still fold the extend into the addressing mode. 281 282 ; CHECK-LABEL: name: ldrbbrow 283 ; CHECK: liveins: $x0, $w0, $w1 284 ; CHECK: %val:gpr32 = COPY $w1 285 ; CHECK: %base:gpr64sp = COPY $x0 286 ; CHECK: %load:gpr32 = LDRBBroW %base, %val, 1, 0 :: (load 1) 287 ; CHECK: $w0 = COPY %load 288 ; CHECK: RET_ReallyLR implicit $w0 289 %val:gpr(s32) = COPY $w1 290 %base:gpr(p0) = COPY $x0 291 %ext:gpr(s64) = G_SEXT %val(s32) 292 %ptr:gpr(p0) = G_PTR_ADD %base, %ext(s64) 293 %load:gpr(s32) = G_LOAD %ptr(p0) :: (load 1) 294 $w0 = COPY %load(s32) 295 RET_ReallyLR implicit $w0 296... 297--- 298name: ldrhrow 299alignment: 4 300legalized: true 301regBankSelected: true 302tracksRegLiveness: true 303frameInfo: 304 maxAlignment: 1 305machineFunctionInfo: {} 306body: | 307 bb.1.entry: 308 liveins: $w1, $x0 309 310 ; Verify that we can select ldrhrow. 311 312 ; CHECK-LABEL: name: ldrhrow 313 ; CHECK: liveins: $w1, $x0 314 ; CHECK: %base:gpr64sp = COPY $x0 315 ; CHECK: %foo:gpr32 = COPY $w1 316 ; CHECK: %load:fpr16 = LDRHroW %base, %foo, 1, 1 :: (load 2) 317 ; CHECK: $h0 = COPY %load 318 ; CHECK: RET_ReallyLR implicit $h0 319 %base:gpr(p0) = COPY $x0 320 %foo:gpr(s32) = COPY $w1 321 %ext:gpr(s64) = G_SEXT %foo(s32) 322 %c:gpr(s64) = G_CONSTANT i64 2 323 %offset:gpr(s64) = G_MUL %c, %ext 324 %ptr:gpr(p0) = G_PTR_ADD %base, %offset(s64) 325 %load:fpr(s16) = G_LOAD %ptr(p0) :: (load 2) 326 $h0 = COPY %load(s16) 327 RET_ReallyLR implicit $h0 328... 329--- 330name: bad_and_mask_1 331alignment: 4 332legalized: true 333regBankSelected: true 334tracksRegLiveness: true 335frameInfo: 336 maxAlignment: 1 337body: | 338 bb.0: 339 liveins: $x0 340 341 ; We should get a roX load here, not a roW load. We can't use the mask in 342 ; this test for an extend. 343 344 ; CHECK-LABEL: name: bad_and_mask_1 345 ; CHECK: liveins: $x0 346 ; CHECK: %base:gpr64sp = COPY $x0 347 ; CHECK: %imp:gpr64 = IMPLICIT_DEF 348 ; CHECK: %and:gpr64common = ANDXri %imp, 4103 349 ; CHECK: %load:gpr64 = LDRXroX %base, %and, 0, 1 :: (load 8) 350 ; CHECK: $x1 = COPY %load 351 ; CHECK: RET_ReallyLR implicit $x1 352 %base:gpr(p0) = COPY $x0 353 %imp:gpr(s64) = G_IMPLICIT_DEF 354 %bad_mask:gpr(s64) = G_CONSTANT i64 255 355 %and:gpr(s64) = G_AND %imp, %bad_mask 356 %c:gpr(s64) = G_CONSTANT i64 8 357 %mul:gpr(s64) = G_MUL %c, %and 358 %ptr:gpr(p0) = G_PTR_ADD %base, %mul(s64) 359 %load:gpr(s64) = G_LOAD %ptr(p0) :: (load 8) 360 $x1 = COPY %load(s64) 361 RET_ReallyLR implicit $x1 362... 363--- 364name: bad_and_mask_2 365alignment: 4 366legalized: true 367regBankSelected: true 368tracksRegLiveness: true 369frameInfo: 370 maxAlignment: 1 371body: | 372 bb.0: 373 liveins: $x0 374 375 ; We should get a roX load here, not a roW load. We can't use the mask in 376 ; this test for an extend. 377 378 ; CHECK-LABEL: name: bad_and_mask_2 379 ; CHECK: liveins: $x0 380 ; CHECK: %base:gpr64sp = COPY $x0 381 ; CHECK: %imp:gpr64 = IMPLICIT_DEF 382 ; CHECK: %and:gpr64common = ANDXri %imp, 4111 383 ; CHECK: %load:gpr64 = LDRXroX %base, %and, 0, 1 :: (load 8) 384 ; CHECK: $x1 = COPY %load 385 ; CHECK: RET_ReallyLR implicit $x1 386 %base:gpr(p0) = COPY $x0 387 %imp:gpr(s64) = G_IMPLICIT_DEF 388 %bad_mask:gpr(s64) = G_CONSTANT i64 65535 389 %and:gpr(s64) = G_AND %imp, %bad_mask 390 %c:gpr(s64) = G_CONSTANT i64 8 391 %mul:gpr(s64) = G_MUL %c, %and 392 %ptr:gpr(p0) = G_PTR_ADD %base, %mul(s64) 393 %load:gpr(s64) = G_LOAD %ptr(p0) :: (load 8) 394 $x1 = COPY %load(s64) 395 RET_ReallyLR implicit $x1 396... 397--- 398name: and_uxtw 399alignment: 4 400legalized: true 401regBankSelected: true 402tracksRegLiveness: true 403frameInfo: 404 maxAlignment: 1 405body: | 406 bb.0: 407 liveins: $x0 408 409 ; The mask used for the AND here is legal for producing a roW load. 410 411 ; CHECK-LABEL: name: and_uxtw 412 ; CHECK: liveins: $x0 413 ; CHECK: %base:gpr64sp = COPY $x0 414 ; CHECK: %imp:gpr64 = IMPLICIT_DEF 415 ; CHECK: [[COPY:%[0-9]+]]:gpr32all = COPY %imp.sub_32 416 ; CHECK: [[COPY1:%[0-9]+]]:gpr32 = COPY [[COPY]] 417 ; CHECK: %load:gpr64 = LDRXroW %base, [[COPY1]], 0, 1 :: (load 8) 418 ; CHECK: $x1 = COPY %load 419 ; CHECK: RET_ReallyLR implicit $x1 420 %base:gpr(p0) = COPY $x0 421 %imp:gpr(s64) = G_IMPLICIT_DEF 422 %mask:gpr(s64) = G_CONSTANT i64 4294967295 423 %and:gpr(s64) = G_AND %imp, %mask 424 %c:gpr(s64) = G_CONSTANT i64 8 425 %mul:gpr(s64) = G_MUL %c, %and 426 %ptr:gpr(p0) = G_PTR_ADD %base, %mul(s64) 427 %load:gpr(s64) = G_LOAD %ptr(p0) :: (load 8) 428 $x1 = COPY %load(s64) 429 RET_ReallyLR implicit $x1 430... 431--- 432name: zext_shl_LDRWroW 433alignment: 4 434legalized: true 435regBankSelected: true 436tracksRegLiveness: true 437liveins: 438 - { reg: '$w0' } 439 - { reg: '$x1' } 440body: | 441 bb.1: 442 liveins: $w0, $x1 443 444 ; We try to look through the G_ZEXT of the SHL here. 445 446 ; CHECK-LABEL: name: zext_shl_LDRWroW 447 ; CHECK: liveins: $w0, $x1 448 ; CHECK: [[COPY:%[0-9]+]]:gpr32 = COPY $w0 449 ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 450 ; CHECK: [[ANDWri:%[0-9]+]]:gpr32common = ANDWri [[COPY]], 7 451 ; CHECK: [[LDRWroW:%[0-9]+]]:gpr32 = LDRWroW [[COPY1]], [[ANDWri]], 0, 1 :: (load 4) 452 ; CHECK: $w0 = COPY [[LDRWroW]] 453 ; CHECK: RET_ReallyLR implicit $w0 454 %0:gpr(s32) = COPY $w0 455 %1:gpr(p0) = COPY $x1 456 %2:gpr(s32) = G_CONSTANT i32 255 457 %3:gpr(s32) = G_AND %0, %2 458 %13:gpr(s64) = G_CONSTANT i64 2 459 %12:gpr(s32) = G_SHL %3, %13(s64) 460 %6:gpr(s64) = G_ZEXT %12(s32) 461 %7:gpr(p0) = G_PTR_ADD %1, %6(s64) 462 %9:gpr(s32) = G_LOAD %7(p0) :: (load 4) 463 $w0 = COPY %9(s32) 464 RET_ReallyLR implicit $w0 465 466... 467