• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2; RUN: llc -mtriple aarch64 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s
3
4declare i32 @bar(...)
5define void @or_cond(i32 %X, i32 %Y, i32 %Z) nounwind {
6  ; CHECK-LABEL: name: or_cond
7  ; CHECK: bb.1.entry:
8  ; CHECK:   successors: %bb.2(0x20000000), %bb.4(0x60000000)
9  ; CHECK:   liveins: $w0, $w1, $w2
10  ; CHECK:   [[COPY:%[0-9]+]]:_(s32) = COPY $w0
11  ; CHECK:   [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
12  ; CHECK:   [[COPY2:%[0-9]+]]:_(s32) = COPY $w2
13  ; CHECK:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
14  ; CHECK:   [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
15  ; CHECK:   [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY]](s32), [[C]]
16  ; CHECK:   [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY1]](s32), [[C1]]
17  ; CHECK:   [[OR:%[0-9]+]]:_(s1) = G_OR [[ICMP1]], [[ICMP]]
18  ; CHECK:   [[ICMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY1]](s32), [[C1]]
19  ; CHECK:   G_BRCOND [[ICMP2]](s1), %bb.2
20  ; CHECK:   G_BR %bb.4
21  ; CHECK: bb.4.entry:
22  ; CHECK:   successors: %bb.2(0x2aaaaaab), %bb.3(0x55555555)
23  ; CHECK:   [[ICMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY]](s32), [[C]]
24  ; CHECK:   G_BRCOND [[ICMP3]](s1), %bb.2
25  ; CHECK:   G_BR %bb.3
26  ; CHECK: bb.2.cond_true:
27  ; CHECK:   TCRETURNdi @bar, 0, csr_aarch64_aapcs, implicit $sp
28  ; CHECK: bb.3.UnifiedReturnBlock:
29  ; CHECK:   RET_ReallyLR
30entry:
31  %tmp1 = icmp eq i32 %X, 0
32  %tmp3 = icmp slt i32 %Y, 5
33  %tmp4 = or i1 %tmp3, %tmp1
34  br i1 %tmp4, label %cond_true, label %UnifiedReturnBlock
35
36cond_true:
37  %tmp5 = tail call i32 (...) @bar( )
38  ret void
39
40UnifiedReturnBlock:
41  ret void
42}
43
44define void @and_cond(i32 %X, i32 %Y, i32 %Z) nounwind {
45  ; CHECK-LABEL: name: and_cond
46  ; CHECK: bb.1.entry:
47  ; CHECK:   successors: %bb.4(0x60000000), %bb.3(0x20000000)
48  ; CHECK:   liveins: $w0, $w1, $w2
49  ; CHECK:   [[COPY:%[0-9]+]]:_(s32) = COPY $w0
50  ; CHECK:   [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
51  ; CHECK:   [[COPY2:%[0-9]+]]:_(s32) = COPY $w2
52  ; CHECK:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
53  ; CHECK:   [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
54  ; CHECK:   [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY]](s32), [[C]]
55  ; CHECK:   [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY1]](s32), [[C1]]
56  ; CHECK:   [[AND:%[0-9]+]]:_(s1) = G_AND [[ICMP1]], [[ICMP]]
57  ; CHECK:   [[ICMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY1]](s32), [[C1]]
58  ; CHECK:   G_BRCOND [[ICMP2]](s1), %bb.4
59  ; CHECK:   G_BR %bb.3
60  ; CHECK: bb.4.entry:
61  ; CHECK:   successors: %bb.2(0x55555555), %bb.3(0x2aaaaaab)
62  ; CHECK:   [[ICMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY]](s32), [[C]]
63  ; CHECK:   G_BRCOND [[ICMP3]](s1), %bb.2
64  ; CHECK:   G_BR %bb.3
65  ; CHECK: bb.2.cond_true:
66  ; CHECK:   TCRETURNdi @bar, 0, csr_aarch64_aapcs, implicit $sp
67  ; CHECK: bb.3.UnifiedReturnBlock:
68  ; CHECK:   RET_ReallyLR
69entry:
70  %tmp1 = icmp eq i32 %X, 0
71  %tmp3 = icmp slt i32 %Y, 5
72  %tmp4 = and i1 %tmp3, %tmp1
73  br i1 %tmp4, label %cond_true, label %UnifiedReturnBlock
74
75cond_true:
76  %tmp5 = tail call i32 (...) @bar( )
77  ret void
78
79UnifiedReturnBlock:
80  ret void
81}
82
83; Don't emit two branches for same operands.
84define void @or_cond_same_values_cmp(i32 %X, i32 %Y, i32 %Z) nounwind {
85  ; CHECK-LABEL: name: or_cond_same_values_cmp
86  ; CHECK: bb.1.entry:
87  ; CHECK:   successors: %bb.2(0x40000000), %bb.3(0x40000000)
88  ; CHECK:   liveins: $w0, $w1, $w2
89  ; CHECK:   [[COPY:%[0-9]+]]:_(s32) = COPY $w0
90  ; CHECK:   [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
91  ; CHECK:   [[COPY2:%[0-9]+]]:_(s32) = COPY $w2
92  ; CHECK:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
93  ; CHECK:   [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY]](s32), [[C]]
94  ; CHECK:   [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY]](s32), [[C]]
95  ; CHECK:   [[OR:%[0-9]+]]:_(s1) = G_OR [[ICMP1]], [[ICMP]]
96  ; CHECK:   G_BRCOND [[OR]](s1), %bb.2
97  ; CHECK:   G_BR %bb.3
98  ; CHECK: bb.2.cond_true:
99  ; CHECK:   TCRETURNdi @bar, 0, csr_aarch64_aapcs, implicit $sp
100  ; CHECK: bb.3.UnifiedReturnBlock:
101  ; CHECK:   RET_ReallyLR
102entry:
103  %tmp1 = icmp eq i32 %X, 5
104  %tmp3 = icmp slt i32 %X, 5
105  %tmp4 = or i1 %tmp3, %tmp1
106  br i1 %tmp4, label %cond_true, label %UnifiedReturnBlock
107
108cond_true:
109  %tmp5 = tail call i32 (...) @bar( )
110  ret void
111
112UnifiedReturnBlock:
113  ret void
114}
115
116; Emit multiple branches for more than 2 cases.
117define void @or_cond_multiple_cases(i32 %X, i32 %Y, i32 %Z) nounwind {
118  ; CHECK-LABEL: name: or_cond_multiple_cases
119  ; CHECK: bb.1.entry:
120  ; CHECK:   successors: %bb.2(0x10000000), %bb.5(0x70000000)
121  ; CHECK:   liveins: $w0, $w1, $w2
122  ; CHECK:   [[COPY:%[0-9]+]]:_(s32) = COPY $w0
123  ; CHECK:   [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
124  ; CHECK:   [[COPY2:%[0-9]+]]:_(s32) = COPY $w2
125  ; CHECK:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
126  ; CHECK:   [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY]](s32), [[C]]
127  ; CHECK:   [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY]](s32), [[C]]
128  ; CHECK:   [[ICMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY2]](s32), [[C]]
129  ; CHECK:   [[OR:%[0-9]+]]:_(s1) = G_OR [[ICMP1]], [[ICMP]]
130  ; CHECK:   [[OR1:%[0-9]+]]:_(s1) = G_OR [[OR]], [[ICMP2]]
131  ; CHECK:   [[ICMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY]](s32), [[C]]
132  ; CHECK:   G_BRCOND [[ICMP3]](s1), %bb.2
133  ; CHECK:   G_BR %bb.5
134  ; CHECK: bb.5.entry:
135  ; CHECK:   successors: %bb.2(0x12492492), %bb.4(0x6db6db6e)
136  ; CHECK:   [[ICMP4:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY]](s32), [[C]]
137  ; CHECK:   G_BRCOND [[ICMP4]](s1), %bb.2
138  ; CHECK:   G_BR %bb.4
139  ; CHECK: bb.4.entry:
140  ; CHECK:   successors: %bb.2(0x2aaaaaab), %bb.3(0x55555555)
141  ; CHECK:   [[ICMP5:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY2]](s32), [[C]]
142  ; CHECK:   G_BRCOND [[ICMP5]](s1), %bb.2
143  ; CHECK:   G_BR %bb.3
144  ; CHECK: bb.2.cond_true:
145  ; CHECK:   TCRETURNdi @bar, 0, csr_aarch64_aapcs, implicit $sp
146  ; CHECK: bb.3.UnifiedReturnBlock:
147  ; CHECK:   RET_ReallyLR
148entry:
149  %tmp1 = icmp eq i32 %X, 5
150  %tmp3 = icmp slt i32 %X, 5
151  %tmpZ = icmp eq i32 %Z, 5
152  %tmp4 = or i1 %tmp3, %tmp1
153  %final = or i1 %tmp4, %tmpZ
154  br i1 %final, label %cond_true, label %UnifiedReturnBlock
155
156cond_true:
157  %tmp5 = tail call i32 (...) @bar( )
158  ret void
159
160UnifiedReturnBlock:
161  ret void
162}
163
164; (X != null) | (Y != null) --> (X|Y) != 0
165; Don't emit two branches.
166define void @or_cond_ne_null(i32 %X, i32 %Y, i32 %Z) nounwind {
167  ; CHECK-LABEL: name: or_cond_ne_null
168  ; CHECK: bb.1.entry:
169  ; CHECK:   successors: %bb.2(0x40000000), %bb.3(0x40000000)
170  ; CHECK:   liveins: $w0, $w1, $w2
171  ; CHECK:   [[COPY:%[0-9]+]]:_(s32) = COPY $w0
172  ; CHECK:   [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
173  ; CHECK:   [[COPY2:%[0-9]+]]:_(s32) = COPY $w2
174  ; CHECK:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
175  ; CHECK:   [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(ne), [[COPY]](s32), [[C]]
176  ; CHECK:   [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(ne), [[COPY1]](s32), [[C]]
177  ; CHECK:   [[OR:%[0-9]+]]:_(s1) = G_OR [[ICMP1]], [[ICMP]]
178  ; CHECK:   G_BRCOND [[OR]](s1), %bb.2
179  ; CHECK:   G_BR %bb.3
180  ; CHECK: bb.2.cond_true:
181  ; CHECK:   TCRETURNdi @bar, 0, csr_aarch64_aapcs, implicit $sp
182  ; CHECK: bb.3.UnifiedReturnBlock:
183  ; CHECK:   RET_ReallyLR
184entry:
185  %tmp1 = icmp ne i32 %X, 0
186  %tmp3 = icmp ne i32 %Y, 0
187  %tmp4 = or i1 %tmp3, %tmp1
188  br i1 %tmp4, label %cond_true, label %UnifiedReturnBlock
189
190cond_true:
191  %tmp5 = tail call i32 (...) @bar( )
192  ret void
193
194UnifiedReturnBlock:
195  ret void
196}
197
198; If the branch is unpredictable, don't add another branch
199; regardless of whether they are expensive or not.
200
201define void @unpredictable(i32 %X, i32 %Y, i32 %Z) nounwind {
202  ; CHECK-LABEL: name: unpredictable
203  ; CHECK: bb.1.entry:
204  ; CHECK:   successors: %bb.2(0x40000000), %bb.3(0x40000000)
205  ; CHECK:   liveins: $w0, $w1, $w2
206  ; CHECK:   [[COPY:%[0-9]+]]:_(s32) = COPY $w0
207  ; CHECK:   [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
208  ; CHECK:   [[COPY2:%[0-9]+]]:_(s32) = COPY $w2
209  ; CHECK:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
210  ; CHECK:   [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
211  ; CHECK:   [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY]](s32), [[C]]
212  ; CHECK:   [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY1]](s32), [[C1]]
213  ; CHECK:   [[OR:%[0-9]+]]:_(s1) = G_OR [[ICMP1]], [[ICMP]]
214  ; CHECK:   G_BRCOND [[OR]](s1), %bb.2
215  ; CHECK:   G_BR %bb.3
216  ; CHECK: bb.2.cond_true:
217  ; CHECK:   TCRETURNdi @bar, 0, csr_aarch64_aapcs, implicit $sp
218  ; CHECK: bb.3.UnifiedReturnBlock:
219  ; CHECK:   RET_ReallyLR
220entry:
221  %tmp1 = icmp eq i32 %X, 0
222  %tmp3 = icmp slt i32 %Y, 5
223  %tmp4 = or i1 %tmp3, %tmp1
224  br i1 %tmp4, label %cond_true, label %UnifiedReturnBlock, !unpredictable !0
225
226cond_true:
227  %tmp5 = tail call i32 (...) @bar( )
228  ret void
229
230UnifiedReturnBlock:
231  ret void
232}
233
234!0 = !{}
235