Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / CodeGen / X86 / callbr-asm.ll
blob65dc635e43cdf43bdf793c94b6d5616480d1b66b
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=i686-- -O3 -verify-machineinstrs | FileCheck %s
4 ; Tests for using callbr as an asm-goto wrapper
6 ; Test 1 - fallthrough label gets removed, but the fallthrough code that is
7 ; unreachable due to asm ending on a jmp is still left in.
8 define i32 @test1(i32 %a) {
9 ; CHECK-LABEL: test1:
10 ; CHECK:       # %bb.0: # %entry
11 ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
12 ; CHECK-NEXT:    addl $4, %eax
13 ; CHECK-NEXT:    #APP
14 ; CHECK-NEXT:    xorl %eax, %eax
15 ; CHECK-NEXT:    jmp .LBB0_2
16 ; CHECK-NEXT:    #NO_APP
17 ; CHECK-NEXT:  # %bb.1: # %normal
18 ; CHECK-NEXT:    xorl %eax, %eax
19 ; CHECK-NEXT:    retl
20 ; CHECK-NEXT:  .LBB0_2: # Block address taken
21 ; CHECK-NEXT:    # %fail
22 ; CHECK-NEXT:    # Label of block must be emitted
23 ; CHECK-NEXT:    movl $1, %eax
24 ; CHECK-NEXT:    retl
25 entry:
26   %0 = add i32 %a, 4
27   callbr void asm "xorl $0, $0; jmp ${1:l}", "r,!i,~{dirflag},~{fpsr},~{flags}"(i32 %0) to label %normal [label %fail]
29 normal:
30   ret i32 0
32 fail:
33   ret i32 1
36 ; Test 1b - Like test 1 but using `asm inteldialect`.
37 define i32 @test1b(i32 %a) {
38 ; CHECK-LABEL: test1b:
39 ; CHECK:       # %bb.0: # %entry
40 ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
41 ; CHECK-NEXT:    addl $4, %eax
42 ; CHECK-NEXT:    #APP
43 ; CHECK-EMPTY:
44 ; CHECK-NEXT:    xorl %eax, %eax
45 ; CHECK-NEXT:    jmp .LBB1_2
46 ; CHECK-EMPTY:
47 ; CHECK-NEXT:    #NO_APP
48 ; CHECK-NEXT:  # %bb.1: # %normal
49 ; CHECK-NEXT:    xorl %eax, %eax
50 ; CHECK-NEXT:    retl
51 ; CHECK-NEXT:  .LBB1_2: # Block address taken
52 ; CHECK-NEXT:    # %fail
53 ; CHECK-NEXT:    # Label of block must be emitted
54 ; CHECK-NEXT:    movl $1, %eax
55 ; CHECK-NEXT:    retl
56 entry:
57   %0 = add i32 %a, 4
58   callbr void asm inteldialect "xor $0, $0; jmp ${1:l}", "r,!i,~{dirflag},~{fpsr},~{flags}"(i32 %0) to label %normal [label %fail]
60 normal:
61   ret i32 0
63 fail:
64   ret i32 1
67 ; Test 2 - callbr terminates an unreachable block, function gets simplified
68 ; to a trivial zero return.
69 define i32 @test2(i32 %a) {
70 ; CHECK-LABEL: test2:
71 ; CHECK:       # %bb.0: # %entry
72 ; CHECK-NEXT:    xorl %eax, %eax
73 ; CHECK-NEXT:    retl
74 entry:
75   br label %normal
77 unreachableasm:
78   %0 = add i32 %a, 4
79   callbr void asm sideeffect "xorl $0, $0; jmp ${1:l}", "r,!i,~{dirflag},~{fpsr},~{flags}"(i32 %0) to label %normal [label %fail]
81 normal:
82   ret i32 0
84 fail:
85   ret i32 1
88 ; Test 3 - asm-goto implements a loop. The loop gets recognized, but many loop
89 ; transforms fail due to canonicalization having callbr exceptions. Trivial
90 ; blocks at labels 1 and 3 also don't get simplified due to callbr.
91 define i32 @test3(i32 %a) {
92 ; CHECK-LABEL: test3:
93 ; CHECK:       # %bb.0: # %entry
94 ; CHECK-NEXT:  .LBB3_1: # Block address taken
95 ; CHECK-NEXT:    # %label01
96 ; CHECK-NEXT:    # =>This Loop Header: Depth=1
97 ; CHECK-NEXT:    # Child Loop BB3_2 Depth 2
98 ; CHECK-NEXT:    # Child Loop BB3_3 Depth 3
99 ; CHECK-NEXT:    # Child Loop BB3_4 Depth 4
100 ; CHECK-NEXT:    # Label of block must be emitted
101 ; CHECK-NEXT:  .LBB3_2: # Block address taken
102 ; CHECK-NEXT:    # %label02
103 ; CHECK-NEXT:    # Parent Loop BB3_1 Depth=1
104 ; CHECK-NEXT:    # => This Loop Header: Depth=2
105 ; CHECK-NEXT:    # Child Loop BB3_3 Depth 3
106 ; CHECK-NEXT:    # Child Loop BB3_4 Depth 4
107 ; CHECK-NEXT:    # Label of block must be emitted
108 ; CHECK-NEXT:    addl $4, {{[0-9]+}}(%esp)
109 ; CHECK-NEXT:  .LBB3_3: # Block address taken
110 ; CHECK-NEXT:    # %label03
111 ; CHECK-NEXT:    # Parent Loop BB3_1 Depth=1
112 ; CHECK-NEXT:    # Parent Loop BB3_2 Depth=2
113 ; CHECK-NEXT:    # => This Loop Header: Depth=3
114 ; CHECK-NEXT:    # Child Loop BB3_4 Depth 4
115 ; CHECK-NEXT:    # Label of block must be emitted
116 ; CHECK-NEXT:  .LBB3_4: # Block address taken
117 ; CHECK-NEXT:    # %label04
118 ; CHECK-NEXT:    # Parent Loop BB3_1 Depth=1
119 ; CHECK-NEXT:    # Parent Loop BB3_2 Depth=2
120 ; CHECK-NEXT:    # Parent Loop BB3_3 Depth=3
121 ; CHECK-NEXT:    # => This Inner Loop Header: Depth=4
122 ; CHECK-NEXT:    # Label of block must be emitted
123 ; CHECK-NEXT:    #APP
124 ; CHECK-NEXT:    jmp .LBB3_1
125 ; CHECK-NEXT:    jmp .LBB3_2
126 ; CHECK-NEXT:    jmp .LBB3_3
127 ; CHECK-NEXT:    #NO_APP
128 ; CHECK-NEXT:  # %bb.5: # %normal0
129 ; CHECK-NEXT:    # in Loop: Header=BB3_4 Depth=4
130 ; CHECK-NEXT:    #APP
131 ; CHECK-NEXT:    jmp .LBB3_1
132 ; CHECK-NEXT:    jmp .LBB3_2
133 ; CHECK-NEXT:    jmp .LBB3_3
134 ; CHECK-NEXT:    jmp .LBB3_4
135 ; CHECK-NEXT:    #NO_APP
136 ; CHECK-NEXT:  # %bb.6: # %normal1
137 ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
138 ; CHECK-NEXT:    retl
139 entry:
140   %a.addr = alloca i32, align 4
141   store i32 %a, ptr %a.addr, align 4
142   br label %label01
144 label01:                                          ; preds = %normal0, %label04, %entry
145   br label %label02
147 label02:                                          ; preds = %normal0, %label04, %label01
148   %0 = load i32, ptr %a.addr, align 4
149   %add = add nsw i32 %0, 4
150   store i32 %add, ptr %a.addr, align 4
151   br label %label03
153 label03:                                          ; preds = %normal0, %label04, %label02
154   br label %label04
156 label04:                                          ; preds = %normal0, %label03
157   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]
160 normal0:                                          ; preds = %label04
161   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]
164 normal1:                                          ; preds = %normal0
165   %1 = load i32, ptr %a.addr, align 4
166   ret i32 %1
169 ; Test 4 - asm-goto referenced with the 'l' (ell) modifier and not.
170 define void @test4() {
171 ; CHECK-LABEL: test4:
172 ; CHECK:       # %bb.0: # %entry
173 ; CHECK-NEXT:    #APP
174 ; CHECK-NEXT:    ja .LBB4_3
175 ; CHECK-NEXT:    #NO_APP
176 ; CHECK-NEXT:  # %bb.1: # %asm.fallthrough
177 ; CHECK-NEXT:    #APP
178 ; CHECK-NEXT:    ja .LBB4_3
179 ; CHECK-NEXT:    #NO_APP
180 ; CHECK-NEXT:  .LBB4_3: # Block address taken
181 ; CHECK-NEXT:    # %quux
182 ; CHECK-NEXT:    # Label of block must be emitted
183 ; CHECK-NEXT:    retl
184 entry:
185   callbr void asm sideeffect "ja $0", "!i,~{dirflag},~{fpsr},~{flags}"()
186           to label %asm.fallthrough [label %quux]
188 asm.fallthrough:                                  ; preds = %entry
189   callbr void asm sideeffect "ja ${0:l}", "!i,~{dirflag},~{fpsr},~{flags}"()
190           to label %cleanup [label %quux]
192 quux:                                             ; preds = %asm.fallthrough, %entry
193   br label %cleanup
195 cleanup:                                          ; preds = %asm.fallthrough, %quux
196   ret void