1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=i686-unknown -verify-machineinstrs < %s | FileCheck %s
3; RUN: opt < %s -codegenprepare -S -mtriple=x86_64-unknown-unknown | FileCheck --check-prefix=CHECK-CGP %s
4
5@A = global i32 zeroinitializer
6@B = global i32 zeroinitializer
7@C = global i32 zeroinitializer
8
9; Test that 'and' is sunk into bb0.
10define i32 @and_sink1(i32 %a, i1 %c) {
11; CHECK-LABEL: and_sink1:
12; CHECK:       # %bb.0:
13; CHECK-NEXT:    testb $1, {{[0-9]+}}(%esp)
14; CHECK-NEXT:    je .LBB0_3
15; CHECK-NEXT:  # %bb.1: # %bb0
16; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
17; CHECK-NEXT:    testb $4, %al
18; CHECK-NEXT:    movl $0, A
19; CHECK-NEXT:    jne .LBB0_3
20; CHECK-NEXT:  # %bb.2: # %bb1
21; CHECK-NEXT:    movl $1, %eax
22; CHECK-NEXT:    retl
23; CHECK-NEXT:  .LBB0_3: # %bb2
24; CHECK-NEXT:    xorl %eax, %eax
25; CHECK-NEXT:    retl
26
27; CHECK-CGP-LABEL: @and_sink1(
28; CHECK-CGP-NOT: and i32
29  %and = and i32 %a, 4
30  br i1 %c, label %bb0, label %bb2
31bb0:
32; CHECK-CGP-LABEL: bb0:
33; CHECK-CGP: and i32
34; CHECK-CGP-NEXT: icmp eq i32
35; CHECK-CGP-NEXT: store
36; CHECK-CGP-NEXT: br
37  %cmp = icmp eq i32 %and, 0
38  store i32 0, i32* @A
39  br i1 %cmp, label %bb1, label %bb2
40bb1:
41  ret i32 1
42bb2:
43  ret i32 0
44}
45
46; Test that both 'and' and cmp get sunk to bb1.
47define i32 @and_sink2(i32 %a, i1 %c, i1 %c2) {
48; CHECK-LABEL: and_sink2:
49; CHECK:       # %bb.0:
50; CHECK-NEXT:    movl $0, A
51; CHECK-NEXT:    testb $1, {{[0-9]+}}(%esp)
52; CHECK-NEXT:    je .LBB1_5
53; CHECK-NEXT:  # %bb.1: # %bb0.preheader
54; CHECK-NEXT:    movb {{[0-9]+}}(%esp), %al
55; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %ecx
56; CHECK-NEXT:    .p2align 4, 0x90
57; CHECK-NEXT:  .LBB1_2: # %bb0
58; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
59; CHECK-NEXT:    movl $0, B
60; CHECK-NEXT:    testb $1, %al
61; CHECK-NEXT:    je .LBB1_5
62; CHECK-NEXT:  # %bb.3: # %bb1
63; CHECK-NEXT:    # in Loop: Header=BB1_2 Depth=1
64; CHECK-NEXT:    testb $4, %cl
65; CHECK-NEXT:    movl $0, C
66; CHECK-NEXT:    jne .LBB1_2
67; CHECK-NEXT:  # %bb.4: # %bb2
68; CHECK-NEXT:    movl $1, %eax
69; CHECK-NEXT:    retl
70; CHECK-NEXT:  .LBB1_5: # %bb3
71; CHECK-NEXT:    xorl %eax, %eax
72; CHECK-NEXT:    retl
73
74; CHECK-CGP-LABEL: @and_sink2(
75; CHECK-CGP-NOT: and i32
76  %and = and i32 %a, 4
77  store i32 0, i32* @A
78  br i1 %c, label %bb0, label %bb3
79bb0:
80; CHECK-CGP-LABEL: bb0:
81; CHECK-CGP-NOT: and i32
82; CHECK-CGP-NOT: icmp
83  %cmp = icmp eq i32 %and, 0
84  store i32 0, i32* @B
85  br i1 %c2, label %bb1, label %bb3
86bb1:
87; CHECK-CGP-LABEL: bb1:
88; CHECK-CGP: and i32
89; CHECK-CGP-NEXT: icmp eq i32
90; CHECK-CGP-NEXT: store
91; CHECK-CGP-NEXT: br
92  store i32 0, i32* @C
93  br i1 %cmp, label %bb2, label %bb0
94bb2:
95  ret i32 1
96bb3:
97  ret i32 0
98}
99
100; Test that CodeGenPrepare doesn't get stuck in a loop sinking and hoisting a masked load.
101define i32 @and_sink3(i1 %c, i32* %p) {
102; CHECK-LABEL: and_sink3:
103; CHECK:       # %bb.0:
104; CHECK-NEXT:    testb $1, {{[0-9]+}}(%esp)
105; CHECK-NEXT:    je .LBB2_3
106; CHECK-NEXT:  # %bb.1: # %bb0
107; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
108; CHECK-NEXT:    movzbl (%eax), %eax
109; CHECK-NEXT:    testl %eax, %eax
110; CHECK-NEXT:    movl $0, A
111; CHECK-NEXT:    je .LBB2_2
112; CHECK-NEXT:  .LBB2_3: # %bb2
113; CHECK-NEXT:    xorl %eax, %eax
114; CHECK-NEXT:    retl
115; CHECK-NEXT:  .LBB2_2: # %bb1
116; CHECK-NEXT:    movl $1, %eax
117; CHECK-NEXT:    retl
118
119; CHECK-CGP-LABEL: @and_sink3(
120; CHECK-CGP: load i32
121; CHECK-CGP-NEXT: and i32
122  %load = load i32, i32* %p
123  %and = and i32 %load, 255
124  br i1 %c, label %bb0, label %bb2
125bb0:
126; CHECK-CGP-LABEL: bb0:
127; CHECK-CGP-NOT: and i32
128; CHECK-CGP: icmp eq i32
129  %cmp = icmp eq i32 %and, 0
130  store i32 0, i32* @A
131  br i1 %cmp, label %bb1, label %bb2
132bb1:
133  ret i32 1
134bb2:
135  ret i32 0
136}
137
138; Test that CodeGenPrepare sinks/duplicates non-immediate 'and'.
139define i32 @and_sink4(i32 %a, i32 %b, i1 %c) {
140; CHECK-LABEL: and_sink4:
141; CHECK:       # %bb.0:
142; CHECK-NEXT:    testb $1, {{[0-9]+}}(%esp)
143; CHECK-NEXT:    je .LBB3_4
144; CHECK-NEXT:  # %bb.1: # %bb0
145; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
146; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %ecx
147; CHECK-NEXT:    testl %eax, %ecx
148; CHECK-NEXT:    movl $0, A
149; CHECK-NEXT:    jne .LBB3_4
150; CHECK-NEXT:  # %bb.2: # %bb1
151; CHECK-NEXT:    leal (%ecx,%eax), %edx
152; CHECK-NEXT:    testl %eax, %ecx
153; CHECK-NEXT:    movl %edx, B
154; CHECK-NEXT:    je .LBB3_3
155; CHECK-NEXT:  .LBB3_4: # %bb3
156; CHECK-NEXT:    xorl %eax, %eax
157; CHECK-NEXT:    retl
158; CHECK-NEXT:  .LBB3_3: # %bb2
159; CHECK-NEXT:    movl $1, %eax
160; CHECK-NEXT:    retl
161
162; CHECK-CGP-LABEL: @and_sink4(
163; CHECK-CGP-NOT: and i32
164; CHECK-CGP-NOT: icmp
165  %and = and i32 %a, %b
166  %cmp = icmp eq i32 %and, 0
167  br i1 %c, label %bb0, label %bb3
168bb0:
169; CHECK-CGP-LABEL: bb0:
170; CHECK-CGP: and i32
171; CHECK-CGP-NEXT: icmp eq i32
172  store i32 0, i32* @A
173  br i1 %cmp, label %bb1, label %bb3
174bb1:
175; CHECK-CGP-LABEL: bb1:
176; CHECK-CGP: and i32
177; CHECK-CGP-NEXT: icmp eq i32
178  %add = add i32 %a, %b
179  store i32 %add, i32* @B
180  br i1 %cmp, label %bb2, label %bb3
181bb2:
182  ret i32 1
183bb3:
184  ret i32 0
185}
186
187
188; Test that CodeGenPrepare doesn't sink/duplicate non-immediate 'and'
189; when it would increase register pressure.
190define i32 @and_sink5(i32 %a, i32 %b, i32 %a2, i32 %b2, i1 %c) {
191; CHECK-LABEL: and_sink5:
192; CHECK:       # %bb.0:
193; CHECK-NEXT:    testb $1, {{[0-9]+}}(%esp)
194; CHECK-NEXT:    je .LBB4_4
195; CHECK-NEXT:  # %bb.1: # %bb0
196; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
197; CHECK-NEXT:    andl {{[0-9]+}}(%esp), %eax
198; CHECK-NEXT:    movl $0, A
199; CHECK-NEXT:    jne .LBB4_4
200; CHECK-NEXT:  # %bb.2: # %bb1
201; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %ecx
202; CHECK-NEXT:    addl {{[0-9]+}}(%esp), %ecx
203; CHECK-NEXT:    testl %eax, %eax
204; CHECK-NEXT:    movl %ecx, B
205; CHECK-NEXT:    je .LBB4_3
206; CHECK-NEXT:  .LBB4_4: # %bb3
207; CHECK-NEXT:    xorl %eax, %eax
208; CHECK-NEXT:    retl
209; CHECK-NEXT:  .LBB4_3: # %bb2
210; CHECK-NEXT:    movl $1, %eax
211; CHECK-NEXT:    retl
212
213; CHECK-CGP-LABEL: @and_sink5(
214; CHECK-CGP: and i32
215; CHECK-CGP-NOT: icmp
216  %and = and i32 %a, %b
217  %cmp = icmp eq i32 %and, 0
218  br i1 %c, label %bb0, label %bb3
219bb0:
220; CHECK-CGP-LABEL: bb0:
221; CHECK-CGP-NOT: and i32
222; CHECK-CGP: icmp eq i32
223  store i32 0, i32* @A
224  br i1 %cmp, label %bb1, label %bb3
225bb1:
226; CHECK-CGP-LABEL: bb1:
227; CHECK-CGP-NOT: and i32
228; CHECK-CGP: icmp eq i32
229  %add = add i32 %a2, %b2
230  store i32 %add, i32* @B
231  br i1 %cmp, label %bb2, label %bb3
232bb2:
233  ret i32 1
234bb3:
235  ret i32 0
236}
237