1 # RUN: llc -run-pass x86-flags-copy-lowering -verify-machineinstrs -o - %s | FileCheck %s 2 # 3 # Lower various interesting copy patterns of EFLAGS without using LAHF/SAHF. 4 5 --- | 6 target triple = "x86_64-unknown-unknown" 7 8 declare void @foo() 9 10 define i32 @test_branch(i64 %a, i64 %b) { 11 entry: 12 call void @foo() 13 ret i32 0 14 } 15 16 define i32 @test_branch_fallthrough(i64 %a, i64 %b) { 17 entry: 18 call void @foo() 19 ret i32 0 20 } 21 22 define void @test_setcc(i64 %a, i64 %b) { 23 entry: 24 call void @foo() 25 ret void 26 } 27 28 define void @test_cmov(i64 %a, i64 %b) { 29 entry: 30 call void @foo() 31 ret void 32 } 33 34 define void @test_adc(i64 %a, i64 %b) { 35 entry: 36 call void @foo() 37 ret void 38 } 39 40 define void @test_sbb(i64 %a, i64 %b) { 41 entry: 42 call void @foo() 43 ret void 44 } 45 46 define void @test_adcx(i64 %a, i64 %b) { 47 entry: 48 call void @foo() 49 ret void 50 } 51 52 define void @test_adox(i64 %a, i64 %b) { 53 entry: 54 call void @foo() 55 ret void 56 } 57 58 define void @test_rcl(i64 %a, i64 %b) { 59 entry: 60 call void @foo() 61 ret void 62 } 63 64 define void @test_rcr(i64 %a, i64 %b) { 65 entry: 66 call void @foo() 67 ret void 68 } 69 70 define void @test_setb_c(i64 %a, i64 %b) { 71 entry: 72 call void @foo() 73 ret void 74 } 75 76 define i64 @test_branch_with_livein_and_kill(i64 %a, i64 %b) { 77 entry: 78 call void @foo() 79 ret i64 0 80 } 81 82 define i64 @test_branch_with_interleaved_livein_and_kill(i64 %a, i64 %b) { 83 entry: 84 call void @foo() 85 ret i64 0 86 } 87 88 define i64 @test_mid_cycle_copies(i64 %a, i64 %b) { 89 entry: 90 call void @foo() 91 ret i64 0 92 } 93 94 define i32 @test_existing_setcc(i64 %a, i64 %b) { 95 entry: 96 call void @foo() 97 ret i32 0 98 } 99 100 define i32 @test_existing_setcc_memory(i64 %a, i64 %b) { 101 entry: 102 call void @foo() 103 ret i32 0 104 } 105 ... 106 --- 107 name: test_branch 108 # CHECK-LABEL: name: test_branch 109 liveins: 110 - { reg: '$rdi', virtual-reg: '%0' } 111 - { reg: '$rsi', virtual-reg: '%1' } 112 body: | 113 bb.0: 114 successors: %bb.1, %bb.2, %bb.3 115 liveins: $rdi, $rsi 116 117 %0:gr64 = COPY $rdi 118 %1:gr64 = COPY $rsi 119 CMP64rr %0, %1, implicit-def $eflags 120 %2:gr64 = COPY $eflags 121 ; CHECK-NOT: COPY{{( killed)?}} $eflags 122 ; CHECK: %[[A_REG:[^:]*]]:gr8 = SETAr implicit $eflags 123 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETBr implicit $eflags 124 ; CHECK-NOT: COPY{{( killed)?}} $eflags 125 126 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 127 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax 128 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 129 130 $eflags = COPY %2 131 JA_1 %bb.1, implicit $eflags 132 JB_1 %bb.2, implicit $eflags 133 JMP_1 %bb.3 134 ; CHECK-NOT: $eflags = 135 ; 136 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags 137 ; CHECK-NEXT: JNE_1 %bb.1, implicit killed $eflags 138 ; CHECK-SAME: {{$[[:space:]]}} 139 ; CHECK-NEXT: bb.4: 140 ; CHECK-NEXT: successors: {{.*$}} 141 ; CHECK-SAME: {{$[[:space:]]}} 142 ; CHECK-NEXT: TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags 143 ; CHECK-NEXT: JNE_1 %bb.2, implicit killed $eflags 144 ; CHECK-NEXT: JMP_1 %bb.3 145 146 bb.1: 147 %3:gr32 = MOV32ri64 42 148 $eax = COPY %3 149 RET 0, $eax 150 151 bb.2: 152 %4:gr32 = MOV32ri64 43 153 $eax = COPY %4 154 RET 0, $eax 155 156 bb.3: 157 %5:gr32 = MOV32r0 implicit-def dead $eflags 158 $eax = COPY %5 159 RET 0, $eax 160 161 ... 162 --- 163 name: test_branch_fallthrough 164 # CHECK-LABEL: name: test_branch_fallthrough 165 liveins: 166 - { reg: '$rdi', virtual-reg: '%0' } 167 - { reg: '$rsi', virtual-reg: '%1' } 168 body: | 169 bb.0: 170 successors: %bb.1, %bb.2, %bb.3 171 liveins: $rdi, $rsi 172 173 %0:gr64 = COPY $rdi 174 %1:gr64 = COPY $rsi 175 CMP64rr %0, %1, implicit-def $eflags 176 %2:gr64 = COPY $eflags 177 ; CHECK-NOT: COPY{{( killed)?}} $eflags 178 ; CHECK: %[[A_REG:[^:]*]]:gr8 = SETAr implicit $eflags 179 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETBr implicit $eflags 180 ; CHECK-NOT: COPY{{( killed)?}} $eflags 181 182 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 183 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax 184 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 185 186 $eflags = COPY %2 187 JA_1 %bb.2, implicit $eflags 188 JB_1 %bb.3, implicit $eflags 189 ; CHECK-NOT: $eflags = 190 ; 191 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags 192 ; CHECK-NEXT: JNE_1 %bb.2, implicit killed $eflags 193 ; CHECK-SAME: {{$[[:space:]]}} 194 ; CHECK-NEXT: bb.4: 195 ; CHECK-NEXT: successors: {{.*$}} 196 ; CHECK-SAME: {{$[[:space:]]}} 197 ; CHECK-NEXT: TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags 198 ; CHECK-NEXT: JNE_1 %bb.3, implicit killed $eflags 199 ; CHECK-SAME: {{$[[:space:]]}} 200 ; CHECK-NEXT: bb.1: 201 202 bb.1: 203 %5:gr32 = MOV32r0 implicit-def dead $eflags 204 $eax = COPY %5 205 RET 0, $eax 206 207 bb.2: 208 %3:gr32 = MOV32ri64 42 209 $eax = COPY %3 210 RET 0, $eax 211 212 bb.3: 213 %4:gr32 = MOV32ri64 43 214 $eax = COPY %4 215 RET 0, $eax 216 217 ... 218 --- 219 name: test_setcc 220 # CHECK-LABEL: name: test_setcc 221 liveins: 222 - { reg: '$rdi', virtual-reg: '%0' } 223 - { reg: '$rsi', virtual-reg: '%1' } 224 body: | 225 bb.0: 226 liveins: $rdi, $rsi 227 228 %0:gr64 = COPY $rdi 229 %1:gr64 = COPY $rsi 230 CMP64rr %0, %1, implicit-def $eflags 231 %2:gr64 = COPY $eflags 232 ; CHECK-NOT: COPY{{( killed)?}} $eflags 233 ; CHECK: %[[A_REG:[^:]*]]:gr8 = SETAr implicit $eflags 234 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETBr implicit $eflags 235 ; CHECK-NEXT: %[[E_REG:[^:]*]]:gr8 = SETEr implicit $eflags 236 ; CHECK-NEXT: %[[NE_REG:[^:]*]]:gr8 = SETNEr implicit $eflags 237 ; CHECK-NOT: COPY{{( killed)?}} $eflags 238 239 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 240 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax 241 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 242 243 $eflags = COPY %2 244 %3:gr8 = SETAr implicit $eflags 245 %4:gr8 = SETBr implicit $eflags 246 %5:gr8 = SETEr implicit $eflags 247 SETNEm $rsp, 1, $noreg, -16, $noreg, implicit killed $eflags 248 MOV8mr $rsp, 1, $noreg, -16, $noreg, killed %3 249 MOV8mr $rsp, 1, $noreg, -16, $noreg, killed %4 250 MOV8mr $rsp, 1, $noreg, -16, $noreg, killed %5 251 ; CHECK-NOT: $eflags = 252 ; CHECK-NOT: = SET{{.*}} 253 ; CHECK: MOV8mr {{.*}}, killed %[[A_REG]] 254 ; CHECK-NEXT: MOV8mr {{.*}}, killed %[[B_REG]] 255 ; CHECK-NEXT: MOV8mr {{.*}}, killed %[[E_REG]] 256 ; CHECK-NOT: MOV8mr {{.*}}, killed %[[NE_REG]] 257 258 RET 0 259 260 ... 261 --- 262 name: test_cmov 263 # CHECK-LABEL: name: test_cmov 264 liveins: 265 - { reg: '$rdi', virtual-reg: '%0' } 266 - { reg: '$rsi', virtual-reg: '%1' } 267 body: | 268 bb.0: 269 liveins: $rdi, $rsi 270 271 %0:gr64 = COPY $rdi 272 %1:gr64 = COPY $rsi 273 CMP64rr %0, %1, implicit-def $eflags 274 %2:gr64 = COPY $eflags 275 ; CHECK-NOT: COPY{{( killed)?}} $eflags 276 ; CHECK: %[[A_REG:[^:]*]]:gr8 = SETAr implicit $eflags 277 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETBr implicit $eflags 278 ; CHECK-NEXT: %[[E_REG:[^:]*]]:gr8 = SETEr implicit $eflags 279 ; CHECK-NOT: COPY{{( killed)?}} $eflags 280 281 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 282 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax 283 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 284 285 $eflags = COPY %2 286 %3:gr64 = CMOVA64rr %0, %1, implicit $eflags 287 %4:gr64 = CMOVB64rr %0, %1, implicit $eflags 288 %5:gr64 = CMOVE64rr %0, %1, implicit $eflags 289 %6:gr64 = CMOVNE64rr %0, %1, implicit killed $eflags 290 ; CHECK-NOT: $eflags = 291 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags 292 ; CHECK-NEXT: %3:gr64 = CMOVNE64rr %0, %1, implicit killed $eflags 293 ; CHECK-NEXT: TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags 294 ; CHECK-NEXT: %4:gr64 = CMOVNE64rr %0, %1, implicit killed $eflags 295 ; CHECK-NEXT: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags 296 ; CHECK-NEXT: %5:gr64 = CMOVNE64rr %0, %1, implicit killed $eflags 297 ; CHECK-NEXT: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags 298 ; CHECK-NEXT: %6:gr64 = CMOVE64rr %0, %1, implicit killed $eflags 299 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %3 300 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %4 301 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5 302 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %6 303 304 RET 0 305 306 ... 307 --- 308 name: test_adc 309 # CHECK-LABEL: name: test_adc 310 liveins: 311 - { reg: '$rdi', virtual-reg: '%0' } 312 - { reg: '$rsi', virtual-reg: '%1' } 313 body: | 314 bb.0: 315 liveins: $rdi, $rsi 316 317 %0:gr64 = COPY $rdi 318 %1:gr64 = COPY $rsi 319 %2:gr64 = ADD64rr %0, %1, implicit-def $eflags 320 %3:gr64 = COPY $eflags 321 ; CHECK-NOT: COPY{{( killed)?}} $eflags 322 ; CHECK: %[[CF_REG:[^:]*]]:gr8 = SETBr implicit $eflags 323 ; CHECK-NOT: COPY{{( killed)?}} $eflags 324 325 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 326 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax 327 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 328 329 $eflags = COPY %3 330 %4:gr64 = ADC64ri32 %2:gr64, 42, implicit-def $eflags, implicit $eflags 331 %5:gr64 = ADC64ri32 %4:gr64, 42, implicit-def $eflags, implicit $eflags 332 ; CHECK-NOT: $eflags = 333 ; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags 334 ; CHECK-NEXT: %4:gr64 = ADC64ri32 %2, 42, implicit-def $eflags, implicit killed $eflags 335 ; CHECK-NEXT: %5:gr64 = ADC64ri32 %4, 42, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags 336 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5 337 338 RET 0 339 340 ... 341 --- 342 name: test_sbb 343 # CHECK-LABEL: name: test_sbb 344 liveins: 345 - { reg: '$rdi', virtual-reg: '%0' } 346 - { reg: '$rsi', virtual-reg: '%1' } 347 body: | 348 bb.0: 349 liveins: $rdi, $rsi 350 351 %0:gr64 = COPY $rdi 352 %1:gr64 = COPY $rsi 353 %2:gr64 = SUB64rr %0, %1, implicit-def $eflags 354 %3:gr64 = COPY killed $eflags 355 ; CHECK-NOT: COPY{{( killed)?}} $eflags 356 ; CHECK: %[[CF_REG:[^:]*]]:gr8 = SETBr implicit $eflags 357 ; CHECK-NOT: COPY{{( killed)?}} $eflags 358 359 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 360 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax 361 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 362 363 $eflags = COPY %3 364 %4:gr64 = SBB64ri32 %2:gr64, 42, implicit-def $eflags, implicit killed $eflags 365 %5:gr64 = SBB64ri32 %4:gr64, 42, implicit-def dead $eflags, implicit killed $eflags 366 ; CHECK-NOT: $eflags = 367 ; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags 368 ; CHECK-NEXT: %4:gr64 = SBB64ri32 %2, 42, implicit-def $eflags, implicit killed $eflags 369 ; CHECK-NEXT: %5:gr64 = SBB64ri32 %4, 42, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags 370 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5 371 372 RET 0 373 374 ... 375 --- 376 name: test_adcx 377 # CHECK-LABEL: name: test_adcx 378 liveins: 379 - { reg: '$rdi', virtual-reg: '%0' } 380 - { reg: '$rsi', virtual-reg: '%1' } 381 body: | 382 bb.0: 383 liveins: $rdi, $rsi 384 385 %0:gr64 = COPY $rdi 386 %1:gr64 = COPY $rsi 387 %2:gr64 = ADD64rr %0, %1, implicit-def $eflags 388 %3:gr64 = COPY $eflags 389 ; CHECK-NOT: COPY{{( killed)?}} $eflags 390 ; CHECK: %[[E_REG:[^:]*]]:gr8 = SETEr implicit $eflags 391 ; CHECK-NEXT: %[[CF_REG:[^:]*]]:gr8 = SETBr implicit $eflags 392 ; CHECK-NOT: COPY{{( killed)?}} $eflags 393 394 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 395 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax 396 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 397 398 $eflags = COPY %3 399 %4:gr64 = CMOVE64rr %0, %1, implicit $eflags 400 %5:gr64 = MOV64ri32 42 401 %6:gr64 = ADCX64rr %2, %5, implicit-def $eflags, implicit $eflags 402 ; CHECK-NOT: $eflags = 403 ; CHECK: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags 404 ; CHECK-NEXT: %4:gr64 = CMOVNE64rr %0, %1, implicit killed $eflags 405 ; CHECK-NEXT: %5:gr64 = MOV64ri32 42 406 ; CHECK-NEXT: dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags 407 ; CHECK-NEXT: %6:gr64 = ADCX64rr %2, %5, implicit-def{{( dead)?}} $eflags, implicit killed $eflags 408 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %4 409 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %6 410 411 RET 0 412 413 ... 414 --- 415 name: test_adox 416 # CHECK-LABEL: name: test_adox 417 liveins: 418 - { reg: '$rdi', virtual-reg: '%0' } 419 - { reg: '$rsi', virtual-reg: '%1' } 420 body: | 421 bb.0: 422 liveins: $rdi, $rsi 423 424 %0:gr64 = COPY $rdi 425 %1:gr64 = COPY $rsi 426 %2:gr64 = ADD64rr %0, %1, implicit-def $eflags 427 %3:gr64 = COPY $eflags 428 ; CHECK-NOT: COPY{{( killed)?}} $eflags 429 ; CHECK: %[[E_REG:[^:]*]]:gr8 = SETEr implicit $eflags 430 ; CHECK-NEXT: %[[OF_REG:[^:]*]]:gr8 = SETOr implicit $eflags 431 ; CHECK-NOT: COPY{{( killed)?}} $eflags 432 433 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 434 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax 435 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 436 437 $eflags = COPY %3 438 %4:gr64 = CMOVE64rr %0, %1, implicit $eflags 439 %5:gr64 = MOV64ri32 42 440 %6:gr64 = ADOX64rr %2, %5, implicit-def $eflags, implicit $eflags 441 ; CHECK-NOT: $eflags = 442 ; CHECK: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags 443 ; CHECK-NEXT: %4:gr64 = CMOVNE64rr %0, %1, implicit killed $eflags 444 ; CHECK-NEXT: %5:gr64 = MOV64ri32 42 445 ; CHECK-NEXT: dead %{{[^:]*}}:gr8 = ADD8ri %[[OF_REG]], 127, implicit-def $eflags 446 ; CHECK-NEXT: %6:gr64 = ADOX64rr %2, %5, implicit-def{{( dead)?}} $eflags, implicit killed $eflags 447 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %4 448 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %6 449 450 RET 0 451 452 ... 453 --- 454 name: test_rcl 455 # CHECK-LABEL: name: test_rcl 456 liveins: 457 - { reg: '$rdi', virtual-reg: '%0' } 458 - { reg: '$rsi', virtual-reg: '%1' } 459 body: | 460 bb.0: 461 liveins: $rdi, $rsi 462 463 %0:gr64 = COPY $rdi 464 %1:gr64 = COPY $rsi 465 %2:gr64 = ADD64rr %0, %1, implicit-def $eflags 466 %3:gr64 = COPY $eflags 467 ; CHECK-NOT: COPY{{( killed)?}} $eflags 468 ; CHECK: %[[CF_REG:[^:]*]]:gr8 = SETBr implicit $eflags 469 ; CHECK-NOT: COPY{{( killed)?}} $eflags 470 471 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 472 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax 473 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 474 475 $eflags = COPY %3 476 %4:gr64 = RCL64r1 %2:gr64, implicit-def $eflags, implicit $eflags 477 %5:gr64 = RCL64r1 %4:gr64, implicit-def $eflags, implicit $eflags 478 ; CHECK-NOT: $eflags = 479 ; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags 480 ; CHECK-NEXT: %4:gr64 = RCL64r1 %2, implicit-def $eflags, implicit killed $eflags 481 ; CHECK-NEXT: %5:gr64 = RCL64r1 %4, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags 482 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5 483 484 RET 0 485 486 ... 487 --- 488 name: test_rcr 489 # CHECK-LABEL: name: test_rcr 490 liveins: 491 - { reg: '$rdi', virtual-reg: '%0' } 492 - { reg: '$rsi', virtual-reg: '%1' } 493 body: | 494 bb.0: 495 liveins: $rdi, $rsi 496 497 %0:gr64 = COPY $rdi 498 %1:gr64 = COPY $rsi 499 %2:gr64 = ADD64rr %0, %1, implicit-def $eflags 500 %3:gr64 = COPY $eflags 501 ; CHECK-NOT: COPY{{( killed)?}} $eflags 502 ; CHECK: %[[CF_REG:[^:]*]]:gr8 = SETBr implicit $eflags 503 ; CHECK-NOT: COPY{{( killed)?}} $eflags 504 505 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 506 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax 507 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 508 509 $eflags = COPY %3 510 %4:gr64 = RCR64r1 %2:gr64, implicit-def $eflags, implicit $eflags 511 %5:gr64 = RCR64r1 %4:gr64, implicit-def $eflags, implicit $eflags 512 ; CHECK-NOT: $eflags = 513 ; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags 514 ; CHECK-NEXT: %4:gr64 = RCR64r1 %2, implicit-def $eflags, implicit killed $eflags 515 ; CHECK-NEXT: %5:gr64 = RCR64r1 %4, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags 516 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5 517 518 RET 0 519 520 ... 521 --- 522 name: test_setb_c 523 # CHECK-LABEL: name: test_setb_c 524 liveins: 525 - { reg: '$rdi', virtual-reg: '%0' } 526 - { reg: '$rsi', virtual-reg: '%1' } 527 body: | 528 bb.0: 529 liveins: $rdi, $rsi 530 531 %0:gr64 = COPY $rdi 532 %1:gr64 = COPY $rsi 533 %2:gr64 = ADD64rr %0, %1, implicit-def $eflags 534 %3:gr64 = COPY $eflags 535 ; CHECK-NOT: COPY{{( killed)?}} $eflags 536 ; CHECK: %[[CF_REG:[^:]*]]:gr8 = SETBr implicit $eflags 537 ; CHECK-NOT: COPY{{( killed)?}} $eflags 538 539 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 540 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax 541 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 542 543 $eflags = COPY %3 544 %4:gr8 = SETB_C8r implicit-def $eflags, implicit $eflags 545 MOV8mr $rsp, 1, $noreg, -16, $noreg, killed %4 546 ; CHECK-NOT: $eflags = 547 ; CHECK: %[[ZERO:[^:]*]]:gr32 = MOV32r0 implicit-def $eflags 548 ; CHECK-NEXT: %[[ZERO_SUBREG:[^:]*]]:gr8 = COPY %[[ZERO]].sub_8bit 549 ; CHECK-NEXT: %[[REPLACEMENT:[^:]*]]:gr8 = SUB8rr %[[ZERO_SUBREG]], %[[CF_REG]] 550 ; CHECK-NEXT: MOV8mr $rsp, 1, $noreg, -16, $noreg, killed %[[REPLACEMENT]] 551 552 $eflags = COPY %3 553 %5:gr16 = SETB_C16r implicit-def $eflags, implicit $eflags 554 MOV16mr $rsp, 1, $noreg, -16, $noreg, killed %5 555 ; CHECK-NOT: $eflags = 556 ; CHECK: %[[CF_EXT:[^:]*]]:gr32 = MOVZX32rr8 %[[CF_REG]] 557 ; CHECK-NEXT: %[[CF_TRUNC:[^:]*]]:gr16 = COPY %[[CF_EXT]].sub_16bit 558 ; CHECK-NEXT: %[[ZERO:[^:]*]]:gr32 = MOV32r0 implicit-def $eflags 559 ; CHECK-NEXT: %[[ZERO_SUBREG:[^:]*]]:gr16 = COPY %[[ZERO]].sub_16bit 560 ; CHECK-NEXT: %[[REPLACEMENT:[^:]*]]:gr16 = SUB16rr %[[ZERO_SUBREG]], %[[CF_TRUNC]] 561 ; CHECK-NEXT: MOV16mr $rsp, 1, $noreg, -16, $noreg, killed %[[REPLACEMENT]] 562 563 $eflags = COPY %3 564 %6:gr32 = SETB_C32r implicit-def $eflags, implicit $eflags 565 MOV32mr $rsp, 1, $noreg, -16, $noreg, killed %6 566 ; CHECK-NOT: $eflags = 567 ; CHECK: %[[CF_EXT:[^:]*]]:gr32 = MOVZX32rr8 %[[CF_REG]] 568 ; CHECK-NEXT: %[[ZERO:[^:]*]]:gr32 = MOV32r0 implicit-def $eflags 569 ; CHECK-NEXT: %[[REPLACEMENT:[^:]*]]:gr32 = SUB32rr %[[ZERO]], %[[CF_EXT]] 570 ; CHECK-NEXT: MOV32mr $rsp, 1, $noreg, -16, $noreg, killed %[[REPLACEMENT]] 571 572 $eflags = COPY %3 573 %7:gr64 = SETB_C64r implicit-def $eflags, implicit $eflags 574 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %7 575 ; CHECK-NOT: $eflags = 576 ; CHECK: %[[CF_EXT1:[^:]*]]:gr32 = MOVZX32rr8 %[[CF_REG]] 577 ; CHECK-NEXT: %[[CF_EXT2:[^:]*]]:gr64 = SUBREG_TO_REG 0, %[[CF_EXT1]], %subreg.sub_32bit 578 ; CHECK-NEXT: %[[ZERO:[^:]*]]:gr32 = MOV32r0 implicit-def $eflags 579 ; CHECK-NEXT: %[[ZERO_EXT:[^:]*]]:gr64 = SUBREG_TO_REG 0, %[[ZERO]], %subreg.sub_32bit 580 ; CHECK-NEXT: %[[REPLACEMENT:[^:]*]]:gr64 = SUB64rr %[[ZERO_EXT]], %[[CF_EXT2]] 581 ; CHECK-NEXT: MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %[[REPLACEMENT]] 582 583 RET 0 584 585 ... 586 --- 587 name: test_branch_with_livein_and_kill 588 # CHECK-LABEL: name: test_branch_with_livein_and_kill 589 liveins: 590 - { reg: '$rdi', virtual-reg: '%0' } 591 - { reg: '$rsi', virtual-reg: '%1' } 592 body: | 593 bb.0: 594 successors: %bb.1, %bb.2, %bb.3 595 liveins: $rdi, $rsi 596 597 %0:gr64 = COPY $rdi 598 %1:gr64 = COPY $rsi 599 CMP64rr %0, %1, implicit-def $eflags 600 %2:gr64 = COPY $eflags 601 ; CHECK-NOT: COPY{{( killed)?}} $eflags 602 ; CHECK: %[[S_REG:[^:]*]]:gr8 = SETSr implicit $eflags 603 ; CHECK-NEXT: %[[NE_REG:[^:]*]]:gr8 = SETNEr implicit $eflags 604 ; CHECK-NEXT: %[[A_REG:[^:]*]]:gr8 = SETAr implicit $eflags 605 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETBr implicit $eflags 606 ; CHECK-NOT: COPY{{( killed)?}} $eflags 607 608 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 609 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax 610 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 611 612 $eflags = COPY %2 613 JA_1 %bb.1, implicit $eflags 614 JB_1 %bb.2, implicit $eflags 615 JMP_1 %bb.3 616 ; CHECK-NOT: $eflags = 617 ; 618 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags 619 ; CHECK-NEXT: JNE_1 %bb.1, implicit killed $eflags 620 ; CHECK-SAME: {{$[[:space:]]}} 621 ; CHECK-NEXT: bb.4: 622 ; CHECK-NEXT: successors: {{.*$}} 623 ; CHECK-SAME: {{$[[:space:]]}} 624 ; CHECK-NEXT: TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags 625 ; CHECK-NEXT: JNE_1 %bb.2, implicit killed $eflags 626 ; CHECK-NEXT: JMP_1 %bb.3 627 628 bb.1: 629 liveins: $eflags 630 631 %3:gr64 = CMOVE64rr %0, %1, implicit killed $eflags 632 ; CHECK-NOT: $eflags = 633 ; CHECK: TEST8rr %[[NE_REG]], %[[NE_REG]], implicit-def $eflags 634 ; CHECK-NEXT: %3:gr64 = CMOVE64rr %0, %1, implicit killed $eflags 635 $rax = COPY %3 636 RET 0, $rax 637 638 bb.2: 639 liveins: $eflags 640 641 %4:gr64 = CMOVNE64rr %0, %1, implicit killed $eflags 642 ; CHECK-NOT: $eflags = 643 ; CHECK: TEST8rr %[[NE_REG]], %[[NE_REG]], implicit-def $eflags 644 ; CHECK-NEXT: %4:gr64 = CMOVNE64rr %0, %1, implicit killed $eflags 645 $rax = COPY %4 646 RET 0, $rax 647 648 bb.3: 649 liveins: $eflags 650 651 %5:gr64 = CMOVS64rr %0, %1, implicit killed $eflags 652 ; CHECK-NOT: $eflags = 653 ; CHECK: TEST8rr %[[S_REG]], %[[S_REG]], implicit-def $eflags 654 ; CHECK-NEXT: %5:gr64 = CMOVNE64rr %0, %1, implicit killed $eflags 655 $rax = COPY %5 656 RET 0, $rax 657 658 ... 659 --- 660 name: test_branch_with_interleaved_livein_and_kill 661 # CHECK-LABEL: name: test_branch_with_interleaved_livein_and_kill 662 liveins: 663 - { reg: '$rdi', virtual-reg: '%0' } 664 - { reg: '$rsi', virtual-reg: '%1' } 665 body: | 666 bb.0: 667 successors: %bb.1, %bb.2, %bb.5 668 liveins: $rdi, $rsi 669 670 %0:gr64 = COPY $rdi 671 %1:gr64 = COPY $rsi 672 CMP64rr %0, %1, implicit-def $eflags 673 %2:gr64 = COPY $eflags 674 ; CHECK-NOT: COPY{{( killed)?}} $eflags 675 ; CHECK: %[[S_REG:[^:]*]]:gr8 = SETSr implicit $eflags 676 ; CHECK-NEXT: %[[P_REG:[^:]*]]:gr8 = SETPr implicit $eflags 677 ; CHECK-NEXT: %[[NE_REG:[^:]*]]:gr8 = SETNEr implicit $eflags 678 ; CHECK-NEXT: %[[A_REG:[^:]*]]:gr8 = SETAr implicit $eflags 679 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETBr implicit $eflags 680 ; CHECK-NEXT: %[[O_REG:[^:]*]]:gr8 = SETOr implicit $eflags 681 ; CHECK-NOT: COPY{{( killed)?}} $eflags 682 683 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 684 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax 685 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 686 687 $eflags = COPY %2 688 JA_1 %bb.1, implicit $eflags 689 JB_1 %bb.2, implicit $eflags 690 JMP_1 %bb.5 691 ; CHECK-NOT: $eflags = 692 ; 693 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags 694 ; CHECK-NEXT: JNE_1 %bb.1, implicit killed $eflags 695 ; CHECK-SAME: {{$[[:space:]]}} 696 ; CHECK-NEXT: bb.6: 697 ; CHECK-NEXT: successors: {{.*$}} 698 ; CHECK-SAME: {{$[[:space:]]}} 699 ; CHECK-NEXT: TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags 700 ; CHECK-NEXT: JNE_1 %bb.2, implicit killed $eflags 701 ; CHECK-NEXT: JMP_1 %bb.5 702 703 bb.1: 704 liveins: $eflags 705 706 %3:gr64 = CMOVE64rr %0, %1, implicit killed $eflags 707 ; CHECK-NOT: $eflags = 708 ; CHECK: TEST8rr %[[NE_REG]], %[[NE_REG]], implicit-def $eflags 709 ; CHECK-NEXT: %3:gr64 = CMOVE64rr %0, %1, implicit killed $eflags 710 $rax = COPY %3 711 RET 0, $rax 712 713 bb.2: 714 ; The goal is to have another batch of successors discovered in a block 715 ; between two successors which kill $eflags. This ensures that neither of 716 ; the surrounding kills impact recursing through this block. 717 successors: %bb.3, %bb.4 718 liveins: $eflags 719 720 JO_1 %bb.3, implicit $eflags 721 JMP_1 %bb.4 722 ; CHECK-NOT: $eflags = 723 ; 724 ; CHECK: TEST8rr %[[O_REG]], %[[O_REG]], implicit-def $eflags 725 ; CHECK-NEXT: JNE_1 %bb.3, implicit killed $eflags 726 ; CHECK-NEXT: JMP_1 %bb.4 727 728 bb.3: 729 liveins: $eflags 730 731 %4:gr64 = CMOVNE64rr %0, %1, implicit $eflags 732 ; CHECK-NOT: $eflags = 733 ; CHECK: TEST8rr %[[NE_REG]], %[[NE_REG]], implicit-def $eflags 734 ; CHECK-NEXT: %4:gr64 = CMOVNE64rr %0, %1, implicit killed $eflags 735 $rax = COPY %4 736 RET 0, $rax 737 738 bb.4: 739 liveins: $eflags 740 741 %5:gr64 = CMOVP64rr %0, %1, implicit $eflags 742 ; CHECK-NOT: $eflags = 743 ; CHECK: TEST8rr %[[P_REG]], %[[P_REG]], implicit-def $eflags 744 ; CHECK-NEXT: %5:gr64 = CMOVNE64rr %0, %1, implicit killed $eflags 745 $rax = COPY %5 746 RET 0, $rax 747 748 bb.5: 749 liveins: $eflags 750 751 %6:gr64 = CMOVS64rr %0, %1, implicit killed $eflags 752 ; CHECK-NOT: $eflags = 753 ; CHECK: TEST8rr %[[S_REG]], %[[S_REG]], implicit-def $eflags 754 ; CHECK-NEXT: %6:gr64 = CMOVNE64rr %0, %1, implicit killed $eflags 755 $rax = COPY %6 756 RET 0, $rax 757 758 ... 759 --- 760 # This test case is designed to exercise a particularly challenging situation: 761 # when the flags are copied and restored *inside* of a complex and cyclic CFG 762 # all of which have live-in flags. To correctly handle this case we have to walk 763 # up the dominator tree and locate a viable reaching definition location, 764 # checking for clobbers along any path. The CFG for this function looks like the 765 # following diagram, control flowing out the bottom of blocks and in the top: 766 # 767 # bb.0 768 # | __________________ 769 # |/ \ 770 # bb.1 | 771 # |\_________ | 772 # | __ \ ____ | 773 # |/ \ |/ \ | 774 # bb.2 | bb.4 | | 775 # |\__/ / \ | | 776 # | / \ | | 777 # bb.3 bb.5 bb.6 | | 778 # | \ / | | 779 # | \ / | | 780 # | bb.7 | | 781 # | ________/ \____/ | 782 # |/ | 783 # bb.8 | 784 # |\__________________/ 785 # | 786 # bb.9 787 # 788 # We set EFLAGS in bb.0, clobber them in bb.3, and copy them in bb.2 and bb.6. 789 # Because of the cycles this requires hoisting the `SETcc` instructions to 790 # capture the flags for the bb.6 copy to bb.1 and using them for the copy in 791 # `bb.2` as well despite the clobber in `bb.3`. The clobber in `bb.3` also 792 # prevents hoisting the `SETcc`s up to `bb.0`. 793 # 794 # Throughout the test we use branch instructions that are totally bogus (as the 795 # flags are obviously not changing!) but this is just to allow us to send 796 # a small but complex CFG structure through the backend and force it to choose 797 # plausible lowering decisions based on the core CFG presented, regardless of 798 # the futility of the actual branches. 799 name: test_mid_cycle_copies 800 # CHECK-LABEL: name: test_mid_cycle_copies 801 liveins: 802 - { reg: '$rdi', virtual-reg: '%0' } 803 - { reg: '$rsi', virtual-reg: '%1' } 804 body: | 805 bb.0: 806 successors: %bb.1 807 liveins: $rdi, $rsi 808 809 %0:gr64 = COPY $rdi 810 %1:gr64 = COPY $rsi 811 CMP64rr %0, %1, implicit-def $eflags 812 ; CHECK: bb.0: 813 ; CHECK-NOT: COPY{{( killed)?}} $eflags 814 ; CHECK: CMP64rr %0, %1, implicit-def $eflags 815 ; CHECK-NOT: COPY{{( killed)?}} $eflags 816 JMP_1 %bb.1 817 818 bb.1: 819 successors: %bb.2, %bb.4 820 liveins: $eflags 821 822 ; Outer loop header, target for one set of hoisting. 823 JE_1 %bb.2, implicit $eflags 824 JMP_1 %bb.4 825 ; CHECK: bb.1: 826 ; CHECK-NOT: COPY{{( killed)?}} $eflags 827 ; CHECK: %[[A_REG:[^:]*]]:gr8 = SETAr implicit $eflags 828 ; CHECK-NEXT: %[[E_REG:[^:]*]]:gr8 = SETEr implicit $eflags 829 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETBr implicit $eflags 830 ; CHECK-NOT: COPY{{( killed)?}} $eflags 831 832 bb.2: 833 successors: %bb.2, %bb.3 834 liveins: $eflags 835 836 ; Inner loop with a local copy. We should eliminate this but can't hoist. 837 %2:gr64 = COPY $eflags 838 $eflags = COPY %2 839 JE_1 %bb.2, implicit $eflags 840 JMP_1 %bb.3 841 ; CHECK: bb.2: 842 ; CHECK-NOT: COPY{{( killed)?}} $eflags 843 ; CHECK: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags 844 ; CHECK-NEXT: JNE_1 %bb.2, implicit killed $eflags 845 ; CHECK-NOT: COPY{{( killed)?}} $eflags 846 847 bb.3: 848 successors: %bb.8 849 liveins: $eflags 850 851 ; Use and then clobber $eflags. Then hop to the outer loop latch. 852 %3:gr64 = ADC64ri32 %0, 42, implicit-def dead $eflags, implicit $eflags 853 ; CHECK: bb.3: 854 ; CHECK-NOT: COPY{{( killed)?}} $eflags 855 ; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri %[[B_REG]], 255, implicit-def $eflags 856 ; CHECK-NEXT: %3:gr64 = ADC64ri32 %0, 42, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags 857 ; CHECK-NOT: COPY{{( killed)?}} $eflags 858 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %3 859 JMP_1 %bb.8 860 861 bb.4: 862 successors: %bb.5, %bb.6 863 liveins: $eflags 864 865 ; Another inner loop, this one with a diamond. 866 JE_1 %bb.5, implicit $eflags 867 JMP_1 %bb.6 868 ; CHECK: bb.4: 869 ; CHECK-NOT: COPY{{( killed)?}} $eflags 870 ; CHECK: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags 871 ; CHECK-NEXT: JNE_1 %bb.5, implicit killed $eflags 872 ; CHECK-NOT: COPY{{( killed)?}} $eflags 873 874 bb.5: 875 successors: %bb.7 876 liveins: $eflags 877 878 ; Just use $eflags on this side of the diamond. 879 %4:gr64 = CMOVA64rr %0, %1, implicit $eflags 880 ; CHECK: bb.5: 881 ; CHECK-NOT: COPY{{( killed)?}} $eflags 882 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags 883 ; CHECK-NEXT: %4:gr64 = CMOVNE64rr %0, %1, implicit killed $eflags 884 ; CHECK-NOT: COPY{{( killed)?}} $eflags 885 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %4 886 JMP_1 %bb.7 887 888 bb.6: 889 successors: %bb.7 890 liveins: $eflags 891 892 ; Use, copy, and then use $eflags again. 893 %5:gr64 = CMOVA64rr %0, %1, implicit $eflags 894 ; CHECK: bb.6: 895 ; CHECK-NOT: COPY{{( killed)?}} $eflags 896 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags 897 ; CHECK-NEXT: %5:gr64 = CMOVNE64rr %0, %1, implicit killed $eflags 898 ; CHECK-NOT: COPY{{( killed)?}} $eflags 899 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5 900 901 %6:gr64 = COPY $eflags 902 $eflags = COPY %6:gr64 903 904 %7:gr64 = CMOVA64rr %0, %1, implicit $eflags 905 ; CHECK-NOT: COPY{{( killed)?}} $eflags 906 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags 907 ; CHECK-NEXT: %7:gr64 = CMOVNE64rr %0, %1, implicit killed $eflags 908 ; CHECK-NOT: COPY{{( killed)?}} $eflags 909 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %7 910 JMP_1 %bb.7 911 912 bb.7: 913 successors: %bb.4, %bb.8 914 liveins: $eflags 915 916 ; Inner loop latch. 917 JE_1 %bb.4, implicit $eflags 918 JMP_1 %bb.8 919 ; CHECK: bb.7: 920 ; CHECK-NOT: COPY{{( killed)?}} $eflags 921 ; CHECK: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags 922 ; CHECK-NEXT: JNE_1 %bb.4, implicit killed $eflags 923 ; CHECK-NOT: COPY{{( killed)?}} $eflags 924 925 bb.8: 926 successors: %bb.1, %bb.9 927 928 ; Outer loop latch. Note that we cannot have EFLAGS live-in here as that 929 ; immediately require PHIs. 930 CMP64rr %0, %1, implicit-def $eflags 931 JE_1 %bb.1, implicit $eflags 932 JMP_1 %bb.9 933 ; CHECK: bb.8: 934 ; CHECK-NOT: COPY{{( killed)?}} $eflags 935 ; CHECK: CMP64rr %0, %1, implicit-def $eflags 936 ; CHECK-NEXT: JE_1 %bb.1, implicit $eflags 937 ; CHECK-NOT: COPY{{( killed)?}} $eflags 938 939 bb.9: 940 liveins: $eflags 941 942 ; And we're done. 943 %8:gr64 = CMOVE64rr %0, %1, implicit killed $eflags 944 $rax = COPY %8 945 RET 0, $rax 946 ; CHECK: bb.9: 947 ; CHECK-NOT: $eflags 948 ; CHECK: %8:gr64 = CMOVE64rr %0, %1, implicit killed $eflags 949 950 ... 951 --- 952 name: test_existing_setcc 953 # CHECK-LABEL: name: test_existing_setcc 954 liveins: 955 - { reg: '$rdi', virtual-reg: '%0' } 956 - { reg: '$rsi', virtual-reg: '%1' } 957 body: | 958 bb.0: 959 successors: %bb.1, %bb.2, %bb.3 960 liveins: $rdi, $rsi 961 962 %0:gr64 = COPY $rdi 963 %1:gr64 = COPY $rsi 964 CMP64rr %0, %1, implicit-def $eflags 965 %2:gr8 = SETAr implicit $eflags 966 %3:gr8 = SETAEr implicit $eflags 967 %4:gr64 = COPY $eflags 968 ; CHECK: CMP64rr %0, %1, implicit-def $eflags 969 ; CHECK-NEXT: %[[A_REG:[^:]*]]:gr8 = SETAr implicit $eflags 970 ; CHECK-NEXT: %[[AE_REG:[^:]*]]:gr8 = SETAEr implicit $eflags 971 ; CHECK-NOT: COPY{{( killed)?}} $eflags 972 973 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 974 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax 975 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 976 977 $eflags = COPY %4 978 JA_1 %bb.1, implicit $eflags 979 JB_1 %bb.2, implicit $eflags 980 JMP_1 %bb.3 981 ; CHECK-NOT: $eflags = 982 ; 983 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags 984 ; CHECK-NEXT: JNE_1 %bb.1, implicit killed $eflags 985 ; CHECK-SAME: {{$[[:space:]]}} 986 ; CHECK-NEXT: bb.4: 987 ; CHECK-NEXT: successors: {{.*$}} 988 ; CHECK-SAME: {{$[[:space:]]}} 989 ; CHECK-NEXT: TEST8rr %[[AE_REG]], %[[AE_REG]], implicit-def $eflags 990 ; CHECK-NEXT: JE_1 %bb.2, implicit killed $eflags 991 ; CHECK-NEXT: JMP_1 %bb.3 992 993 bb.1: 994 %5:gr32 = MOV32ri64 42 995 $eax = COPY %5 996 RET 0, $eax 997 998 bb.2: 999 %6:gr32 = MOV32ri64 43 1000 $eax = COPY %6 1001 RET 0, $eax 1002 1003 bb.3: 1004 %7:gr32 = MOV32r0 implicit-def dead $eflags 1005 $eax = COPY %7 1006 RET 0, $eax 1007 1008 ... 1009 --- 1010 name: test_existing_setcc_memory 1011 # CHECK-LABEL: name: test_existing_setcc_memory 1012 liveins: 1013 - { reg: '$rdi', virtual-reg: '%0' } 1014 - { reg: '$rsi', virtual-reg: '%1' } 1015 body: | 1016 bb.0: 1017 successors: %bb.1, %bb.2 1018 liveins: $rdi, $rsi 1019 1020 %0:gr64 = COPY $rdi 1021 %1:gr64 = COPY $rsi 1022 CMP64rr %0, %1, implicit-def $eflags 1023 SETEm %0, 1, $noreg, -16, $noreg, implicit $eflags 1024 %2:gr64 = COPY $eflags 1025 ; CHECK: CMP64rr %0, %1, implicit-def $eflags 1026 ; We cannot reuse this SETE because it stores the flag directly to memory, 1027 ; so we have two SETEs here. FIXME: It'd be great if something could fold 1028 ; these automatically. If not, maybe we want to unfold SETcc instructions 1029 ; writing to memory so we can reuse them. 1030 ; CHECK-NEXT: SETEm {{.*}} implicit $eflags 1031 ; CHECK-NEXT: %[[E_REG:[^:]*]]:gr8 = SETEr implicit $eflags 1032 ; CHECK-NOT: COPY{{( killed)?}} $eflags 1033 1034 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 1035 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax 1036 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 1037 1038 $eflags = COPY %2 1039 JE_1 %bb.1, implicit $eflags 1040 JMP_1 %bb.2 1041 ; CHECK-NOT: $eflags = 1042 ; 1043 ; CHECK: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags 1044 ; CHECK-NEXT: JNE_1 %bb.1, implicit killed $eflags 1045 ; CHECK-NEXT: JMP_1 %bb.2 1046 1047 bb.1: 1048 %3:gr32 = MOV32ri64 42 1049 $eax = COPY %3 1050 RET 0, $eax 1051 1052 bb.2: 1053 %4:gr32 = MOV32ri64 43 1054 $eax = COPY %4 1055 RET 0, $eax 1056 1057 ... 1058