1# RUN: llc -mtriple=thumbv8.1m.main -run-pass=arm-low-overhead-loops %s --verify-machineinstrs -o - | FileCheck %s
2
3# CHECK: name: non_loop
4# CHECK: bb.0.entry:
5# CHECK:   tBcc %bb.2, 3
6# CHECK: bb.1.not.preheader:
7# CHECK:   t2CMPri renamable $lr, 0, 14
8# CHECK:   tBcc %bb.4, 0
9# CHECK:   tB %bb.2
10# CHECK: bb.3.while.body:
11# CHECK:   t2CMPri renamable $lr, 0, 14
12# CHECK:   tBcc %bb.3, 1
13# CHECK:   tB %bb.4
14# CHECK: bb.4.while.end:
15
16--- |
17  target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
18  target triple = "thumbv8.1m.main"
19
20  define void @non_loop(i16* nocapture %a, i16* nocapture readonly %b, i32 %N) {
21  entry:
22    %cmp = icmp ugt i32 %N, 2
23    br i1 %cmp, label %not.preheader, label %while.body.preheader
24
25  not.preheader:                                    ; preds = %entry
26    %test = call i1 @llvm.test.set.loop.iterations.i32(i32 %N)
27    br i1 %test, label %while.body.preheader, label %while.end
28
29  while.body.preheader:                             ; preds = %not.preheader, %entry
30    %scevgep = getelementptr i16, i16* %a, i32 -1
31    %scevgep3 = getelementptr i16, i16* %b, i32 -1
32    br label %while.body
33
34  while.body:                                       ; preds = %while.body, %while.body.preheader
35    %lsr.iv4 = phi i16* [ %scevgep3, %while.body.preheader ], [ %scevgep5, %while.body ]
36    %lsr.iv = phi i16* [ %scevgep, %while.body.preheader ], [ %scevgep1, %while.body ]
37    %count = phi i32 [ %count.next, %while.body ], [ %N, %while.body.preheader ]
38    %scevgep7 = getelementptr i16, i16* %lsr.iv, i32 1
39    %scevgep4 = getelementptr i16, i16* %lsr.iv4, i32 1
40    %load = load i16, i16* %scevgep4, align 2
41    store i16 %load, i16* %scevgep7, align 2
42    %count.next = call i32 @llvm.loop.decrement.reg.i32.i32.i32(i32 %count, i32 1)
43    %cmp1 = icmp ne i32 %count.next, 0
44    %scevgep1 = getelementptr i16, i16* %lsr.iv, i32 1
45    %scevgep5 = getelementptr i16, i16* %lsr.iv4, i32 1
46    br i1 %cmp1, label %while.body, label %while.end
47
48  while.end:                                        ; preds = %while.body, %not.preheader
49    ret void
50  }
51
52  declare i1 @llvm.test.set.loop.iterations.i32(i32) #0
53  declare i32 @llvm.loop.decrement.reg.i32.i32.i32(i32, i32) #0
54  declare void @llvm.stackprotector(i8*, i8**) #1
55
56  attributes #0 = { noduplicate nounwind }
57  attributes #1 = { nounwind }
58
59...
60---
61name:            non_loop
62alignment:       2
63exposesReturnsTwice: false
64legalized:       false
65regBankSelected: false
66selected:        false
67failedISel:      false
68tracksRegLiveness: true
69hasWinCFI:       false
70registers:       []
71liveins:
72  - { reg: '$r0', virtual-reg: '' }
73  - { reg: '$r1', virtual-reg: '' }
74  - { reg: '$r2', virtual-reg: '' }
75frameInfo:
76  isFrameAddressTaken: false
77  isReturnAddressTaken: false
78  hasStackMap:     false
79  hasPatchPoint:   false
80  stackSize:       8
81  offsetAdjustment: 0
82  maxAlignment:    4
83  adjustsStack:    false
84  hasCalls:        false
85  stackProtector:  ''
86  maxCallFrameSize: 0
87  cvBytesOfCalleeSavedRegisters: 0
88  hasOpaqueSPAdjustment: false
89  hasVAStart:      false
90  hasMustTailInVarArgFunc: false
91  localFrameSize:  0
92  savePoint:       ''
93  restorePoint:    ''
94fixedStack:      []
95stack:
96  - { id: 0, name: '', type: spill-slot, offset: -4, size: 4, alignment: 4,
97      stack-id: default, callee-saved-register: '$lr', callee-saved-restored: false,
98      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
99  - { id: 1, name: '', type: spill-slot, offset: -8, size: 4, alignment: 4,
100      stack-id: default, callee-saved-register: '$r7', callee-saved-restored: true,
101      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
102callSites:       []
103constants:       []
104machineFunctionInfo: {}
105body:             |
106  bb.0.entry:
107    successors: %bb.1(0x40000000), %bb.2(0x40000000)
108    liveins: $r0, $r1, $r2, $r7, $lr
109
110    frame-setup tPUSH 14, $noreg, killed $r7, killed $lr, implicit-def $sp, implicit $sp
111    frame-setup CFI_INSTRUCTION def_cfa_offset 8
112    frame-setup CFI_INSTRUCTION offset $lr, -4
113    frame-setup CFI_INSTRUCTION offset $r7, -8
114    $lr = tMOVr $r2, 14, $noreg
115    tCMPi8 killed $r2, 3, 14, $noreg, implicit-def $cpsr
116    tBcc %bb.2, 3, killed $cpsr
117
118  bb.1.not.preheader:
119    successors: %bb.2(0x40000000), %bb.4(0x40000000)
120    liveins: $lr, $r0, $r1
121
122    t2WhileLoopStart renamable $lr, %bb.4, implicit-def dead $cpsr
123    tB %bb.2, 14, $noreg
124
125  bb.2.while.body.preheader:
126    successors: %bb.3(0x80000000)
127    liveins: $lr, $r0, $r1
128
129    renamable $r1, dead $cpsr = tSUBi8 killed renamable $r1, 2, 14, $noreg
130    renamable $r0, dead $cpsr = tSUBi8 killed renamable $r0, 2, 14, $noreg
131
132  bb.3.while.body:
133    successors: %bb.3(0x7c000000), %bb.4(0x04000000)
134    liveins: $lr, $r0, $r1
135
136    renamable $r2, renamable $r1 = t2LDRH_PRE killed renamable $r1, 2, 14, $noreg :: (load 2 from %ir.scevgep4)
137    early-clobber renamable $r0 = t2STRH_PRE killed renamable $r2, killed renamable $r0, 2, 14, $noreg :: (store 2 into %ir.scevgep7)
138    renamable $lr = t2LoopDec killed renamable $lr, 1
139    t2LoopEnd renamable $lr, %bb.3, implicit-def dead $cpsr
140    tB %bb.4, 14, $noreg
141
142  bb.4.while.end:
143    tPOP_RET 14, $noreg, def $r7, def $pc
144
145...
146