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# Check folding a G_SHL into a G_BRCOND which has been matched as a TB(N)Z. 5... 6--- 7name: fold_shl 8alignment: 4 9legalized: true 10regBankSelected: true 11body: | 12 ; CHECK-LABEL: name: fold_shl 13 ; CHECK: bb.0: 14 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000) 15 ; CHECK: %copy:gpr64all = COPY $x0 16 ; CHECK: [[COPY:%[0-9]+]]:gpr32all = COPY %copy.sub_32 17 ; CHECK: [[COPY1:%[0-9]+]]:gpr32 = COPY [[COPY]] 18 ; CHECK: TBNZW [[COPY1]], 2, %bb.1 19 ; CHECK: B %bb.0 20 ; CHECK: bb.1: 21 ; CHECK: RET_ReallyLR 22 bb.0: 23 successors: %bb.0, %bb.1 24 liveins: $x0 25 %copy:gpr(s64) = COPY $x0 26 %bit:gpr(s64) = G_CONSTANT i64 8 27 %zero:gpr(s64) = G_CONSTANT i64 0 28 29 ; tbnz (shl x, 1), 3 == tbnz x, 2 30 %fold_cst:gpr(s64) = G_CONSTANT i64 1 31 %fold_me:gpr(s64) = G_SHL %copy, %fold_cst 32 33 %and:gpr(s64) = G_AND %fold_me, %bit 34 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero 35 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32) 36 G_BRCOND %cmp_trunc(s1), %bb.1 37 G_BR %bb.0 38 bb.1: 39 RET_ReallyLR 40... 41--- 42name: dont_fold_shl_1 43alignment: 4 44legalized: true 45regBankSelected: true 46body: | 47 ; CHECK-LABEL: name: dont_fold_shl_1 48 ; CHECK: bb.0: 49 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000) 50 ; CHECK: %copy:gpr64 = COPY $x0 51 ; CHECK: %fold_me:gpr64 = UBFMXri %copy, 59, 58 52 ; CHECK: [[COPY:%[0-9]+]]:gpr32all = COPY %fold_me.sub_32 53 ; CHECK: [[COPY1:%[0-9]+]]:gpr32 = COPY [[COPY]] 54 ; CHECK: TBNZW [[COPY1]], 3, %bb.1 55 ; CHECK: B %bb.0 56 ; CHECK: bb.1: 57 ; CHECK: RET_ReallyLR 58 bb.0: 59 successors: %bb.0, %bb.1 60 liveins: $x0 61 %copy:gpr(s64) = COPY $x0 62 %bit:gpr(s64) = G_CONSTANT i64 8 63 %zero:gpr(s64) = G_CONSTANT i64 0 64 65 ; 5 > 3, so we cannot do the transformation as above. 66 %fold_cst:gpr(s64) = G_CONSTANT i64 5 67 %fold_me:gpr(s64) = G_SHL %copy, %fold_cst 68 69 %and:gpr(s64) = G_AND %fold_me, %bit 70 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero 71 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32) 72 G_BRCOND %cmp_trunc(s1), %bb.1 73 G_BR %bb.0 74 bb.1: 75 RET_ReallyLR 76... 77--- 78name: dont_fold_shl_2 79alignment: 4 80legalized: true 81regBankSelected: true 82body: | 83 ; CHECK-LABEL: name: dont_fold_shl_2 84 ; CHECK: bb.0: 85 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000) 86 ; CHECK: %copy:gpr64 = COPY $x0 87 ; CHECK: %fold_cst:gpr64 = MOVi64imm -5 88 ; CHECK: %fold_me:gpr64 = LSLVXr %copy, %fold_cst 89 ; CHECK: [[COPY:%[0-9]+]]:gpr32all = COPY %fold_me.sub_32 90 ; CHECK: [[COPY1:%[0-9]+]]:gpr32 = COPY [[COPY]] 91 ; CHECK: TBNZW [[COPY1]], 3, %bb.1 92 ; CHECK: B %bb.0 93 ; CHECK: bb.1: 94 ; CHECK: RET_ReallyLR 95 bb.0: 96 successors: %bb.0, %bb.1 97 liveins: $x0 98 %copy:gpr(s64) = COPY $x0 99 %bit:gpr(s64) = G_CONSTANT i64 8 100 %zero:gpr(s64) = G_CONSTANT i64 0 101 102 ; Same case as above, except we wrap around. 103 %fold_cst:gpr(s64) = G_CONSTANT i64 -5 104 %fold_me:gpr(s64) = G_SHL %copy, %fold_cst 105 106 %and:gpr(s64) = G_AND %fold_me, %bit 107 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero 108 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32) 109 G_BRCOND %cmp_trunc(s1), %bb.1 110 G_BR %bb.0 111 bb.1: 112 RET_ReallyLR 113 114... 115--- 116name: dont_fold_shl_3 117alignment: 4 118legalized: true 119regBankSelected: true 120body: | 121 ; CHECK-LABEL: name: dont_fold_shl_3 122 ; CHECK: bb.0: 123 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000) 124 ; CHECK: %copy:gpr64 = COPY $x0 125 ; CHECK: %shl:gpr64 = UBFMXri %copy, 62, 61 126 ; CHECK: [[COPY:%[0-9]+]]:gpr32all = COPY %shl.sub_32 127 ; CHECK: [[COPY1:%[0-9]+]]:gpr32 = COPY [[COPY]] 128 ; CHECK: TBNZW [[COPY1]], 3, %bb.1 129 ; CHECK: B %bb.0 130 ; CHECK: bb.1: 131 ; CHECK: %second_use:gpr64sp = ORRXri %shl, 8000 132 ; CHECK: $x0 = COPY %second_use 133 ; CHECK: RET_ReallyLR implicit $x0 134 bb.0: 135 successors: %bb.0, %bb.1 136 liveins: $x0 137 %copy:gpr(s64) = COPY $x0 138 %bit:gpr(s64) = G_CONSTANT i64 8 139 %zero:gpr(s64) = G_CONSTANT i64 0 140 %fold_cst:gpr(s64) = G_CONSTANT i64 2 141 142 ; Don't walk past the G_SHL when it's used more than once. 143 %shl:gpr(s64) = G_SHL %copy, %fold_cst 144 %and:gpr(s64) = G_AND %shl, %bit 145 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero 146 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32) 147 G_BRCOND %cmp_trunc(s1), %bb.1 148 G_BR %bb.0 149 150 bb.1: 151 %second_use:gpr(s64) = G_OR %shl, %bit 152 $x0 = COPY %second_use 153 RET_ReallyLR implicit $x0 154 155... 156--- 157name: fold_ashr_in_range 158alignment: 4 159legalized: true 160regBankSelected: true 161body: | 162 ; CHECK-LABEL: name: fold_ashr_in_range 163 ; CHECK: bb.0: 164 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000) 165 ; CHECK: %copy:gpr64all = COPY $x0 166 ; CHECK: [[COPY:%[0-9]+]]:gpr32all = COPY %copy.sub_32 167 ; CHECK: [[COPY1:%[0-9]+]]:gpr32 = COPY [[COPY]] 168 ; CHECK: TBNZW [[COPY1]], 4, %bb.1 169 ; CHECK: B %bb.0 170 ; CHECK: bb.1: 171 ; CHECK: RET_ReallyLR 172 bb.0: 173 successors: %bb.0, %bb.1 174 liveins: $x0 175 %copy:gpr(s64) = COPY $x0 176 %bit:gpr(s64) = G_CONSTANT i64 8 177 %zero:gpr(s64) = G_CONSTANT i64 0 178 179 ; tb(n)z (ashr x, c), b == tbz(x, b + c) when b+c <= the size of the type. 180 ; In this case, we should get 1 + 3 = 4 as the bit number. 181 %fold_cst:gpr(s64) = G_CONSTANT i64 1 182 %fold_me:gpr(s64) = G_ASHR %copy, %fold_cst 183 184 %and:gpr(s64) = G_AND %fold_me, %bit 185 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero 186 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32) 187 G_BRCOND %cmp_trunc(s1), %bb.1 188 G_BR %bb.0 189 bb.1: 190 RET_ReallyLR 191 192... 193--- 194name: fold_ashr_msb_1 195alignment: 4 196legalized: true 197regBankSelected: true 198body: | 199 ; CHECK-LABEL: name: fold_ashr_msb_1 200 ; CHECK: bb.0: 201 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000) 202 ; CHECK: %copy:gpr32 = COPY $w0 203 ; CHECK: TBNZW %copy, 31, %bb.1 204 ; CHECK: B %bb.0 205 ; CHECK: bb.1: 206 ; CHECK: RET_ReallyLR 207 bb.0: 208 successors: %bb.0, %bb.1 209 liveins: $x0 210 %copy:gpr(s32) = COPY $w0 211 %bit:gpr(s32) = G_CONSTANT i32 8 212 %zero:gpr(s32) = G_CONSTANT i32 0 213 214 ; We should get a TBNZW with a 31 as the bit. 215 %fold_cst:gpr(s32) = G_CONSTANT i32 1234 216 %fold_me:gpr(s32) = G_ASHR %copy, %fold_cst 217 218 %and:gpr(s32) = G_AND %fold_me, %bit 219 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s32), %zero 220 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32) 221 G_BRCOND %cmp_trunc(s1), %bb.1 222 G_BR %bb.0 223 bb.1: 224 RET_ReallyLR 225 226... 227--- 228name: fold_ashr_msb_2 229alignment: 4 230legalized: true 231regBankSelected: true 232body: | 233 ; CHECK-LABEL: name: fold_ashr_msb_2 234 ; CHECK: bb.0: 235 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000) 236 ; CHECK: %copy:gpr64 = COPY $x0 237 ; CHECK: TBNZX %copy, 63, %bb.1 238 ; CHECK: B %bb.0 239 ; CHECK: bb.1: 240 ; CHECK: RET_ReallyLR 241 bb.0: 242 successors: %bb.0, %bb.1 243 liveins: $x0 244 %copy:gpr(s64) = COPY $x0 245 %bit:gpr(s64) = G_CONSTANT i64 8 246 %zero:gpr(s64) = G_CONSTANT i64 0 247 248 ; We should get a TBNZX with a 63 as the bit. 249 %fold_cst:gpr(s64) = G_CONSTANT i64 1234 250 %fold_me:gpr(s64) = G_ASHR %copy, %fold_cst 251 252 %and:gpr(s64) = G_AND %fold_me, %bit 253 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero 254 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32) 255 G_BRCOND %cmp_trunc(s1), %bb.1 256 G_BR %bb.0 257 bb.1: 258 RET_ReallyLR 259 260... 261--- 262name: fold_lshr 263alignment: 4 264legalized: true 265regBankSelected: true 266body: | 267 ; CHECK-LABEL: name: fold_lshr 268 ; CHECK: bb.0: 269 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000) 270 ; CHECK: %copy:gpr32 = COPY $w0 271 ; CHECK: TBNZW %copy, 4, %bb.1 272 ; CHECK: B %bb.0 273 ; CHECK: bb.1: 274 ; CHECK: RET_ReallyLR 275 bb.0: 276 successors: %bb.0, %bb.1 277 liveins: $x0 278 %copy:gpr(s32) = COPY $w0 279 %bit:gpr(s32) = G_CONSTANT i32 8 280 %zero:gpr(s32) = G_CONSTANT i32 0 281 282 ; We should get 4 as the test bit. 283 %fold_cst:gpr(s32) = G_CONSTANT i32 1 284 %fold_me:gpr(s32) = G_LSHR %copy, %fold_cst 285 286 %and:gpr(s32) = G_AND %fold_me, %bit 287 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s32), %zero 288 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32) 289 G_BRCOND %cmp_trunc(s1), %bb.1 290 G_BR %bb.0 291 bb.1: 292 RET_ReallyLR 293 294... 295--- 296name: fold_lshr_2 297alignment: 4 298legalized: true 299regBankSelected: true 300body: | 301 ; CHECK-LABEL: name: fold_lshr_2 302 ; CHECK: bb.0: 303 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000) 304 ; CHECK: %copy:gpr64 = COPY $x0 305 ; CHECK: TBNZX %copy, 32, %bb.1 306 ; CHECK: B %bb.0 307 ; CHECK: bb.1: 308 ; CHECK: RET_ReallyLR 309 bb.0: 310 successors: %bb.0, %bb.1 311 liveins: $x0 312 %copy:gpr(s64) = COPY $x0 313 %bit:gpr(s64) = G_CONSTANT i64 8 314 %zero:gpr(s64) = G_CONSTANT i64 0 315 316 ; We're testing a s64. 317 ; 3 + 29 = 32, which is less than 63, so we can fold. 318 %fold_cst:gpr(s64) = G_CONSTANT i64 29 319 %fold_me:gpr(s64) = G_LSHR %copy, %fold_cst 320 321 %and:gpr(s64) = G_AND %fold_me, %bit 322 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s64), %zero 323 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32) 324 G_BRCOND %cmp_trunc(s1), %bb.1 325 G_BR %bb.0 326 bb.1: 327 RET_ReallyLR 328 329... 330--- 331name: dont_fold_lshr 332alignment: 4 333legalized: true 334regBankSelected: true 335body: | 336 ; CHECK-LABEL: name: dont_fold_lshr 337 ; CHECK: bb.0: 338 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000) 339 ; CHECK: %copy:gpr32 = COPY $w0 340 ; CHECK: %fold_cst:gpr32 = MOVi32imm 29 341 ; CHECK: %fold_me:gpr32 = LSRVWr %copy, %fold_cst 342 ; CHECK: TBNZW %fold_me, 3, %bb.1 343 ; CHECK: B %bb.0 344 ; CHECK: bb.1: 345 ; CHECK: RET_ReallyLR 346 bb.0: 347 successors: %bb.0, %bb.1 348 liveins: $x0 349 %copy:gpr(s32) = COPY $w0 350 %bit:gpr(s32) = G_CONSTANT i32 8 351 %zero:gpr(s32) = G_CONSTANT i32 0 352 353 ; We're testing a s32. 354 ; 3 + 29 = 32, which is greater than 31, so we don't fold. 355 %fold_cst:gpr(s32) = G_CONSTANT i32 29 356 %fold_me:gpr(s32) = G_LSHR %copy, %fold_cst 357 358 %and:gpr(s32) = G_AND %fold_me, %bit 359 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s32), %zero 360 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32) 361 G_BRCOND %cmp_trunc(s1), %bb.1 362 G_BR %bb.0 363 bb.1: 364 RET_ReallyLR 365 366... 367--- 368name: lshr_negative 369alignment: 4 370legalized: true 371regBankSelected: true 372body: | 373 ; CHECK-LABEL: name: lshr_negative 374 ; CHECK: bb.0: 375 ; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000) 376 ; CHECK: %copy:gpr32 = COPY $w0 377 ; CHECK: TBNZW %copy, 2, %bb.1 378 ; CHECK: B %bb.0 379 ; CHECK: bb.1: 380 ; CHECK: RET_ReallyLR 381 bb.0: 382 successors: %bb.0, %bb.1 383 liveins: $x0 384 %copy:gpr(s32) = COPY $w0 385 %bit:gpr(s32) = G_CONSTANT i32 8 386 %zero:gpr(s32) = G_CONSTANT i32 0 387 388 ; Constant becomes very large and wraps around. Since it's larger than the 389 ; bit width, that means the LSHR is poison, so we can still fold. 390 %fold_cst:gpr(s32) = G_CONSTANT i32 -1 391 %fold_me:gpr(s32) = G_LSHR %copy, %fold_cst 392 393 %and:gpr(s32) = G_AND %fold_me, %bit 394 %cmp:gpr(s32) = G_ICMP intpred(ne), %and(s32), %zero 395 %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32) 396 G_BRCOND %cmp_trunc(s1), %bb.1 397 G_BR %bb.0 398 bb.1: 399 RET_ReallyLR 400