1# RUN: llc -O0 -run-pass=arm-low-overhead-loops -o - -verify-machineinstrs %s | FileCheck %s
2# CHECK-NOT: WLS
3# CHECK-NOT: WhileLoopStart
4
5--- |
6  ; ModuleID = '/home/sampar01/src/llvm/test/CodeGen/Thumb2/LowOverheadLoops/while-negative-offset.ll'
7  source_filename = "while-size-limit.ll"
8  target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
9  target triple = "thumbv8.1m.main"
10
11  define void @size_limit(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %N) #0 {
12  entry:
13    br label %while
14
15  for.cond.cleanup:                                 ; preds = %while, %for.body
16    ret void
17
18  for.body.preheader:                               ; preds = %while
19    %scevgep = getelementptr i32, i32* %a, i32 -1
20    %scevgep4 = getelementptr i32, i32* %c, i32 -1
21    %scevgep8 = getelementptr i32, i32* %b, i32 -1
22    br label %for.body
23
24  for.body:                                         ; preds = %for.body, %for.body.preheader
25    %lsr.iv9 = phi i32* [ %scevgep8, %for.body.preheader ], [ %scevgep10, %for.body ]
26    %lsr.iv5 = phi i32* [ %scevgep4, %for.body.preheader ], [ %scevgep6, %for.body ]
27    %lsr.iv1 = phi i32* [ %scevgep, %for.body.preheader ], [ %scevgep2, %for.body ]
28    %0 = phi i32 [ %N, %for.body.preheader ], [ %3, %for.body ]
29    %scevgep11 = getelementptr i32, i32* %lsr.iv9, i32 1
30    %1 = load i32, i32* %scevgep11, align 4
31    %scevgep7 = getelementptr i32, i32* %lsr.iv5, i32 1
32    %2 = load i32, i32* %scevgep7, align 4
33    %mul = mul nsw i32 %2, %1
34    %scevgep3 = getelementptr i32, i32* %lsr.iv1, i32 1
35    store i32 %mul, i32* %scevgep3, align 4
36    %scevgep2 = getelementptr i32, i32* %lsr.iv1, i32 1
37    %scevgep6 = getelementptr i32, i32* %lsr.iv5, i32 1
38    %scevgep10 = getelementptr i32, i32* %lsr.iv9, i32 1
39    %3 = call i32 @llvm.loop.decrement.reg.i32.i32.i32(i32 %0, i32 1)
40    %4 = icmp ne i32 %3, 0
41    br i1 %4, label %for.body, label %for.cond.cleanup
42
43  while:                                            ; preds = %entry
44    %cmp8 = call i1 @llvm.test.set.loop.iterations.i32(i32 %N)
45    br i1 %cmp8, label %for.body.preheader, label %for.cond.cleanup
46  }
47
48  ; Function Attrs: nounwind
49  declare i32 @llvm.arm.space(i32 immarg, i32) #1
50  ; Function Attrs: noduplicate nounwind
51  declare i1 @llvm.test.set.loop.iterations.i32(i32) #2
52  ; Function Attrs: noduplicate nounwind
53  declare i32 @llvm.loop.decrement.reg.i32.i32.i32(i32, i32) #2
54
55  attributes #0 = { "target-features"="+lob" }
56  attributes #1 = { nounwind }
57  attributes #2 = { noduplicate nounwind }
58
59...
60---
61name:            size_limit
62alignment:       1
63exposesReturnsTwice: false
64legalized:       false
65regBankSelected: false
66selected:        false
67failedISel:      false
68tracksRegLiveness: false
69hasWinCFI:       false
70registers:       []
71liveins:
72  - { reg: '$r0', virtual-reg: '' }
73  - { reg: '$r1', virtual-reg: '' }
74  - { reg: '$r2', virtual-reg: '' }
75  - { reg: '$r3', virtual-reg: '' }
76frameInfo:
77  isFrameAddressTaken: false
78  isReturnAddressTaken: false
79  hasStackMap:     false
80  hasPatchPoint:   false
81  stackSize:       40
82  offsetAdjustment: 0
83  maxAlignment:    4
84  adjustsStack:    false
85  hasCalls:        false
86  stackProtector:  ''
87  maxCallFrameSize: 0
88  cvBytesOfCalleeSavedRegisters: 0
89  hasOpaqueSPAdjustment: false
90  hasVAStart:      false
91  hasMustTailInVarArgFunc: false
92  localFrameSize:  0
93  savePoint:       ''
94  restorePoint:    ''
95fixedStack:      []
96stack:
97  - { id: 0, name: '', type: spill-slot, offset: -12, size: 4, alignment: 4,
98      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
99      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
100  - { id: 1, name: '', type: spill-slot, offset: -16, size: 4, alignment: 4,
101      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
102      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
103  - { id: 2, name: '', type: spill-slot, offset: -20, size: 4, alignment: 4,
104      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
105      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
106  - { id: 3, name: '', type: spill-slot, offset: -24, size: 4, alignment: 4,
107      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
108      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
109  - { id: 4, name: '', type: spill-slot, offset: -28, size: 4, alignment: 4,
110      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
111      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
112  - { id: 5, name: '', type: spill-slot, offset: -32, size: 4, alignment: 4,
113      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
114      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
115  - { id: 6, name: '', type: spill-slot, offset: -36, size: 4, alignment: 4,
116      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
117      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
118  - { id: 7, name: '', type: spill-slot, offset: -40, size: 4, alignment: 4,
119      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
120      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
121  - { id: 8, name: '', type: spill-slot, offset: -4, size: 4, alignment: 4,
122      stack-id: default, callee-saved-register: '$lr', callee-saved-restored: false,
123      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
124  - { id: 9, name: '', type: spill-slot, offset: -8, size: 4, alignment: 4,
125      stack-id: default, callee-saved-register: '$r4', callee-saved-restored: true,
126      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
127callSites:       []
128constants:       []
129machineFunctionInfo: {}
130body:             |
131  bb.0.entry:
132    successors: %bb.4(0x80000000)
133
134    frame-setup tPUSH 14, $noreg, killed $r4, killed $lr, implicit-def $sp, implicit $sp
135    frame-setup CFI_INSTRUCTION def_cfa_offset 8
136    frame-setup CFI_INSTRUCTION offset $lr, -4
137    frame-setup CFI_INSTRUCTION offset $r4, -8
138    $sp = frame-setup tSUBspi $sp, 8, 14, $noreg
139    frame-setup CFI_INSTRUCTION def_cfa_offset 40
140    tSTRspi killed $r3, $sp, 7, 14, $noreg :: (store 4 into %stack.0)
141    tSTRspi killed $r2, $sp, 6, 14, $noreg :: (store 4 into %stack.1)
142    tSTRspi killed $r1, $sp, 5, 14, $noreg :: (store 4 into %stack.2)
143    tSTRspi killed $r0, $sp, 4, 14, $noreg :: (store 4 into %stack.3)
144    tB %bb.4, 14, $noreg
145
146  bb.1.for.cond.cleanup:
147    $sp = tADDspi $sp, 8, 14, $noreg
148    tPOP_RET 14, $noreg, def $r4, def $pc
149
150  bb.2.for.body.preheader:
151    successors: %bb.3(0x80000000)
152
153    $r0 = tLDRspi $sp, 4, 14, $noreg :: (load 4 from %stack.3)
154    renamable $r1, dead $cpsr = tSUBi3 killed renamable $r0, 4, 14, $noreg
155    $r2 = tLDRspi $sp, 6, 14, $noreg :: (load 4 from %stack.1)
156    renamable $r3, dead $cpsr = tSUBi3 killed renamable $r2, 4, 14, $noreg
157    $r12 = t2LDRi12 $sp, 20, 14, $noreg :: (load 4 from %stack.2)
158    renamable $lr = t2SUBri killed renamable $r12, 4, 14, $noreg, $noreg
159    $r4 = tLDRspi $sp, 7, 14, $noreg :: (load 4 from %stack.0)
160    t2STRi12 killed $lr, $sp, 12, 14, $noreg :: (store 4 into %stack.4)
161    tSTRspi killed $r3, $sp, 2, 14, $noreg :: (store 4 into %stack.5)
162    tSTRspi killed $r1, $sp, 1, 14, $noreg :: (store 4 into %stack.6)
163    tSTRspi killed $r4, $sp, 0, 14, $noreg :: (store 4 into %stack.7)
164    tB %bb.3, 14, $noreg
165
166  bb.3.for.body:
167    successors: %bb.3(0x40000000), %bb.1(0x40000000)
168
169    $r0 = tLDRspi $sp, 0, 14, $noreg :: (load 4 from %stack.7)
170    $r1 = tLDRspi $sp, 1, 14, $noreg :: (load 4 from %stack.6)
171    $r2 = tLDRspi $sp, 2, 14, $noreg :: (load 4 from %stack.5)
172    $r3 = tLDRspi $sp, 3, 14, $noreg :: (load 4 from %stack.4)
173    renamable $r12, renamable $r3 = t2LDR_PRE renamable $r3, 4, 14, $noreg :: (load 4 from %ir.scevgep11)
174    renamable $lr, renamable $r2 = t2LDR_PRE renamable $r2, 4, 14, $noreg :: (load 4 from %ir.scevgep7)
175    renamable $r12 = nsw t2MUL killed renamable $lr, killed renamable $r12, 14, $noreg
176    early-clobber renamable $r1 = t2STR_PRE killed renamable $r12, renamable $r1, 4, 14, $noreg :: (store 4 into %ir.scevgep3)
177    $lr = tMOVr killed $r0, 14, $noreg
178    renamable $lr = t2LoopDec killed renamable $lr, 1
179    $r0 = tMOVr $lr, 14, $noreg
180    tSTRspi killed $r0, $sp, 0, 14, $noreg :: (store 4 into %stack.7)
181    tSTRspi killed $r1, $sp, 1, 14, $noreg :: (store 4 into %stack.6)
182    tSTRspi killed $r2, $sp, 2, 14, $noreg :: (store 4 into %stack.5)
183    tSTRspi killed $r3, $sp, 3, 14, $noreg :: (store 4 into %stack.4)
184    t2LoopEnd killed renamable $lr, %bb.3, implicit-def dead $cpsr
185    tB %bb.1, 14, $noreg
186
187  bb.4.while:
188    successors: %bb.2(0x40000000), %bb.1(0x40000000)
189
190    $r0 = tLDRspi $sp, 7, 14, $noreg :: (load 4 from %stack.0)
191    t2WhileLoopStart killed renamable $r0, %bb.1, implicit-def dead $cpsr
192    tB %bb.2, 14, $noreg
193
194...
195
196
197