371 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py2; FIXME(ndesaulniers): get this test to pass with -verify-machineinstrs3; enabled. https://github.com/llvm/llvm-project/issues/608274; RUN: llc -mtriple=x86_64-linux-gnu %s -o - -stop-after=finalize-isel \5; RUN: -verify-machineinstrs=0 -start-before=x86-isel | FileCheck %s6 7; One virtual register, w/o phi8define i32 @test0() {9 ; CHECK-LABEL: name: test010 ; CHECK: bb.0 (%ir-block.0):11 ; CHECK-NEXT: successors: %bb.1(0x80000000), %bb.2(0x00000000)12 ; CHECK-NEXT: {{ $}}13 ; CHECK-NEXT: INLINEASM_BR &"", 0 /* attdialect */, 2686986 /* regdef:GR32_NOREX2 */, def %1, 13 /* imm */, %bb.214 ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY %115 ; CHECK-NEXT: JMP_1 %bb.116 ; CHECK-NEXT: {{ $}}17 ; CHECK-NEXT: bb.1.cleanup:18 ; CHECK-NEXT: [[MOV32ri:%[0-9]+]]:gr32 = MOV32ri 4219 ; CHECK-NEXT: $eax = COPY [[MOV32ri]]20 ; CHECK-NEXT: RET 0, $eax21 ; CHECK-NEXT: {{ $}}22 ; CHECK-NEXT: bb.2.z.split (inlineasm-br-indirect-target):23 ; CHECK-NEXT: $eax = COPY %124 ; CHECK-NEXT: RET 0, $eax25 %direct = callbr i32 asm "", "=r,!i"()26 to label %cleanup [label %z.split]27 28cleanup:29 ret i32 4230z.split:31 %indirect = call i32 @llvm.callbr.landingpad.i32(i32 %direct)32 ret i32 %indirect33}34 35; One virtual register, w/ phi36define i32 @test1() {37 ; CHECK-LABEL: name: test138 ; CHECK: bb.0.entry:39 ; CHECK-NEXT: successors: %bb.2(0x80000000), %bb.1(0x00000000)40 ; CHECK-NEXT: {{ $}}41 ; CHECK-NEXT: [[MOV32ri:%[0-9]+]]:gr32 = MOV32ri 4242 ; CHECK-NEXT: INLINEASM_BR &"", 0 /* attdialect */, 2686986 /* regdef:GR32_NOREX2 */, def %4, 13 /* imm */, %bb.143 ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY %444 ; CHECK-NEXT: JMP_1 %bb.245 ; CHECK-NEXT: {{ $}}46 ; CHECK-NEXT: bb.1.z.split (inlineasm-br-indirect-target):47 ; CHECK-NEXT: successors: %bb.2(0x80000000)48 ; CHECK-NEXT: {{ $}}49 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr32 = COPY %450 ; CHECK-NEXT: {{ $}}51 ; CHECK-NEXT: bb.2.cleanup:52 ; CHECK-NEXT: [[PHI:%[0-9]+]]:gr32 = PHI [[MOV32ri]], %bb.0, [[COPY1]], %bb.153 ; CHECK-NEXT: $eax = COPY [[PHI]]54 ; CHECK-NEXT: RET 0, $eax55entry:56 %direct = callbr i32 asm "", "=r,!i"()57 to label %cleanup [label %z.split]58 59z.split:60 %indirect = call i32 @llvm.callbr.landingpad.i32(i32 %direct)61 br label %cleanup62 63cleanup:64 %retval.0 = phi i32 [ %indirect, %z.split ], [ 42, %entry ]65 ret i32 %retval.066}67 68; Two virtual registers69define i32 @test2() {70 ; CHECK-LABEL: name: test271 ; CHECK: bb.0.entry:72 ; CHECK-NEXT: successors: %bb.2(0x80000000), %bb.1(0x00000000)73 ; CHECK-NEXT: {{ $}}74 ; CHECK-NEXT: [[MOV32ri:%[0-9]+]]:gr32 = MOV32ri 4275 ; CHECK-NEXT: INLINEASM_BR &"", 0 /* attdialect */, 2686986 /* regdef:GR32_NOREX2 */, def %5, 2686986 /* regdef:GR32_NOREX2 */, def %6, 13 /* imm */, %bb.176 ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY %677 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr32 = COPY %578 ; CHECK-NEXT: JMP_1 %bb.279 ; CHECK-NEXT: {{ $}}80 ; CHECK-NEXT: bb.1.z.split (inlineasm-br-indirect-target):81 ; CHECK-NEXT: successors: %bb.2(0x80000000)82 ; CHECK-NEXT: {{ $}}83 ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gr32 = COPY %584 ; CHECK-NEXT: {{ $}}85 ; CHECK-NEXT: bb.2.cleanup:86 ; CHECK-NEXT: [[PHI:%[0-9]+]]:gr32 = PHI [[MOV32ri]], %bb.0, [[COPY2]], %bb.187 ; CHECK-NEXT: $eax = COPY [[PHI]]88 ; CHECK-NEXT: RET 0, $eax89entry:90 %direct = callbr { i32, i32 } asm "", "=r,=r,!i"()91 to label %cleanup [label %z.split]92 93z.split:94 %indirect = call { i32, i32 } @llvm.callbr.landingpad.sl_i32i32s({ i32, i32 } %direct)95 %asmresult2 = extractvalue { i32, i32 } %indirect, 096 br label %cleanup97 98cleanup:99 %retval.0 = phi i32 [ %asmresult2, %z.split ], [ 42, %entry ]100 ret i32 %retval.0101}102 103; One physical register104define i32 @test3() {105 ; CHECK-LABEL: name: test3106 ; CHECK: bb.0.entry:107 ; CHECK-NEXT: successors: %bb.2(0x80000000), %bb.1(0x00000000)108 ; CHECK-NEXT: {{ $}}109 ; CHECK-NEXT: [[MOV32ri:%[0-9]+]]:gr32 = MOV32ri 42110 ; CHECK-NEXT: INLINEASM_BR &"", 0 /* attdialect */, 10 /* regdef */, implicit-def $ebx, 13 /* imm */, %bb.1111 ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY $ebx112 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr32 = COPY [[COPY]]113 ; CHECK-NEXT: JMP_1 %bb.2114 ; CHECK-NEXT: {{ $}}115 ; CHECK-NEXT: bb.1.z.split (inlineasm-br-indirect-target):116 ; CHECK-NEXT: successors: %bb.2(0x80000000)117 ; CHECK-NEXT: liveins: $ebx118 ; CHECK-NEXT: {{ $}}119 ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gr32 = COPY $ebx120 ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gr32 = COPY [[COPY2]]121 ; CHECK-NEXT: {{ $}}122 ; CHECK-NEXT: bb.2.cleanup:123 ; CHECK-NEXT: [[PHI:%[0-9]+]]:gr32 = PHI [[MOV32ri]], %bb.0, [[COPY3]], %bb.1124 ; CHECK-NEXT: $eax = COPY [[PHI]]125 ; CHECK-NEXT: RET 0, $eax126entry:127 %direct = callbr i32 asm "", "={bx},!i"()128 to label %cleanup [label %z.split]129 130z.split:131 %indirect = call i32 @llvm.callbr.landingpad.i32(i32 %direct)132 br label %cleanup133 134cleanup:135 %retval.0 = phi i32 [ %indirect, %z.split ], [ 42, %entry ]136 ret i32 %retval.0137}138 139; Two physical registers140define i32 @test4() {141 ; CHECK-LABEL: name: test4142 ; CHECK: bb.0.entry:143 ; CHECK-NEXT: successors: %bb.2(0x80000000), %bb.1(0x00000000)144 ; CHECK-NEXT: {{ $}}145 ; CHECK-NEXT: [[MOV32ri:%[0-9]+]]:gr32 = MOV32ri 42146 ; CHECK-NEXT: INLINEASM_BR &"", 0 /* attdialect */, 10 /* regdef */, implicit-def $ebx, 10 /* regdef */, implicit-def $edx, 13 /* imm */, %bb.1147 ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY $ebx148 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr32 = COPY $edx149 ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gr32 = COPY [[COPY1]]150 ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gr32 = COPY [[COPY]]151 ; CHECK-NEXT: JMP_1 %bb.2152 ; CHECK-NEXT: {{ $}}153 ; CHECK-NEXT: bb.1.z.split (inlineasm-br-indirect-target):154 ; CHECK-NEXT: successors: %bb.2(0x80000000)155 ; CHECK-NEXT: liveins: $ebx, $edx156 ; CHECK-NEXT: {{ $}}157 ; CHECK-NEXT: [[COPY4:%[0-9]+]]:gr32 = COPY $ebx158 ; CHECK-NEXT: [[COPY5:%[0-9]+]]:gr32 = COPY [[COPY4]]159 ; CHECK-NEXT: {{ $}}160 ; CHECK-NEXT: bb.2.cleanup:161 ; CHECK-NEXT: [[PHI:%[0-9]+]]:gr32 = PHI [[MOV32ri]], %bb.0, [[COPY5]], %bb.1162 ; CHECK-NEXT: $eax = COPY [[PHI]]163 ; CHECK-NEXT: RET 0, $eax164entry:165 %direct = callbr { i32, i32 } asm "", "={bx},={dx},!i"()166 to label %cleanup [label %z.split]167 168z.split:169 %indirect = call { i32, i32 } @llvm.callbr.landingpad.sl_i32i32s({ i32, i32 } %direct)170 %asmresult2 = extractvalue { i32, i32 } %indirect, 0171 br label %cleanup172 173cleanup:174 %retval.0 = phi i32 [ %asmresult2, %z.split ], [ 42, %entry ]175 ret i32 %retval.0176}177 178; Test the same destination appearing in the direct/fallthrough branch as the179; indirect branch. Physreg.180define i32 @test5() {181 ; CHECK-LABEL: name: test5182 ; CHECK: bb.0.entry:183 ; CHECK-NEXT: successors: %bb.1(0x80000000)184 ; CHECK-NEXT: {{ $}}185 ; CHECK-NEXT: INLINEASM_BR &"# $0", 0 /* attdialect */, 10 /* regdef */, implicit-def $ebx, 13 /* imm */, %bb.1186 ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY $ebx187 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr32 = COPY [[COPY]]188 ; CHECK-NEXT: JMP_1 %bb.1189 ; CHECK-NEXT: {{ $}}190 ; CHECK-NEXT: bb.1.cleanup (inlineasm-br-indirect-target):191 ; CHECK-NEXT: liveins: $ebx192 ; CHECK-NEXT: {{ $}}193 ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gr32 = COPY $ebx194 ; CHECK-NEXT: $eax = COPY [[COPY2]]195 ; CHECK-NEXT: RET 0, $eax196entry:197 %direct = callbr i32 asm "# $0", "={bx},!i"()198 to label %cleanup [label %cleanup]199 200cleanup:201 %indirect = call i32 @llvm.callbr.landingpad.i32(i32 %direct)202 ret i32 %indirect203}204 205; "The Devil's cross" (i.e. two asm goto with conflicting physreg constraints206; going to the same destination) as expressed by clang.207define i64 @test6() {208 ; CHECK-LABEL: name: test6209 ; CHECK: bb.0.entry:210 ; CHECK-NEXT: successors: %bb.1(0x80000000), %bb.3(0x00000000)211 ; CHECK-NEXT: {{ $}}212 ; CHECK-NEXT: INLINEASM_BR &"", 0 /* attdialect */, 10 /* regdef */, implicit-def $rdx, 13 /* imm */, %bb.3213 ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr64 = COPY $rdx214 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr64 = COPY [[COPY]]215 ; CHECK-NEXT: JMP_1 %bb.1216 ; CHECK-NEXT: {{ $}}217 ; CHECK-NEXT: bb.1.asm.fallthrough:218 ; CHECK-NEXT: successors: %bb.2(0x80000000), %bb.4(0x00000000)219 ; CHECK-NEXT: {{ $}}220 ; CHECK-NEXT: INLINEASM_BR &"", 0 /* attdialect */, 10 /* regdef */, implicit-def $rbx, 13 /* imm */, %bb.4221 ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gr64 = COPY $rbx222 ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gr64 = COPY [[COPY2]]223 ; CHECK-NEXT: JMP_1 %bb.2224 ; CHECK-NEXT: {{ $}}225 ; CHECK-NEXT: bb.2.foo:226 ; CHECK-NEXT: [[PHI:%[0-9]+]]:gr64 = PHI %3, %bb.3, [[COPY3]], %bb.1, %4, %bb.4227 ; CHECK-NEXT: $rax = COPY [[PHI]]228 ; CHECK-NEXT: RET 0, $rax229 ; CHECK-NEXT: {{ $}}230 ; CHECK-NEXT: bb.3.foo.split (inlineasm-br-indirect-target):231 ; CHECK-NEXT: successors: %bb.2(0x80000000)232 ; CHECK-NEXT: liveins: $rdx233 ; CHECK-NEXT: {{ $}}234 ; CHECK-NEXT: [[COPY4:%[0-9]+]]:gr64 = COPY $rdx235 ; CHECK-NEXT: [[COPY5:%[0-9]+]]:gr64 = COPY [[COPY4]]236 ; CHECK-NEXT: JMP_1 %bb.2237 ; CHECK-NEXT: {{ $}}238 ; CHECK-NEXT: bb.4.foo.split2 (inlineasm-br-indirect-target):239 ; CHECK-NEXT: successors: %bb.2(0x80000000)240 ; CHECK-NEXT: liveins: $rbx241 ; CHECK-NEXT: {{ $}}242 ; CHECK-NEXT: [[COPY6:%[0-9]+]]:gr64 = COPY $rbx243 ; CHECK-NEXT: [[COPY7:%[0-9]+]]:gr64 = COPY [[COPY6]]244 ; CHECK-NEXT: JMP_1 %bb.2245entry:246 %0 = callbr i64 asm "", "={dx},!i"()247 to label %asm.fallthrough [label %foo.split]248 249asm.fallthrough:250 %1 = callbr i64 asm "", "={bx},!i"()251 to label %foo [label %foo.split2]252 253foo:254 %x.0 = phi i64 [ %3, %foo.split2 ], [ %2, %foo.split ], [ %1, %asm.fallthrough ]255 ret i64 %x.0256 257foo.split:258 %2 = call i64 @llvm.callbr.landingpad.i64(i64 %0)259 br label %foo260 261foo.split2:262 %3 = call i64 @llvm.callbr.landingpad.i64(i64 %1)263 br label %foo264}265 266 267; Test a callbr looping back on itself.268define i32 @test7() {269 ; CHECK-LABEL: name: test7270 ; CHECK: bb.0.entry:271 ; CHECK-NEXT: successors: %bb.1(0x80000000)272 ; CHECK-NEXT: {{ $}}273 ; CHECK-NEXT: [[DEF:%[0-9]+]]:gr32 = IMPLICIT_DEF274 ; CHECK-NEXT: {{ $}}275 ; CHECK-NEXT: bb.1.retry:276 ; CHECK-NEXT: successors: %bb.2(0x80000000), %bb.3(0x00000000)277 ; CHECK-NEXT: {{ $}}278 ; CHECK-NEXT: [[PHI:%[0-9]+]]:gr32 = PHI [[DEF]], %bb.0, %2, %bb.3279 ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY [[PHI]]280 ; CHECK-NEXT: INLINEASM_BR &"", 0 /* attdialect */, 10 /* regdef */, implicit-def $edx, 2147483657 /* reguse tiedto:$0 */, [[COPY]](tied-def 3), 13 /* imm */, %bb.3281 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr32 = COPY $edx282 ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gr32 = COPY [[COPY1]]283 ; CHECK-NEXT: JMP_1 %bb.2284 ; CHECK-NEXT: {{ $}}285 ; CHECK-NEXT: bb.2.asm.fallthrough:286 ; CHECK-NEXT: $eax = COPY [[COPY2]]287 ; CHECK-NEXT: RET 0, $eax288 ; CHECK-NEXT: {{ $}}289 ; CHECK-NEXT: bb.3.retry.split (inlineasm-br-indirect-target):290 ; CHECK-NEXT: successors: %bb.1(0x80000000)291 ; CHECK-NEXT: liveins: $edx292 ; CHECK-NEXT: {{ $}}293 ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gr32 = COPY $edx294 ; CHECK-NEXT: [[COPY4:%[0-9]+]]:gr32 = COPY [[COPY3]]295 ; CHECK-NEXT: JMP_1 %bb.1296entry:297 br label %retry298 299retry:300 %x.0 = phi i32 [ undef, %entry ], [ %1, %retry.split ]301 %0 = callbr i32 asm "", "={dx},0,!i"(i32 %x.0)302 to label %asm.fallthrough [label %retry.split]303 304asm.fallthrough:305 ret i32 %0306 307retry.split:308 %1 = call i32 @llvm.callbr.landingpad.i32(i32 %0)309 br label %retry310}311 312; Test the same destination appearing in the direct/fallthrough branch as the313; indirect branch. Same as test5 but with a virtreg rather than a physreg314; constraint.315define i32 @test8() {316 ; CHECK-LABEL: name: test8317 ; CHECK: bb.0.entry:318 ; CHECK-NEXT: successors: %bb.1(0x80000000)319 ; CHECK-NEXT: {{ $}}320 ; CHECK-NEXT: INLINEASM_BR &"# $0", 0 /* attdialect */, 2686986 /* regdef:GR32_NOREX2 */, def %1, 13 /* imm */, %bb.1321 ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY %1322 ; CHECK-NEXT: JMP_1 %bb.1323 ; CHECK-NEXT: {{ $}}324 ; CHECK-NEXT: bb.1.cleanup (inlineasm-br-indirect-target):325 ; CHECK-NEXT: $eax = COPY %1326 ; CHECK-NEXT: RET 0, $eax327entry:328 %direct = callbr i32 asm "# $0", "=r,!i"()329 to label %cleanup [label %cleanup]330 331cleanup:332 %indirect = call i32 @llvm.callbr.landingpad.i32(i32 %direct)333 ret i32 %indirect334}335 336define i64 @condition_code() {337 ; CHECK-LABEL: name: condition_code338 ; CHECK: bb.0 (%ir-block.0):339 ; CHECK-NEXT: successors: %bb.1(0x80000000), %bb.2(0x00000000)340 ; CHECK-NEXT: {{ $}}341 ; CHECK-NEXT: INLINEASM_BR &"", 16 /* maystore attdialect */, 2359306 /* regdef:GR32 */, def %1, 13 /* imm */, %bb.2342 ; CHECK-NEXT: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 4, implicit $eflags343 ; CHECK-NEXT: [[MOVZX32rr8_:%[0-9]+]]:gr32 = MOVZX32rr8 killed [[SETCCr]]344 ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gr64 = SUBREG_TO_REG 0, killed [[MOVZX32rr8_]], %subreg.sub_32bit345 ; CHECK-NEXT: JMP_1 %bb.1346 ; CHECK-NEXT: {{ $}}347 ; CHECK-NEXT: bb.1.b:348 ; CHECK-NEXT: $rax = COPY [[SUBREG_TO_REG]]349 ; CHECK-NEXT: RET 0, $rax350 ; CHECK-NEXT: {{ $}}351 ; CHECK-NEXT: bb.2.c (inlineasm-br-indirect-target):352 ; CHECK-NEXT: [[SETCCr1:%[0-9]+]]:gr8 = SETCCr 4, implicit $eflags353 ; CHECK-NEXT: [[MOVZX32rr8_1:%[0-9]+]]:gr32 = MOVZX32rr8 killed [[SETCCr1]]354 ; CHECK-NEXT: [[SUBREG_TO_REG1:%[0-9]+]]:gr64 = SUBREG_TO_REG 0, killed [[MOVZX32rr8_1]], %subreg.sub_32bit355 ; CHECK-NEXT: $rax = COPY [[SUBREG_TO_REG1]]356 ; CHECK-NEXT: RET 0, $rax357 %a = callbr i64 asm "", "={@ccz},!i"()358 to label %b [label %c]359 360b:361 ret i64 %a362 363c:364 %1 = call i64 @llvm.callbr.landingpad.i64(i64 %a)365 ret i64 %1366}367 368declare i64 @llvm.callbr.landingpad.i64(i64)369declare i32 @llvm.callbr.landingpad.i32(i32)370declare { i32, i32 } @llvm.callbr.landingpad.sl_i32i32s({ i32, i32 })371