• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# RUN: llc -mtriple=thumbv8a-unknown-linux-gnueabi %s -o - -run-pass=if-converter -debug-only=if-converter | FileCheck %s
2# RUN: llc -mtriple=thumbv7-unknown-linux-gnueabi %s -o - -run-pass=if-converter -debug-only=if-converter 2>%t| FileCheck %s
3# RUN: FileCheck %s < %t --check-prefix=DEBUG
4# REQUIRES: asserts
5
6# When optimising for size, we use a different set of heuristics for
7# if-conversion, which take into account the size of the instructions, not the
8# time taken to execute them. This is more complicated for Thumb, where it if
9# also affected by selection of narrow branch instructions, insertion if IT
10# instructions, and selection of the CB(N)Z instructions.
11
12--- |
13
14  define void @fn1() minsize {
15  entry:
16    unreachable
17  if.then:
18    unreachable
19  if.else:
20    unreachable
21  if.end:
22    unreachable
23  }
24
25  define void @fn2() minsize {
26  entry:
27    unreachable
28  if.then:
29    unreachable
30  if.else:
31    unreachable
32  if.end:
33    unreachable
34  }
35
36  define void @fn3() minsize {
37  entry:
38    unreachable
39  if.then:
40    unreachable
41  if.else:
42    unreachable
43  if.end:
44    unreachable
45  }
46
47  define void @fn4() minsize "target-features"="-thumb-mode" {
48  entry:
49    unreachable
50  if.then:
51    unreachable
52  if.else:
53    unreachable
54  if.end:
55    unreachable
56  }
57
58  define void @fn5() minsize {
59  entry:
60    unreachable
61  if.then:
62    unreachable
63  if.else:
64    unreachable
65  if.end:
66    unreachable
67  }
68
69  define void @fn6() minsize {
70  entry:
71    unreachable
72  if.then:
73    unreachable
74  if.else:
75    unreachable
76  if2.then:
77    unreachable
78  if2.else:
79    unreachable
80  }
81
82  define void @fn7() minsize "target-features"="-thumb-mode" {
83  entry:
84    unreachable
85  if.then:
86    unreachable
87  if.else:
88    unreachable
89  if.end:
90    unreachable
91  }
92
93  define void @fn8() minsize {
94  entry:
95    unreachable
96  if.then:
97    unreachable
98  if.else:
99    unreachable
100  if.end:
101    unreachable
102  }
103
104  define void @fn9() minsize {
105  entry:
106    unreachable
107  if.then:
108    unreachable
109  if.else:
110    unreachable
111  lab1:
112    unreachable
113  }
114...
115---
116name:            fn1
117alignment:       1
118tracksRegLiveness: true
119
120# If-conversion is profitable here because it will remove two branches of 2
121# bytes each (assuming they can become narrow branches later), and will only
122# add 2 bytes with the IT instruction.
123
124# CHECK-LABEL: name:            fn1
125# CHECK:      t2CMPri
126# CHECK-NEXT: t2LDRi12
127# CHECK-NEXT: t2LDRi12
128# CHECK-NEXT: t2LDRi12
129# CHECK-NEXT: t2LDRSHi12
130# CHECK-NEXT: t2MOVi
131
132# DEBUG-LABEL: Ifcvt: function ({{[0-9]+}}) 'fn1'
133# DEBUG: MeetIfcvtSizeLimit(BranchBytes=4, CommonBytes=0, NumPredicatedInstructions=4, ExtraPredicateBytes=2)
134
135body:             |
136  bb.0.entry:
137    successors: %bb.1(0x40000000), %bb.2(0x40000000)
138    liveins: $r0, $r1, $r2, $r3
139
140    t2CMPri killed renamable $r2, 5, 14, $noreg, implicit-def $cpsr
141    t2Bcc %bb.2, 11, killed $cpsr
142
143  bb.1.if.then:
144    successors: %bb.3(0x80000000)
145    liveins: $r0, $r3
146
147    renamable $r0 = t2LDRi12 killed renamable $r0, 0, 14, $noreg
148    t2B %bb.3, 14, $noreg
149
150  bb.2.if.else:
151    successors: %bb.3(0x80000000)
152    liveins: $r1, $r3
153
154    renamable $r0 = t2LDRi12 killed renamable $r1, 0, 14, $noreg
155    renamable $r0 = t2LDRi12 killed renamable $r0, 0, 14, $noreg
156    renamable $r0 = t2LDRSHi12 killed renamable $r0, 0, 14, $noreg
157
158  bb.3.if.end:
159    liveins: $r0, $r3
160
161    renamable $r1 = t2MOVi 0, 14, $noreg, $noreg
162    t2STRi12 killed renamable $r1, killed renamable $r3, 0, 14, $noreg
163    tBX_RET 14, $noreg, implicit $r0
164
165---
166name:            fn2
167alignment:       1
168tracksRegLiveness: true
169
170# If-conversion is not profitable here, because the 5 conditional instructions
171# would require 2 IT instructions.
172
173# CHECK-LABEL: name:            fn2
174# CHECK:      t2CMPri
175# CHECK-NEXT: t2Bcc
176
177# DEBUG-LABEL: Ifcvt: function ({{[0-9]+}}) 'fn2'
178# DEBUG: MeetIfcvtSizeLimit(BranchBytes=4, CommonBytes=0, NumPredicatedInstructions=5, ExtraPredicateBytes=4)
179
180body:             |
181  bb.0.entry:
182    successors: %bb.1(0x40000000), %bb.2(0x40000000)
183    liveins: $r0, $r1, $r2, $r3
184
185    t2CMPri killed renamable $r2, 5, 14, $noreg, implicit-def $cpsr
186    t2Bcc %bb.2, 11, killed $cpsr
187
188  bb.1.if.then:
189    successors: %bb.3(0x80000000)
190    liveins: $r0, $r3
191
192    renamable $r0 = t2LDRi12 killed renamable $r0, 0, 14, $noreg
193    renamable $r0 = t2LDRi12 killed renamable $r0, 0, 14, $noreg
194    t2B %bb.3, 14, $noreg
195
196  bb.2.if.else:
197    successors: %bb.3(0x80000000)
198    liveins: $r1, $r3
199
200    renamable $r0 = t2LDRi12 killed renamable $r1, 0, 14, $noreg
201    renamable $r0 = t2LDRi12 killed renamable $r0, 0, 14, $noreg
202    renamable $r0 = t2LDRSHi12 killed renamable $r0, 0, 14, $noreg
203
204  bb.3.if.end:
205    liveins: $r0, $r3
206
207    renamable $r1 = t2MOVi 0, 14, $noreg, $noreg
208    t2STRi12 killed renamable $r1, killed renamable $r3, 0, 14, $noreg
209    tBX_RET 14, $noreg, implicit $r0
210
211---
212name:            fn3
213alignment:       1
214tracksRegLiveness: true
215
216# Here, the true and false blocks both end in a tBX_RET instruction. One of
217# these will be removed, saving 2 bytes, and the remaining one isn't
218# conditional, so doesn't push us over the limit of 4 instructions in an IT
219# block.
220
221# CHECK-LABEL: name:            fn3
222# CHECK:      t2CMPri
223# CHECK-NEXT: t2LDRi12
224# CHECK-NEXT: t2LDRi12
225# CHECK-NEXT: t2LDRi12
226# CHECK-NEXT: t2LDRSHi12
227# CHECK-NEXT: tBX_RET
228
229# DEBUG-LABEL: Ifcvt: function ({{[0-9]+}}) 'fn3'
230# DEBUG: MeetIfcvtSizeLimit(BranchBytes=2, CommonBytes=2, NumPredicatedInstructions=4, ExtraPredicateBytes=2)
231
232body:             |
233  bb.0.entry:
234    successors: %bb.1(0x40000000), %bb.2(0x40000000)
235    liveins: $r0, $r1, $r2, $r3
236
237    t2CMPri killed renamable $r2, 5, 14, $noreg, implicit-def $cpsr
238    t2Bcc %bb.2, 11, killed $cpsr
239
240  bb.1.if.then:
241    liveins: $r0, $r3
242
243    renamable $r0 = t2LDRi12 killed renamable $r0, 0, 14, $noreg
244    tBX_RET 14, $noreg, implicit $r0
245
246  bb.2.if.else:
247    liveins: $r1, $r3
248
249    renamable $r0 = t2LDRi12 killed renamable $r1, 0, 14, $noreg
250    renamable $r0 = t2LDRi12 killed renamable $r0, 0, 14, $noreg
251    renamable $r0 = t2LDRSHi12 killed renamable $r0, 0, 14, $noreg
252    tBX_RET 14, $noreg, implicit $r0
253
254---
255name:            fn4
256alignment:       1
257tracksRegLiveness: true
258
259# This is the same as fn2, but compiled for ARM, which doesn't need IT
260# instructions, so if-conversion is profitable.
261
262# CHECK-LABEL: name:            fn4
263# CHECK:      CMPri
264# CHECK-NEXT: LDRi12
265# CHECK-NEXT: LDRi12
266# CHECK-NEXT: LDRSH
267# CHECK-NEXT: LDRi12
268# CHECK-NEXT: LDRi12
269# CHECK-NEXT: MOVi
270
271# DEBUG-LABEL: Ifcvt: function ({{[0-9]+}}) 'fn4'
272# DEBUG: MeetIfcvtSizeLimit(BranchBytes=8, CommonBytes=0, NumPredicatedInstructions=5, ExtraPredicateBytes=0)
273
274body:             |
275  bb.0.entry:
276    successors: %bb.1(0x40000000), %bb.2(0x40000000)
277    liveins: $r0, $r1, $r2, $r3
278
279    CMPri killed renamable $r2, 5, 14, $noreg, implicit-def $cpsr
280    Bcc %bb.2, 11, killed $cpsr
281
282  bb.1.if.then:
283    successors: %bb.3(0x80000000)
284    liveins: $r0, $r3
285
286    renamable $r0 = LDRi12 killed renamable $r0, 0, 14, $noreg
287    renamable $r0 = LDRi12 killed renamable $r0, 0, 14, $noreg
288    B %bb.3
289
290  bb.2.if.else:
291    successors: %bb.3(0x80000000)
292    liveins: $r1, $r3
293
294    renamable $r0 = LDRi12 killed renamable $r1, 0, 14, $noreg
295    renamable $r0 = LDRi12 killed renamable $r0, 0, 14, $noreg
296    renamable $r0 = LDRSH killed renamable $r0, $noreg, 0, 14, $noreg
297
298  bb.3.if.end:
299    liveins: $r0, $r3
300
301    renamable $r1 = MOVi 0, 14, $noreg, $noreg
302    STRi12 killed renamable $r1, killed renamable $r3, 0, 14, $noreg
303    BX_RET 14, $noreg, implicit $r0
304
305---
306name:            fn5
307alignment:       1
308tracksRegLiveness: true
309
310# Here, the compare and conditional branch can be turned into a CBZ, so we
311# don't want to if-convert.
312
313# CHECK-LABEL: name:            fn5
314# CHECK: t2CMPri
315# CHECK: t2Bcc
316
317# DEBUG-LABEL: Ifcvt: function ({{[0-9]+}}) 'fn5'
318# DEBUG: MeetIfcvtSizeLimit(BranchBytes=0, CommonBytes=2, NumPredicatedInstructions=4, ExtraPredicateBytes=2)
319
320body:             |
321  bb.0.entry:
322    successors: %bb.1(0x30000000), %bb.2(0x50000000)
323    liveins: $r0, $r1, $r2
324
325    t2CMPri killed renamable $r2, 0, 14, $noreg, implicit-def $cpsr
326    t2Bcc %bb.2, 1, killed $cpsr
327
328  bb.1.if.then:
329    liveins: $r0
330
331    renamable $r0 = t2LDRi12 killed renamable $r0, 0, 14, $noreg
332    tBX_RET 14, $noreg, implicit $r0
333
334  bb.2.if.else:
335    liveins: $r1
336
337    renamable $r0 = t2LDRi12 killed renamable $r1, 0, 14, $noreg
338    renamable $r0 = t2LDRi12 killed renamable $r0, 0, 14, $noreg
339    renamable $r0 = t2LDRSHi12 killed renamable $r0, 0, 14, $noreg
340    tBX_RET 14, $noreg, implicit $r0
341
342---
343name:            fn6
344alignment:       1
345tracksRegLiveness: true
346
347# This is a forked-diamond pattern, we recognise that the conditional branches
348# at the ends of the true and false blocks are the same, and can be shared.
349
350# CHECK-LABEL: name:            fn6
351# CHECK:      t2CMPri
352# CHECK-NEXT: t2LDRSHi12
353# CHECK-NEXT: t2LDRi12
354# CHECK-NEXT: t2LDRi12
355# CHECK-NEXT: t2LDRi12
356# CHECK-NEXT: t2CMPri
357# CHECK-NEXT: t2Bcc
358
359# DEBUG-LABEL: Ifcvt: function ({{[0-9]+}}) 'fn6'
360# DEBUG: MeetIfcvtSizeLimit(BranchBytes=2, CommonBytes=12, NumPredicatedInstructions=4, ExtraPredicateBytes=2)
361
362body:             |
363  bb.0.entry:
364    successors: %bb.1(0x30000000), %bb.2(0x50000000)
365    liveins: $r0, $r1, $r2, $r3
366
367    t2CMPri killed renamable $r2, 4, 14, $noreg, implicit-def $cpsr
368    t2Bcc %bb.2, 1, killed $cpsr
369
370  bb.1.if.then:
371    successors: %bb.3(0x30000000), %bb.4(0x50000000)
372    liveins: $r0, $r1, $r3
373
374    renamable $r0 = t2LDRi12 killed renamable $r0, 0, 14, $noreg
375    renamable $r0 = t2LDRi12 killed renamable $r0, 0, 14, $noreg
376    renamable $r0 = t2LDRi12 killed renamable $r0, 0, 14, $noreg
377    t2CMPri renamable $r0, 0, 14, $noreg, implicit-def $cpsr
378    t2Bcc %bb.3.if2.then, 1, killed $cpsr
379    t2B %bb.4.if2.else, 14, $noreg
380
381  bb.2.if.else:
382    successors: %bb.3(0x30000000), %bb.4(0x50000000)
383    liveins: $r0, $r1, $r3
384
385    renamable $r0 = t2LDRSHi12 killed renamable $r0, 0, 14, $noreg
386    t2CMPri renamable $r0, 0, 14, $noreg, implicit-def $cpsr
387    t2Bcc %bb.3.if2.then, 1, killed $cpsr
388    t2B %bb.4.if2.else, 14, $noreg
389
390  bb.3.if2.then:
391    liveins: $r0, $r1, $r3
392
393    t2STRi12 killed renamable $r1, killed renamable $r3, 0, 14, $noreg
394    tBX_RET 14, $noreg, implicit $r0
395
396  bb.4.if2.else:
397    liveins: $r0
398
399    tBX_RET 14, $noreg, implicit $r0
400
401---
402name:            fn7
403alignment:       1
404tracksRegLiveness: true
405
406# When compiling for ARM, it would be good for code size to generate very long
407# runs of conditional instructions, but we put an (arbitrary) limit on this to
408# avoid generating code which is very bad for performance, and only saves a few
409# bytes of code size.
410
411# CHECK-LABEL: name:            fn7
412# CHECK:      CMPri
413# CHECK-NEXT: Bcc
414
415body:             |
416  bb.0.entry:
417    successors: %bb.1(0x40000000), %bb.2(0x40000000)
418    liveins: $r0, $r1, $r2, $r3
419
420    CMPri killed renamable $r2, 5, 14, $noreg, implicit-def $cpsr
421    Bcc %bb.2, 11, killed $cpsr
422
423  bb.1.if.then:
424    successors: %bb.3(0x80000000)
425    liveins: $r0, $r3
426
427    renamable $r0 = LDRi12 killed renamable $r0, 0, 14, $noreg
428    renamable $r0 = LDRi12 killed renamable $r0, 0, 14, $noreg
429    renamable $r0 = LDRi12 killed renamable $r0, 0, 14, $noreg
430    renamable $r0 = LDRi12 killed renamable $r0, 0, 14, $noreg
431    renamable $r0 = LDRi12 killed renamable $r0, 0, 14, $noreg
432    renamable $r0 = LDRi12 killed renamable $r0, 0, 14, $noreg
433    renamable $r0 = LDRi12 killed renamable $r0, 0, 14, $noreg
434    renamable $r0 = LDRi12 killed renamable $r0, 0, 14, $noreg
435    renamable $r0 = LDRi12 killed renamable $r0, 0, 14, $noreg
436    renamable $r0 = LDRi12 killed renamable $r0, 0, 14, $noreg
437    renamable $r0 = LDRi12 killed renamable $r0, 0, 14, $noreg
438    renamable $r0 = LDRi12 killed renamable $r0, 0, 14, $noreg
439    renamable $r0 = LDRi12 killed renamable $r0, 0, 14, $noreg
440    B %bb.3
441
442  bb.2.if.else:
443    successors: %bb.3(0x80000000)
444    liveins: $r1, $r3
445
446    renamable $r0 = LDRi12 killed renamable $r1, 0, 14, $noreg
447    renamable $r0 = LDRi12 killed renamable $r0, 0, 14, $noreg
448    renamable $r0 = LDRSH killed renamable $r0, $noreg, 0, 14, $noreg
449
450  bb.3.if.end:
451    liveins: $r0, $r3
452
453    renamable $r1 = MOVi 0, 14, $noreg, $noreg
454    STRi12 killed renamable $r1, killed renamable $r3, 0, 14, $noreg
455    BX_RET 14, $noreg, implicit $r0
456
457---
458name:            fn8
459alignment:       1
460tracksRegLiveness: true
461
462# The first t2LDRi12 instruction in each branch is the same, so one copy of it
463# will be removed, and it doesn't need to be predicated, keeping us under the 4
464# instruction IT block limit.
465
466# CHECK-LABEL: name:            fn8
467# CHECK:      t2CMPri
468# CHECK-NEXT: t2LDRi12
469# CHECK-NEXT: t2LDRi12
470# CHECK-NEXT: t2LDRi12
471# CHECK-NEXT: t2LDRi12
472# CHECK-NEXT: t2LDRSHi12
473# CHECK-NEXT: t2MOVi
474
475# DEBUG-LABEL: Ifcvt: function ({{[0-9]+}}) 'fn8'
476# DEBUG: MeetIfcvtSizeLimit(BranchBytes=4, CommonBytes=4, NumPredicatedInstructions=4, ExtraPredicateBytes=2)
477
478body:             |
479  bb.0.entry:
480    successors: %bb.1(0x40000000), %bb.2(0x40000000)
481    liveins: $r0, $r1, $r2, $r3
482
483    t2CMPri killed renamable $r2, 5, 14, $noreg, implicit-def $cpsr
484    t2Bcc %bb.2, 11, killed $cpsr
485
486  bb.1.if.then:
487    successors: %bb.3(0x80000000)
488    liveins: $r0, $r3
489
490    renamable $r0 = t2LDRi12 killed renamable $r0, 0, 14, $noreg
491    renamable $r0 = t2LDRi12 killed renamable $r0, 4, 14, $noreg
492    t2B %bb.3, 14, $noreg
493
494  bb.2.if.else:
495    successors: %bb.3(0x80000000)
496    liveins: $r0, $r3
497
498    renamable $r0 = t2LDRi12 killed renamable $r0, 0, 14, $noreg
499    renamable $r0 = t2LDRi12 killed renamable $r0, 0, 14, $noreg
500    renamable $r0 = t2LDRi12 killed renamable $r0, 0, 14, $noreg
501    renamable $r0 = t2LDRSHi12 killed renamable $r0, 0, 14, $noreg
502
503  bb.3.if.end:
504    liveins: $r0, $r3
505
506    renamable $r1 = t2MOVi 0, 14, $noreg, $noreg
507    t2STRi12 killed renamable $r1, killed renamable $r3, 0, 14, $noreg
508    tBX_RET 14, $noreg, implicit $r0
509
510---
511name:            fn9
512alignment:       2
513tracksRegLiveness: true
514
515# The INLINEASM_BR instructions aren't analyzable, but they are identical so we
516# can still do diamond if-conversion. From a code-size POV, they are common
517# instructions, so one will be removed, and they don't need an IT block slot.
518
519# CHECK-LABEL: name:            fn9
520# CHECK:      tCMPi8
521# CHECK-NEXT: tLDRi
522# CHECK-NEXT: tLDRi
523# CHECK-NEXT: tLDRi
524# CHECK-NEXT: t2LDRSHi12
525# CHECK-NEXT: INLINEASM_BR
526
527# DEBUG-LABEL: Ifcvt: function ({{[0-9]+}}) 'fn9'
528# DEBUG: MeetIfcvtSizeLimit(BranchBytes=2, CommonBytes=8, NumPredicatedInstructions=4, ExtraPredicateBytes=2)
529
530body:             |
531  bb.0.entry:
532    successors: %bb.1(0x30000000), %bb.3(0x50000000)
533    liveins: $r0, $r1, $r2
534
535    tCMPi8 renamable $r2, 42, 14, $noreg, implicit-def $cpsr
536    t2Bcc %bb.3, 1, killed $cpsr
537
538  bb.1.if.then:
539    successors:  %bb.5(0x7fffffff)
540    liveins: $r0, $r2
541
542    renamable $r0 = tLDRi killed renamable $r0, 0, 14, $noreg
543    INLINEASM_BR &"b ${0:l}", 1, 13, blockaddress(@fn9, %ir-block.lab1)
544    tBX_RET 14, $noreg, implicit $r2
545
546  bb.3.if.else:
547    successors: %bb.5(0x7fffffff)
548    liveins: $r1, $r2
549
550    renamable $r0 = tLDRi killed renamable $r1, 0, 14, $noreg
551    renamable $r0 = tLDRi killed renamable $r0, 0, 14, $noreg
552    renamable $r0 = t2LDRSHi12 killed renamable $r0, 0, 14, $noreg
553    INLINEASM_BR &"b ${0:l}", 1, 13, blockaddress(@fn9, %ir-block.lab1)
554    tBX_RET 14, $noreg, implicit $r2
555
556  bb.5.lab1 (address-taken):
557    liveins: $r0
558
559    renamable $r0, dead $cpsr = nsw tADDi8 killed renamable $r0, 5, 14, $noreg
560    tBX_RET 14, $noreg, implicit $r0
561...
562