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--- 107name: test_branch 108# CHECK-LABEL: name: test_branch 109liveins: 110 - { reg: '$rdi', virtual-reg: '%0' } 111 - { reg: '$rsi', virtual-reg: '%1' } 112body: | 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 = SETCCr 7, implicit $eflags 123 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, 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 JCC_1 %bb.1, 7, implicit $eflags 132 JCC_1 %bb.2, 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: JCC_1 %bb.1, 5, 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: JCC_1 %bb.2, 5, implicit killed $eflags 144 ; CHECK-NEXT: JMP_1 %bb.3 145 146 bb.1: 147 %3:gr32 = MOV32ri 42 148 $eax = COPY %3 149 RET 0, $eax 150 151 bb.2: 152 %4:gr32 = MOV32ri 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--- 163name: test_branch_fallthrough 164# CHECK-LABEL: name: test_branch_fallthrough 165liveins: 166 - { reg: '$rdi', virtual-reg: '%0' } 167 - { reg: '$rsi', virtual-reg: '%1' } 168body: | 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 = SETCCr 7, implicit $eflags 179 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, 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 JCC_1 %bb.2, 7, implicit $eflags 188 JCC_1 %bb.3, 2, implicit $eflags 189 ; CHECK-NOT: $eflags = 190 ; 191 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags 192 ; CHECK-NEXT: JCC_1 %bb.2, 5, 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: JCC_1 %bb.3, 5, 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 = MOV32ri 42 209 $eax = COPY %3 210 RET 0, $eax 211 212 bb.3: 213 %4:gr32 = MOV32ri 43 214 $eax = COPY %4 215 RET 0, $eax 216 217... 218--- 219name: test_setcc 220# CHECK-LABEL: name: test_setcc 221liveins: 222 - { reg: '$rdi', virtual-reg: '%0' } 223 - { reg: '$rsi', virtual-reg: '%1' } 224body: | 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 = SETCCr 7, implicit $eflags 234 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags 235 ; CHECK-NEXT: %[[E_REG:[^:]*]]:gr8 = SETCCr 4, implicit $eflags 236 ; CHECK-NEXT: %[[NE_REG:[^:]*]]:gr8 = SETCCr 5, 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 = SETCCr 7, implicit $eflags 245 %4:gr8 = SETCCr 2, implicit $eflags 246 %5:gr8 = SETCCr 4, implicit $eflags 247 SETCCm $rsp, 1, $noreg, -16, $noreg, 5, 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--- 262name: test_cmov 263# CHECK-LABEL: name: test_cmov 264liveins: 265 - { reg: '$rdi', virtual-reg: '%0' } 266 - { reg: '$rsi', virtual-reg: '%1' } 267body: | 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 = SETCCr 7, implicit $eflags 277 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags 278 ; CHECK-NEXT: %[[E_REG:[^:]*]]:gr8 = SETCCr 4, 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 = CMOV64rr %0, %1, 7, implicit $eflags 287 %4:gr64 = CMOV64rr %0, %1, 2, implicit $eflags 288 %5:gr64 = CMOV64rr %0, %1, 4, implicit $eflags 289 %6:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags 290 ; CHECK-NOT: $eflags = 291 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags 292 ; CHECK-NEXT: %3:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags 293 ; CHECK-NEXT: TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags 294 ; CHECK-NEXT: %4:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags 295 ; CHECK-NEXT: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags 296 ; CHECK-NEXT: %5:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags 297 ; CHECK-NEXT: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags 298 ; CHECK-NEXT: %6:gr64 = CMOV64rr %0, %1, 4, 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--- 308name: test_adc 309# CHECK-LABEL: name: test_adc 310liveins: 311 - { reg: '$rdi', virtual-reg: '%0' } 312 - { reg: '$rsi', virtual-reg: '%1' } 313body: | 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 = SETCCr 2, 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--- 342name: test_sbb 343# CHECK-LABEL: name: test_sbb 344liveins: 345 - { reg: '$rdi', virtual-reg: '%0' } 346 - { reg: '$rsi', virtual-reg: '%1' } 347body: | 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 = SETCCr 2, 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--- 376name: test_adcx 377# CHECK-LABEL: name: test_adcx 378liveins: 379 - { reg: '$rdi', virtual-reg: '%0' } 380 - { reg: '$rsi', virtual-reg: '%1' } 381body: | 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 = SETCCr 4, implicit $eflags 391 ; CHECK-NEXT: %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, 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 = CMOV64rr %0, %1, 4, 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 = CMOV64rr %0, %1, 5, 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--- 415name: test_adox 416# CHECK-LABEL: name: test_adox 417liveins: 418 - { reg: '$rdi', virtual-reg: '%0' } 419 - { reg: '$rsi', virtual-reg: '%1' } 420body: | 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 = SETCCr 4, implicit $eflags 430 ; CHECK-NEXT: %[[OF_REG:[^:]*]]:gr8 = SETCCr 0, 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 = CMOV64rr %0, %1, 4, 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 = CMOV64rr %0, %1, 5, 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--- 454name: test_rcl 455# CHECK-LABEL: name: test_rcl 456liveins: 457 - { reg: '$rdi', virtual-reg: '%0' } 458 - { reg: '$rsi', virtual-reg: '%1' } 459body: | 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 = SETCCr 2, 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--- 488name: test_rcr 489# CHECK-LABEL: name: test_rcr 490liveins: 491 - { reg: '$rdi', virtual-reg: '%0' } 492 - { reg: '$rsi', virtual-reg: '%1' } 493body: | 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 = SETCCr 2, 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--- 522name: test_setb_c 523# CHECK-LABEL: name: test_setb_c 524liveins: 525 - { reg: '$rdi', virtual-reg: '%0' } 526 - { reg: '$rsi', virtual-reg: '%1' } 527body: | 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 = SETCCr 2, 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:gr32 = SETB_C32r implicit-def $eflags, implicit $eflags 545 MOV32mr $rsp, 1, $noreg, -16, $noreg, killed %4 546 ; CHECK-NOT: $eflags = 547 ; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags 548 ; CHECK-NEXT: %[[SETB:[^:]*]]:gr32 = SETB_C32r implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags 549 ; CHECK-NEXT: MOV32mr $rsp, 1, $noreg, -16, $noreg, killed %[[SETB]] 550 551 $eflags = COPY %3 552 %5:gr64 = SETB_C64r implicit-def $eflags, implicit $eflags 553 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5 554 ; CHECK-NOT: $eflags = 555 ; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags 556 ; CHECK-NEXT: %[[SETB:[^:]*]]:gr64 = SETB_C64r implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags 557 ; CHECK-NEXT: MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %[[SETB]] 558 559 RET 0 560 561... 562--- 563name: test_branch_with_livein_and_kill 564# CHECK-LABEL: name: test_branch_with_livein_and_kill 565liveins: 566 - { reg: '$rdi', virtual-reg: '%0' } 567 - { reg: '$rsi', virtual-reg: '%1' } 568body: | 569 bb.0: 570 successors: %bb.1, %bb.2, %bb.3 571 liveins: $rdi, $rsi 572 573 %0:gr64 = COPY $rdi 574 %1:gr64 = COPY $rsi 575 CMP64rr %0, %1, implicit-def $eflags 576 %2:gr64 = COPY $eflags 577 ; CHECK-NOT: COPY{{( killed)?}} $eflags 578 ; CHECK: %[[S_REG:[^:]*]]:gr8 = SETCCr 8, implicit $eflags 579 ; CHECK-NEXT: %[[NE_REG:[^:]*]]:gr8 = SETCCr 5, implicit $eflags 580 ; CHECK-NEXT: %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags 581 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags 582 ; CHECK-NOT: COPY{{( killed)?}} $eflags 583 584 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 585 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax 586 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 587 588 $eflags = COPY %2 589 JCC_1 %bb.1, 7, implicit $eflags 590 JCC_1 %bb.2, 2, implicit $eflags 591 JMP_1 %bb.3 592 ; CHECK-NOT: $eflags = 593 ; 594 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags 595 ; CHECK-NEXT: JCC_1 %bb.1, 5, implicit killed $eflags 596 ; CHECK-SAME: {{$[[:space:]]}} 597 ; CHECK-NEXT: bb.4: 598 ; CHECK-NEXT: successors: {{.*$}} 599 ; CHECK-SAME: {{$[[:space:]]}} 600 ; CHECK-NEXT: TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags 601 ; CHECK-NEXT: JCC_1 %bb.2, 5, implicit killed $eflags 602 ; CHECK-NEXT: JMP_1 %bb.3 603 604 bb.1: 605 liveins: $eflags 606 607 %3:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags 608 ; CHECK-NOT: $eflags = 609 ; CHECK: TEST8rr %[[NE_REG]], %[[NE_REG]], implicit-def $eflags 610 ; CHECK-NEXT: %3:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags 611 $rax = COPY %3 612 RET 0, $rax 613 614 bb.2: 615 liveins: $eflags 616 617 %4:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags 618 ; CHECK-NOT: $eflags = 619 ; CHECK: TEST8rr %[[NE_REG]], %[[NE_REG]], implicit-def $eflags 620 ; CHECK-NEXT: %4:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags 621 $rax = COPY %4 622 RET 0, $rax 623 624 bb.3: 625 liveins: $eflags 626 627 %5:gr64 = CMOV64rr %0, %1, 8, implicit killed $eflags 628 ; CHECK-NOT: $eflags = 629 ; CHECK: TEST8rr %[[S_REG]], %[[S_REG]], implicit-def $eflags 630 ; CHECK-NEXT: %5:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags 631 $rax = COPY %5 632 RET 0, $rax 633 634... 635--- 636name: test_branch_with_interleaved_livein_and_kill 637# CHECK-LABEL: name: test_branch_with_interleaved_livein_and_kill 638liveins: 639 - { reg: '$rdi', virtual-reg: '%0' } 640 - { reg: '$rsi', virtual-reg: '%1' } 641body: | 642 bb.0: 643 successors: %bb.1, %bb.2, %bb.5 644 liveins: $rdi, $rsi 645 646 %0:gr64 = COPY $rdi 647 %1:gr64 = COPY $rsi 648 CMP64rr %0, %1, implicit-def $eflags 649 %2:gr64 = COPY $eflags 650 ; CHECK-NOT: COPY{{( killed)?}} $eflags 651 ; CHECK: %[[S_REG:[^:]*]]:gr8 = SETCCr 8, implicit $eflags 652 ; CHECK-NEXT: %[[P_REG:[^:]*]]:gr8 = SETCCr 10, implicit $eflags 653 ; CHECK-NEXT: %[[NE_REG:[^:]*]]:gr8 = SETCCr 5, implicit $eflags 654 ; CHECK-NEXT: %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags 655 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags 656 ; CHECK-NEXT: %[[O_REG:[^:]*]]:gr8 = SETCCr 0, implicit $eflags 657 ; CHECK-NOT: COPY{{( killed)?}} $eflags 658 659 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 660 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax 661 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 662 663 $eflags = COPY %2 664 JCC_1 %bb.1, 7, implicit $eflags 665 JCC_1 %bb.2, 2, implicit $eflags 666 JMP_1 %bb.5 667 ; CHECK-NOT: $eflags = 668 ; 669 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags 670 ; CHECK-NEXT: JCC_1 %bb.1, 5, implicit killed $eflags 671 ; CHECK-SAME: {{$[[:space:]]}} 672 ; CHECK-NEXT: bb.6: 673 ; CHECK-NEXT: successors: {{.*$}} 674 ; CHECK-SAME: {{$[[:space:]]}} 675 ; CHECK-NEXT: TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags 676 ; CHECK-NEXT: JCC_1 %bb.2, 5, implicit killed $eflags 677 ; CHECK-NEXT: JMP_1 %bb.5 678 679 bb.1: 680 liveins: $eflags 681 682 %3:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags 683 ; CHECK-NOT: $eflags = 684 ; CHECK: TEST8rr %[[NE_REG]], %[[NE_REG]], implicit-def $eflags 685 ; CHECK-NEXT: %3:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags 686 $rax = COPY %3 687 RET 0, $rax 688 689 bb.2: 690 ; The goal is to have another batch of successors discovered in a block 691 ; between two successors which kill $eflags. This ensures that neither of 692 ; the surrounding kills impact recursing through this block. 693 successors: %bb.3, %bb.4 694 liveins: $eflags 695 696 JCC_1 %bb.3, 0, implicit $eflags 697 JMP_1 %bb.4 698 ; CHECK-NOT: $eflags = 699 ; 700 ; CHECK: TEST8rr %[[O_REG]], %[[O_REG]], implicit-def $eflags 701 ; CHECK-NEXT: JCC_1 %bb.3, 5, implicit killed $eflags 702 ; CHECK-NEXT: JMP_1 %bb.4 703 704 bb.3: 705 liveins: $eflags 706 707 %4:gr64 = CMOV64rr %0, %1, 5, implicit $eflags 708 ; CHECK-NOT: $eflags = 709 ; CHECK: TEST8rr %[[NE_REG]], %[[NE_REG]], implicit-def $eflags 710 ; CHECK-NEXT: %4:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags 711 $rax = COPY %4 712 RET 0, $rax 713 714 bb.4: 715 liveins: $eflags 716 717 %5:gr64 = CMOV64rr %0, %1, 10, implicit $eflags 718 ; CHECK-NOT: $eflags = 719 ; CHECK: TEST8rr %[[P_REG]], %[[P_REG]], implicit-def $eflags 720 ; CHECK-NEXT: %5:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags 721 $rax = COPY %5 722 RET 0, $rax 723 724 bb.5: 725 liveins: $eflags 726 727 %6:gr64 = CMOV64rr %0, %1, 8, implicit killed $eflags 728 ; CHECK-NOT: $eflags = 729 ; CHECK: TEST8rr %[[S_REG]], %[[S_REG]], implicit-def $eflags 730 ; CHECK-NEXT: %6:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags 731 $rax = COPY %6 732 RET 0, $rax 733 734... 735--- 736# This test case is designed to exercise a particularly challenging situation: 737# when the flags are copied and restored *inside* of a complex and cyclic CFG 738# all of which have live-in flags. To correctly handle this case we have to walk 739# up the dominator tree and locate a viable reaching definition location, 740# checking for clobbers along any path. The CFG for this function looks like the 741# following diagram, control flowing out the bottom of blocks and in the top: 742# 743# bb.0 744# | __________________ 745# |/ \ 746# bb.1 | 747# |\_________ | 748# | __ \ ____ | 749# |/ \ |/ \ | 750# bb.2 | bb.4 | | 751# |\__/ / \ | | 752# | / \ | | 753# bb.3 bb.5 bb.6 | | 754# | \ / | | 755# | \ / | | 756# | bb.7 | | 757# | ________/ \____/ | 758# |/ | 759# bb.8 | 760# |\__________________/ 761# | 762# bb.9 763# 764# We set EFLAGS in bb.0, clobber them in bb.3, and copy them in bb.2 and bb.6. 765# Because of the cycles this requires hoisting the `SETcc` instructions to 766# capture the flags for the bb.6 copy to bb.1 and using them for the copy in 767# `bb.2` as well despite the clobber in `bb.3`. The clobber in `bb.3` also 768# prevents hoisting the `SETcc`s up to `bb.0`. 769# 770# Throughout the test we use branch instructions that are totally bogus (as the 771# flags are obviously not changing!) but this is just to allow us to send 772# a small but complex CFG structure through the backend and force it to choose 773# plausible lowering decisions based on the core CFG presented, regardless of 774# the futility of the actual branches. 775name: test_mid_cycle_copies 776# CHECK-LABEL: name: test_mid_cycle_copies 777liveins: 778 - { reg: '$rdi', virtual-reg: '%0' } 779 - { reg: '$rsi', virtual-reg: '%1' } 780body: | 781 bb.0: 782 successors: %bb.1 783 liveins: $rdi, $rsi 784 785 %0:gr64 = COPY $rdi 786 %1:gr64 = COPY $rsi 787 CMP64rr %0, %1, implicit-def $eflags 788 ; CHECK: bb.0: 789 ; CHECK-NOT: COPY{{( killed)?}} $eflags 790 ; CHECK: CMP64rr %0, %1, implicit-def $eflags 791 ; CHECK-NOT: COPY{{( killed)?}} $eflags 792 JMP_1 %bb.1 793 794 bb.1: 795 successors: %bb.2, %bb.4 796 liveins: $eflags 797 798 ; Outer loop header, target for one set of hoisting. 799 JCC_1 %bb.2, 4, implicit $eflags 800 JMP_1 %bb.4 801 ; CHECK: bb.1: 802 ; CHECK-NOT: COPY{{( killed)?}} $eflags 803 ; CHECK: %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags 804 ; CHECK-NEXT: %[[E_REG:[^:]*]]:gr8 = SETCCr 4, implicit $eflags 805 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags 806 ; CHECK-NOT: COPY{{( killed)?}} $eflags 807 808 bb.2: 809 successors: %bb.2, %bb.3 810 liveins: $eflags 811 812 ; Inner loop with a local copy. We should eliminate this but can't hoist. 813 %2:gr64 = COPY $eflags 814 $eflags = COPY %2 815 JCC_1 %bb.2, 4, implicit $eflags 816 JMP_1 %bb.3 817 ; CHECK: bb.2: 818 ; CHECK-NOT: COPY{{( killed)?}} $eflags 819 ; CHECK: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags 820 ; CHECK-NEXT: JCC_1 %bb.2, 5, implicit killed $eflags 821 ; CHECK-NOT: COPY{{( killed)?}} $eflags 822 823 bb.3: 824 successors: %bb.8 825 liveins: $eflags 826 827 ; Use and then clobber $eflags. Then hop to the outer loop latch. 828 %3:gr64 = ADC64ri32 %0, 42, implicit-def dead $eflags, implicit $eflags 829 ; CHECK: bb.3: 830 ; CHECK-NOT: COPY{{( killed)?}} $eflags 831 ; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri %[[B_REG]], 255, implicit-def $eflags 832 ; CHECK-NEXT: %3:gr64 = ADC64ri32 %0, 42, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags 833 ; CHECK-NOT: COPY{{( killed)?}} $eflags 834 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %3 835 JMP_1 %bb.8 836 837 bb.4: 838 successors: %bb.5, %bb.6 839 liveins: $eflags 840 841 ; Another inner loop, this one with a diamond. 842 JCC_1 %bb.5, 4, implicit $eflags 843 JMP_1 %bb.6 844 ; CHECK: bb.4: 845 ; CHECK-NOT: COPY{{( killed)?}} $eflags 846 ; CHECK: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags 847 ; CHECK-NEXT: JCC_1 %bb.5, 5, implicit killed $eflags 848 ; CHECK-NOT: COPY{{( killed)?}} $eflags 849 850 bb.5: 851 successors: %bb.7 852 liveins: $eflags 853 854 ; Just use $eflags on this side of the diamond. 855 %4:gr64 = CMOV64rr %0, %1, 7, implicit $eflags 856 ; CHECK: bb.5: 857 ; CHECK-NOT: COPY{{( killed)?}} $eflags 858 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags 859 ; CHECK-NEXT: %4:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags 860 ; CHECK-NOT: COPY{{( killed)?}} $eflags 861 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %4 862 JMP_1 %bb.7 863 864 bb.6: 865 successors: %bb.7 866 liveins: $eflags 867 868 ; Use, copy, and then use $eflags again. 869 %5:gr64 = CMOV64rr %0, %1, 7, implicit $eflags 870 ; CHECK: bb.6: 871 ; CHECK-NOT: COPY{{( killed)?}} $eflags 872 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags 873 ; CHECK-NEXT: %5:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags 874 ; CHECK-NOT: COPY{{( killed)?}} $eflags 875 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5 876 877 %6:gr64 = COPY $eflags 878 $eflags = COPY %6:gr64 879 880 %7:gr64 = CMOV64rr %0, %1, 7, implicit $eflags 881 ; CHECK-NOT: COPY{{( killed)?}} $eflags 882 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags 883 ; CHECK-NEXT: %7:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags 884 ; CHECK-NOT: COPY{{( killed)?}} $eflags 885 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %7 886 JMP_1 %bb.7 887 888 bb.7: 889 successors: %bb.4, %bb.8 890 liveins: $eflags 891 892 ; Inner loop latch. 893 JCC_1 %bb.4, 4, implicit $eflags 894 JMP_1 %bb.8 895 ; CHECK: bb.7: 896 ; CHECK-NOT: COPY{{( killed)?}} $eflags 897 ; CHECK: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags 898 ; CHECK-NEXT: JCC_1 %bb.4, 5, implicit killed $eflags 899 ; CHECK-NOT: COPY{{( killed)?}} $eflags 900 901 bb.8: 902 successors: %bb.1, %bb.9 903 904 ; Outer loop latch. Note that we cannot have EFLAGS live-in here as that 905 ; immediately require PHIs. 906 CMP64rr %0, %1, implicit-def $eflags 907 JCC_1 %bb.1, 4, implicit $eflags 908 JMP_1 %bb.9 909 ; CHECK: bb.8: 910 ; CHECK-NOT: COPY{{( killed)?}} $eflags 911 ; CHECK: CMP64rr %0, %1, implicit-def $eflags 912 ; CHECK-NEXT: JCC_1 %bb.1, 4, implicit $eflags 913 ; CHECK-NOT: COPY{{( killed)?}} $eflags 914 915 bb.9: 916 liveins: $eflags 917 918 ; And we're done. 919 %8:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags 920 $rax = COPY %8 921 RET 0, $rax 922 ; CHECK: bb.9: 923 ; CHECK-NOT: $eflags 924 ; CHECK: %8:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags 925 926... 927--- 928name: test_existing_setcc 929# CHECK-LABEL: name: test_existing_setcc 930liveins: 931 - { reg: '$rdi', virtual-reg: '%0' } 932 - { reg: '$rsi', virtual-reg: '%1' } 933body: | 934 bb.0: 935 successors: %bb.1, %bb.2, %bb.3 936 liveins: $rdi, $rsi 937 938 %0:gr64 = COPY $rdi 939 %1:gr64 = COPY $rsi 940 CMP64rr %0, %1, implicit-def $eflags 941 %2:gr8 = SETCCr 7, implicit $eflags 942 %3:gr8 = SETCCr 3, implicit $eflags 943 %4:gr64 = COPY $eflags 944 ; CHECK: CMP64rr %0, %1, implicit-def $eflags 945 ; CHECK-NEXT: %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags 946 ; CHECK-NEXT: %[[AE_REG:[^:]*]]:gr8 = SETCCr 3, implicit $eflags 947 ; CHECK-NOT: COPY{{( killed)?}} $eflags 948 949 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 950 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax 951 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 952 953 $eflags = COPY %4 954 JCC_1 %bb.1, 7, implicit $eflags 955 JCC_1 %bb.2, 2, implicit $eflags 956 JMP_1 %bb.3 957 ; CHECK-NOT: $eflags = 958 ; 959 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags 960 ; CHECK-NEXT: JCC_1 %bb.1, 5, implicit killed $eflags 961 ; CHECK-SAME: {{$[[:space:]]}} 962 ; CHECK-NEXT: bb.4: 963 ; CHECK-NEXT: successors: {{.*$}} 964 ; CHECK-SAME: {{$[[:space:]]}} 965 ; CHECK-NEXT: TEST8rr %[[AE_REG]], %[[AE_REG]], implicit-def $eflags 966 ; CHECK-NEXT: JCC_1 %bb.2, 4, implicit killed $eflags 967 ; CHECK-NEXT: JMP_1 %bb.3 968 969 bb.1: 970 %5:gr32 = MOV32ri 42 971 $eax = COPY %5 972 RET 0, $eax 973 974 bb.2: 975 %6:gr32 = MOV32ri 43 976 $eax = COPY %6 977 RET 0, $eax 978 979 bb.3: 980 %7:gr32 = MOV32r0 implicit-def dead $eflags 981 $eax = COPY %7 982 RET 0, $eax 983 984... 985--- 986name: test_existing_setcc_memory 987# CHECK-LABEL: name: test_existing_setcc_memory 988liveins: 989 - { reg: '$rdi', virtual-reg: '%0' } 990 - { reg: '$rsi', virtual-reg: '%1' } 991body: | 992 bb.0: 993 successors: %bb.1, %bb.2 994 liveins: $rdi, $rsi 995 996 %0:gr64 = COPY $rdi 997 %1:gr64 = COPY $rsi 998 CMP64rr %0, %1, implicit-def $eflags 999 SETCCm %0, 1, $noreg, -16, $noreg, 4, implicit $eflags 1000 %2:gr64 = COPY $eflags 1001 ; CHECK: CMP64rr %0, %1, implicit-def $eflags 1002 ; We cannot reuse this SETE because it stores the flag directly to memory, 1003 ; so we have two SETEs here. FIXME: It'd be great if something could fold 1004 ; these automatically. If not, maybe we want to unfold SETcc instructions 1005 ; writing to memory so we can reuse them. 1006 ; CHECK-NEXT: SETCCm {{.*}} 4, implicit $eflags 1007 ; CHECK-NEXT: %[[E_REG:[^:]*]]:gr8 = SETCCr 4, implicit $eflags 1008 ; CHECK-NOT: COPY{{( killed)?}} $eflags 1009 1010 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 1011 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax 1012 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp 1013 1014 $eflags = COPY %2 1015 JCC_1 %bb.1, 4, implicit $eflags 1016 JMP_1 %bb.2 1017 ; CHECK-NOT: $eflags = 1018 ; 1019 ; CHECK: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags 1020 ; CHECK-NEXT: JCC_1 %bb.1, 5, implicit killed $eflags 1021 ; CHECK-NEXT: JMP_1 %bb.2 1022 1023 bb.1: 1024 %3:gr32 = MOV32ri 42 1025 $eax = COPY %3 1026 RET 0, $eax 1027 1028 bb.2: 1029 %4:gr32 = MOV32ri 43 1030 $eax = COPY %4 1031 RET 0, $eax 1032 1033... 1034