198 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=i686-- -O3 -verify-machineinstrs | FileCheck %s3 4; Tests for using callbr as an asm-goto wrapper5 6; Test 1 - fallthrough label gets removed, but the fallthrough code that is7; unreachable due to asm ending on a jmp is still left in.8define i32 @test1(i32 %a) {9; CHECK-LABEL: test1:10; CHECK: # %bb.0: # %entry11; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax12; CHECK-NEXT: addl $4, %eax13; CHECK-NEXT: #APP14; CHECK-NEXT: xorl %eax, %eax15; CHECK-NEXT: jmp .LBB0_216; CHECK-NEXT: #NO_APP17; CHECK-NEXT: # %bb.1: # %normal18; CHECK-NEXT: xorl %eax, %eax19; CHECK-NEXT: retl20; CHECK-NEXT: .LBB0_2: # Inline asm indirect target21; CHECK-NEXT: # %fail22; CHECK-NEXT: # Label of block must be emitted23; CHECK-NEXT: movl $1, %eax24; CHECK-NEXT: retl25entry:26 %0 = add i32 %a, 427 callbr void asm "xorl $0, $0; jmp ${1:l}", "r,!i,~{dirflag},~{fpsr},~{flags}"(i32 %0) to label %normal [label %fail]28 29normal:30 ret i32 031 32fail:33 ret i32 134}35 36; Test 1b - Like test 1 but using `asm inteldialect`.37define i32 @test1b(i32 %a) {38; CHECK-LABEL: test1b:39; CHECK: # %bb.0: # %entry40; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax41; CHECK-NEXT: addl $4, %eax42; CHECK-NEXT: #APP43; CHECK-EMPTY:44; CHECK-NEXT: xorl %eax, %eax45; CHECK-NEXT: jmp .LBB1_246; CHECK-EMPTY:47; CHECK-NEXT: #NO_APP48; CHECK-NEXT: # %bb.1: # %normal49; CHECK-NEXT: xorl %eax, %eax50; CHECK-NEXT: retl51; CHECK-NEXT: .LBB1_2: # Inline asm indirect target52; CHECK-NEXT: # %fail53; CHECK-NEXT: # Label of block must be emitted54; CHECK-NEXT: movl $1, %eax55; CHECK-NEXT: retl56entry:57 %0 = add i32 %a, 458 callbr void asm inteldialect "xor $0, $0; jmp ${1:l}", "r,!i,~{dirflag},~{fpsr},~{flags}"(i32 %0) to label %normal [label %fail]59 60normal:61 ret i32 062 63fail:64 ret i32 165}66 67; Test 2 - callbr terminates an unreachable block, function gets simplified68; to a trivial zero return.69define i32 @test2(i32 %a) {70; CHECK-LABEL: test2:71; CHECK: # %bb.0: # %entry72; CHECK-NEXT: xorl %eax, %eax73; CHECK-NEXT: retl74entry:75 br label %normal76 77unreachableasm:78 %0 = add i32 %a, 479 callbr void asm sideeffect "xorl $0, $0; jmp ${1:l}", "r,!i,~{dirflag},~{fpsr},~{flags}"(i32 %0) to label %normal [label %fail]80 81normal:82 ret i32 083 84fail:85 ret i32 186}87 88; Test 3 - asm-goto implements a loop. The loop gets recognized, but many loop89; transforms fail due to canonicalization having callbr exceptions. Trivial90; blocks at labels 1 and 3 also don't get simplified due to callbr.91define i32 @test3(i32 %a) {92; CHECK-LABEL: test3:93; CHECK: # %bb.0: # %entry94; CHECK-NEXT: .LBB3_1: # Inline asm indirect target95; CHECK-NEXT: # %label0196; CHECK-NEXT: # =>This Loop Header: Depth=197; CHECK-NEXT: # Child Loop BB3_2 Depth 298; CHECK-NEXT: # Child Loop BB3_3 Depth 399; CHECK-NEXT: # Child Loop BB3_4 Depth 4100; CHECK-NEXT: # Label of block must be emitted101; CHECK-NEXT: .LBB3_2: # Inline asm indirect target102; CHECK-NEXT: # %label02103; CHECK-NEXT: # Parent Loop BB3_1 Depth=1104; CHECK-NEXT: # => This Loop Header: Depth=2105; CHECK-NEXT: # Child Loop BB3_3 Depth 3106; CHECK-NEXT: # Child Loop BB3_4 Depth 4107; CHECK-NEXT: # Label of block must be emitted108; CHECK-NEXT: addl $4, {{[0-9]+}}(%esp)109; CHECK-NEXT: .LBB3_3: # Inline asm indirect target110; CHECK-NEXT: # %label03111; CHECK-NEXT: # Parent Loop BB3_1 Depth=1112; CHECK-NEXT: # Parent Loop BB3_2 Depth=2113; CHECK-NEXT: # => This Loop Header: Depth=3114; CHECK-NEXT: # Child Loop BB3_4 Depth 4115; CHECK-NEXT: # Label of block must be emitted116; CHECK-NEXT: .LBB3_4: # Inline asm indirect target117; CHECK-NEXT: # %label04118; CHECK-NEXT: # Parent Loop BB3_1 Depth=1119; CHECK-NEXT: # Parent Loop BB3_2 Depth=2120; CHECK-NEXT: # Parent Loop BB3_3 Depth=3121; CHECK-NEXT: # => This Inner Loop Header: Depth=4122; CHECK-NEXT: # Label of block must be emitted123; CHECK-NEXT: #APP124; CHECK-NEXT: jmp .LBB3_1125; CHECK-NEXT: jmp .LBB3_2126; CHECK-NEXT: jmp .LBB3_3127; CHECK-NEXT: #NO_APP128; CHECK-NEXT: # %bb.5: # %normal0129; CHECK-NEXT: # in Loop: Header=BB3_4 Depth=4130; CHECK-NEXT: #APP131; CHECK-NEXT: jmp .LBB3_1132; CHECK-NEXT: jmp .LBB3_2133; CHECK-NEXT: jmp .LBB3_3134; CHECK-NEXT: jmp .LBB3_4135; CHECK-NEXT: #NO_APP136; CHECK-NEXT: # %bb.6: # %normal1137; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax138; CHECK-NEXT: retl139entry:140 %a.addr = alloca i32, align 4141 store i32 %a, ptr %a.addr, align 4142 br label %label01143 144label01: ; preds = %normal0, %label04, %entry145 br label %label02146 147label02: ; preds = %normal0, %label04, %label01148 %0 = load i32, ptr %a.addr, align 4149 %add = add nsw i32 %0, 4150 store i32 %add, ptr %a.addr, align 4151 br label %label03152 153label03: ; preds = %normal0, %label04, %label02154 br label %label04155 156label04: ; preds = %normal0, %label03157 callbr void asm sideeffect "jmp ${0:l}; jmp ${1:l}; jmp ${2:l}", "!i,!i,!i,~{dirflag},~{fpsr},~{flags}"()158 to label %normal0 [label %label01, label %label02, label %label03]159 160normal0: ; preds = %label04161 callbr void asm sideeffect "jmp ${0:l}; jmp ${1:l}; jmp ${2:l}; jmp ${3:l}", "!i,!i,!i,!i,~{dirflag},~{fpsr},~{flags}"()162 to label %normal1 [label %label01, label %label02, label %label03, label %label04]163 164normal1: ; preds = %normal0165 %1 = load i32, ptr %a.addr, align 4166 ret i32 %1167}168 169; Test 4 - asm-goto referenced with the 'l' (ell) modifier and not.170define void @test4() {171; CHECK-LABEL: test4:172; CHECK: # %bb.0: # %entry173; CHECK-NEXT: #APP174; CHECK-NEXT: ja .LBB4_3175; CHECK-NEXT: #NO_APP176; CHECK-NEXT: # %bb.1: # %asm.fallthrough177; CHECK-NEXT: #APP178; CHECK-NEXT: ja .LBB4_3179; CHECK-NEXT: #NO_APP180; CHECK-NEXT: .LBB4_3: # Inline asm indirect target181; CHECK-NEXT: # %quux182; CHECK-NEXT: # Label of block must be emitted183; CHECK-NEXT: retl184entry:185 callbr void asm sideeffect "ja $0", "!i,~{dirflag},~{fpsr},~{flags}"()186 to label %asm.fallthrough [label %quux]187 188asm.fallthrough: ; preds = %entry189 callbr void asm sideeffect "ja ${0:l}", "!i,~{dirflag},~{fpsr},~{flags}"()190 to label %cleanup [label %quux]191 192quux: ; preds = %asm.fallthrough, %entry193 br label %cleanup194 195cleanup: ; preds = %asm.fallthrough, %quux196 ret void197}198