Skip to content

Commit 6ed97fd

Browse files
committed
[Z80] Add large frame index rewrite tests
1 parent ac2fcfb commit 6ed97fd

2 files changed

Lines changed: 390 additions & 0 deletions

File tree

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
# RUN: llc -mtriple=ez80 -run-pass=prologepilog -o - %s | FileCheck %s
2+
3+
# Check that large frame-index rewrites can keep a legal nonzero final
4+
# displacement instead of fully chunking the address adjustment into LEAs.
5+
6+
--- |
7+
; ModuleID = '<stdin>'
8+
source_filename = "/tmp/ez80-large-frame-repro/repro.c"
9+
target datalayout = "e-m:z-p:24:8-p1:16:8-p2:8:8-p3:16:8-p4:24:8-i16:8-i24:8-i32:8-i48:8-i64:8-i96:8-f32:8-f64:8-a:8-n8:16:24-S8"
10+
target triple = "ez80"
11+
12+
@gp = dso_local local_unnamed_addr global ptr null, align 1
13+
@sink = dso_local global i16 0, align 2
14+
15+
; Function Attrs: minsize nofree norecurse nounwind optsize memory(readwrite, argmem: read)
16+
define dso_local i16 @repro(ptr nocapture noundef readonly %p, i16 noundef %n) local_unnamed_addr #0 {
17+
entry:
18+
%pad = alloca [128 x i16], align 2
19+
call void @llvm.lifetime.start.p0(i64 256, ptr nonnull %pad) #4
20+
store ptr %pad, ptr @gp, align 1, !tbaa !2
21+
%wide.trip.count = zext i16 %n to i24
22+
br label %for.cond
23+
24+
for.cond: ; preds = %for.body, %entry
25+
%lsr.iv2 = phi i24 [ %lsr.iv.next3, %for.body ], [ %wide.trip.count, %entry ]
26+
%lsr.iv1 = phi i16 [ %lsr.iv.next, %for.body ], [ 36, %entry ]
27+
%lsr.iv = phi ptr [ %scevgep, %for.body ], [ %p, %entry ]
28+
%exitcond.not = icmp eq i24 %lsr.iv2, 0
29+
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
30+
31+
for.cond.cleanup: ; preds = %for.cond
32+
%0 = load volatile i16, ptr @sink, align 2, !tbaa !6
33+
%arrayidx14 = getelementptr inbounds i8, ptr %pad, i24 246
34+
%1 = load volatile i16, ptr %arrayidx14, align 2, !tbaa !6
35+
%add16 = add i16 %1, %0
36+
call void @llvm.lifetime.end.p0(i64 256, ptr nonnull %pad) #4
37+
ret i16 %add16
38+
39+
for.body: ; preds = %for.cond
40+
%sunkaddr = getelementptr inbounds i8, ptr %pad, i24 250
41+
store volatile i16 %lsr.iv1, ptr %sunkaddr, align 2, !tbaa !6
42+
%sunkaddr4 = getelementptr inbounds i8, ptr %pad, i24 248
43+
%2 = load volatile i16, ptr %sunkaddr4, align 2, !tbaa !6
44+
%3 = load i16, ptr %lsr.iv, align 2, !tbaa !6
45+
%add9 = add i16 %3, %2
46+
%4 = load volatile i16, ptr @sink, align 2, !tbaa !6
47+
%add11 = add i16 %add9, %4
48+
store volatile i16 %add11, ptr @sink, align 2, !tbaa !6
49+
%scevgep = getelementptr i8, ptr %lsr.iv, i24 2
50+
%lsr.iv.next = add i16 %lsr.iv1, 1
51+
%lsr.iv.next3 = add nsw i24 %lsr.iv2, -1
52+
br label %for.cond, !llvm.loop !8
53+
}
54+
55+
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
56+
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1
57+
58+
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
59+
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1
60+
61+
declare void @_Unwind_SjLj_Register(ptr)
62+
63+
declare void @_Unwind_SjLj_Unregister(ptr)
64+
65+
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none)
66+
declare ptr @llvm.frameaddress.p0(i32 immarg) #2
67+
68+
; Function Attrs: nocallback nofree nosync nounwind willreturn
69+
declare ptr @llvm.stacksave.p0() #3
70+
71+
; Function Attrs: nocallback nofree nosync nounwind willreturn
72+
declare void @llvm.stackrestore.p0(ptr) #3
73+
74+
; Function Attrs: nounwind
75+
declare void @llvm.eh.sjlj.setup.dispatch() #4
76+
77+
; Function Attrs: nounwind memory(none)
78+
declare ptr @llvm.eh.sjlj.lsda() #5
79+
80+
; Function Attrs: nounwind memory(none)
81+
declare void @llvm.eh.sjlj.callsite(i32 immarg) #5
82+
83+
; Function Attrs: nounwind
84+
declare void @llvm.eh.sjlj.functioncontext(ptr) #4
85+
86+
attributes #0 = { minsize nofree norecurse nounwind optsize memory(readwrite, argmem: read) "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
87+
attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
88+
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(none) }
89+
attributes #3 = { nocallback nofree nosync nounwind willreturn }
90+
attributes #4 = { nounwind }
91+
attributes #5 = { nounwind memory(none) }
92+
93+
!llvm.module.flags = !{!0}
94+
!llvm.ident = !{!1}
95+
96+
!0 = !{i32 1, !"wchar_size", i32 2}
97+
!1 = !{!"clang version 19.1.0 (git@github.com:Sightem/llvm-project.git ff9761906b160716d7d53f5641d52d409fdb8766)"}
98+
!2 = !{!3, !3, i64 0}
99+
!3 = !{!"any pointer", !4, i64 0}
100+
!4 = !{!"omnipotent char", !5, i64 0}
101+
!5 = !{!"Simple C/C++ TBAA"}
102+
!6 = !{!7, !7, i64 0}
103+
!7 = !{!"short", !4, i64 0}
104+
!8 = distinct !{!8, !9}
105+
!9 = !{!"llvm.loop.mustprogress"}
106+
107+
...
108+
---
109+
# CHECK-LABEL: name: repro
110+
name: repro
111+
alignment: 1
112+
legalized: true
113+
regBankSelected: true
114+
selected: true
115+
tracksRegLiveness: true
116+
tracksDebugUserValues: true
117+
frameInfo:
118+
maxAlignment: 2
119+
localFrameSize: 256
120+
fixedStack:
121+
- { id: 0, offset: 3, size: 2, alignment: 1, isImmutable: true }
122+
- { id: 1, size: 3, alignment: 1, isImmutable: true }
123+
stack:
124+
- { id: 0, name: pad, size: 256, alignment: 2, local-offset: -256 }
125+
- { id: 1, type: spill-slot, size: 3, alignment: 1 }
126+
- { id: 2, type: spill-slot, size: 2, alignment: 1 }
127+
machineFunctionInfo: {}
128+
body: |
129+
bb.0.entry:
130+
$uhl = LD24ro %fixed-stack.1, 0 :: (invariant load (p0) from %fixed-stack.1, align 1)
131+
LD24or %stack.1, 0, killed $uhl
132+
$uhl = LD24ro %fixed-stack.0, 0 :: (invariant load (s16) from %fixed-stack.0, align 1)
133+
$iy = LD16ri 36
134+
$ude = LEA24ro %stack.0.pad, 0
135+
LD24mr @gp, killed $ude :: (store (p0) into @gp, align 1, !tbaa !2)
136+
$ubc = LD24r0 implicit-def dead $f
137+
$bc = COPY $hl, implicit killed $uhl, implicit killed $ubc, implicit-def $ubc
138+
JQ %bb.1
139+
140+
bb.1.for.cond:
141+
liveins: $iy, $ubc
142+
143+
Cmp24a0 $ubc, implicit-def $f, implicit-def dead $uhl
144+
JQCC %bb.3, 0, implicit killed $f
145+
JQ %bb.2
146+
147+
bb.2.for.cond.cleanup:
148+
$uhl = LD24ri @sink
149+
$de = LD88rp killed $uhl :: (volatile dereferenceable load (s16) from @sink, !tbaa !6)
150+
$hl = LD88ro %stack.0.pad, 246 :: (volatile dereferenceable load (s16) from %ir.arrayidx14, !tbaa !6)
151+
$hl = ADD16ao killed $hl, killed $de, implicit-def dead $f
152+
RET24 implicit-def $spl, implicit $spl, implicit $hl
153+
154+
bb.3.for.body:
155+
liveins: $iy, $ubc
156+
157+
LD88or %stack.0.pad, 250, $iy :: (volatile store (s16) into %ir.sunkaddr, !tbaa !6)
158+
$de = LD88ro %stack.0.pad, 248 :: (volatile dereferenceable load (s16) from %ir.sunkaddr4, !tbaa !6)
159+
LD88or %stack.2, 0, killed $iy
160+
$uhl = LD24ro %stack.1, 0
161+
$uiy = LD24rp killed $uhl :: (load (s16) from %ir.lsr.iv, !tbaa !6)
162+
$uhl = COPY killed $uiy
163+
$hl = ADD16ao $hl, killed $de, implicit-def dead $f, implicit killed $uhl, implicit-def $uhl
164+
$uiy = LD24ri @sink
165+
$de = LD88rp killed $uiy :: (volatile dereferenceable load (s16) from @sink, !tbaa !6)
166+
$hl = ADD16ao $hl, killed $de, implicit-def dead $f, implicit killed $uhl, implicit-def $uhl
167+
$ude = COPY killed $uhl
168+
$uhl = LD24ri @sink
169+
LD88pr killed $uhl, $de, implicit killed $ude :: (volatile store (s16) into @sink, !tbaa !6)
170+
$uiy = LD24ro %stack.1, 0
171+
$uiy = LEA24ro killed $uiy, 2
172+
LD24or %stack.1, 0, killed $uiy
173+
$iy = LD88ro %stack.2, 0
174+
$iy = INC16r killed $iy
175+
$ubc = DEC24r killed $ubc
176+
JQ %bb.1
177+
178+
...
179+
180+
# CHECK: bb.3.for.body:
181+
# CHECK-NEXT: successors: %bb.1(0x80000000)
182+
# CHECK-NEXT: liveins: $iy, $ubc
183+
# CHECK: LD88or $uix, -13, $iy
184+
# CHECK-NEXT: $de = LD88ro $uix, -15
185+
# CHECK-NEXT: PUSH24r $uix, implicit-def $spl, implicit $spl
186+
# CHECK-NEXT: $uix = LEA24ro $uix, -128
187+
# CHECK-NEXT: $uix = LEA24ro $uix, -12
188+
# CHECK-NEXT: LD88or $uix, -128, killed $iy
189+
# CHECK-NEXT: $uix = POP24r implicit-def $spl, implicit $spl
190+
# CHECK-NEXT: $uiy = LEA24ro $uix, 0
191+
# CHECK-NEXT: $uiy = LEA24ro $uiy, -128
192+
# CHECK-NEXT: $uiy = LEA24ro $uiy, -10
193+
# CHECK-NEXT: $uhl = LD24ro $uiy, -128
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
# RUN: llc -mtriple=ez80 -run-pass=prologepilog -o - %s | FileCheck %s
2+
3+
# Check that once the remaining LEA chain is large enough, PEI rewrites switch
4+
# to a controlled manual spill plus LDri+ADD instead of continuing to chunk the
5+
# address in signed-8 LEA steps.
6+
7+
--- |
8+
; ModuleID = '<stdin>'
9+
source_filename = "/tmp/ez80-large-frame-repro/repro-large.c"
10+
target datalayout = "e-m:z-p:24:8-p1:16:8-p2:8:8-p3:16:8-p4:24:8-i16:8-i24:8-i32:8-i48:8-i64:8-i96:8-f32:8-f64:8-a:8-n8:16:24-S8"
11+
target triple = "ez80"
12+
13+
@gp = dso_local local_unnamed_addr global ptr null, align 1
14+
@sink = dso_local global i16 0, align 2
15+
16+
; Function Attrs: minsize nofree norecurse nounwind optsize memory(readwrite, argmem: read)
17+
define dso_local i16 @repro(ptr nocapture noundef readonly %p, i16 noundef %n) local_unnamed_addr #0 {
18+
entry:
19+
%pad = alloca [256 x i16], align 2
20+
call void @llvm.lifetime.start.p0(i64 512, ptr nonnull %pad) #4
21+
store ptr %pad, ptr @gp, align 1, !tbaa !2
22+
%wide.trip.count = zext i16 %n to i24
23+
br label %for.cond
24+
25+
for.cond: ; preds = %for.body, %entry
26+
%lsr.iv2 = phi i24 [ %lsr.iv.next3, %for.body ], [ %wide.trip.count, %entry ]
27+
%lsr.iv1 = phi i16 [ %lsr.iv.next, %for.body ], [ 36, %entry ]
28+
%lsr.iv = phi ptr [ %scevgep, %for.body ], [ %p, %entry ]
29+
%exitcond.not = icmp eq i24 %lsr.iv2, 0
30+
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
31+
32+
for.cond.cleanup: ; preds = %for.cond
33+
%0 = load volatile i16, ptr @sink, align 2, !tbaa !6
34+
%arrayidx14 = getelementptr inbounds i8, ptr %pad, i24 502
35+
%1 = load volatile i16, ptr %arrayidx14, align 2, !tbaa !6
36+
%add16 = add i16 %1, %0
37+
call void @llvm.lifetime.end.p0(i64 512, ptr nonnull %pad) #4
38+
ret i16 %add16
39+
40+
for.body: ; preds = %for.cond
41+
%sunkaddr = getelementptr inbounds i8, ptr %pad, i24 506
42+
store volatile i16 %lsr.iv1, ptr %sunkaddr, align 2, !tbaa !6
43+
%sunkaddr4 = getelementptr inbounds i8, ptr %pad, i24 504
44+
%2 = load volatile i16, ptr %sunkaddr4, align 2, !tbaa !6
45+
%3 = load i16, ptr %lsr.iv, align 2, !tbaa !6
46+
%add9 = add i16 %3, %2
47+
%4 = load volatile i16, ptr @sink, align 2, !tbaa !6
48+
%add11 = add i16 %add9, %4
49+
store volatile i16 %add11, ptr @sink, align 2, !tbaa !6
50+
%scevgep = getelementptr i8, ptr %lsr.iv, i24 2
51+
%lsr.iv.next = add i16 %lsr.iv1, 1
52+
%lsr.iv.next3 = add nsw i24 %lsr.iv2, -1
53+
br label %for.cond, !llvm.loop !8
54+
}
55+
56+
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
57+
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1
58+
59+
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
60+
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1
61+
62+
declare void @_Unwind_SjLj_Register(ptr)
63+
64+
declare void @_Unwind_SjLj_Unregister(ptr)
65+
66+
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none)
67+
declare ptr @llvm.frameaddress.p0(i32 immarg) #2
68+
69+
; Function Attrs: nocallback nofree nosync nounwind willreturn
70+
declare ptr @llvm.stacksave.p0() #3
71+
72+
; Function Attrs: nocallback nofree nosync nounwind willreturn
73+
declare void @llvm.stackrestore.p0(ptr) #3
74+
75+
; Function Attrs: nounwind
76+
declare void @llvm.eh.sjlj.setup.dispatch() #4
77+
78+
; Function Attrs: nounwind memory(none)
79+
declare ptr @llvm.eh.sjlj.lsda() #5
80+
81+
; Function Attrs: nounwind memory(none)
82+
declare void @llvm.eh.sjlj.callsite(i32 immarg) #5
83+
84+
; Function Attrs: nounwind
85+
declare void @llvm.eh.sjlj.functioncontext(ptr) #4
86+
87+
attributes #0 = { minsize nofree norecurse nounwind optsize memory(readwrite, argmem: read) "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
88+
attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
89+
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(none) }
90+
attributes #3 = { nocallback nofree nosync nounwind willreturn }
91+
attributes #4 = { nounwind }
92+
attributes #5 = { nounwind memory(none) }
93+
94+
!llvm.module.flags = !{!0}
95+
!llvm.ident = !{!1}
96+
97+
!0 = !{i32 1, !"wchar_size", i32 2}
98+
!1 = !{!"clang version 19.1.0 (git@github.com:Sightem/llvm-project.git ff9761906b160716d7d53f5641d52d409fdb8766)"}
99+
!2 = !{!3, !3, i64 0}
100+
!3 = !{!"any pointer", !4, i64 0}
101+
!4 = !{!"omnipotent char", !5, i64 0}
102+
!5 = !{!"Simple C/C++ TBAA"}
103+
!6 = !{!7, !7, i64 0}
104+
!7 = !{!"short", !4, i64 0}
105+
!8 = distinct !{!8, !9}
106+
!9 = !{!"llvm.loop.mustprogress"}
107+
108+
...
109+
---
110+
# CHECK-LABEL: name: repro
111+
name: repro
112+
alignment: 1
113+
legalized: true
114+
regBankSelected: true
115+
selected: true
116+
tracksRegLiveness: true
117+
tracksDebugUserValues: true
118+
frameInfo:
119+
maxAlignment: 2
120+
localFrameSize: 512
121+
fixedStack:
122+
- { id: 0, offset: 3, size: 2, alignment: 1, isImmutable: true }
123+
- { id: 1, size: 3, alignment: 1, isImmutable: true }
124+
stack:
125+
- { id: 0, name: pad, size: 512, alignment: 2, local-offset: -512 }
126+
- { id: 1, type: spill-slot, size: 3, alignment: 1 }
127+
- { id: 2, type: spill-slot, size: 2, alignment: 1 }
128+
machineFunctionInfo: {}
129+
body: |
130+
bb.0.entry:
131+
$uhl = LD24ro %fixed-stack.1, 0 :: (invariant load (p0) from %fixed-stack.1, align 1)
132+
LD24or %stack.1, 0, killed $uhl
133+
$uhl = LD24ro %fixed-stack.0, 0 :: (invariant load (s16) from %fixed-stack.0, align 1)
134+
$iy = LD16ri 36
135+
$ude = LEA24ro %stack.0.pad, 0
136+
LD24mr @gp, killed $ude :: (store (p0) into @gp, align 1, !tbaa !2)
137+
$ubc = LD24r0 implicit-def dead $f
138+
$bc = COPY $hl, implicit killed $uhl, implicit killed $ubc, implicit-def $ubc
139+
JQ %bb.1
140+
141+
bb.1.for.cond:
142+
successors: %bb.2, %bb.3
143+
liveins: $iy, $ubc
144+
145+
Cmp24a0 $ubc, implicit-def $f, implicit-def dead $uhl
146+
JQCC %bb.3, 0, implicit killed $f
147+
JQ %bb.2
148+
149+
bb.2.for.cond.cleanup:
150+
$uhl = LD24ri @sink
151+
$de = LD88rp killed $uhl :: (volatile dereferenceable load (s16) from @sink, !tbaa !6)
152+
$hl = LD88ro %stack.0.pad, 502 :: (volatile dereferenceable load (s16) from %ir.arrayidx14, !tbaa !6)
153+
$hl = ADD16ao killed $hl, killed $de, implicit-def dead $f
154+
RET24 implicit-def $spl, implicit $spl, implicit $hl
155+
156+
bb.3.for.body:
157+
liveins: $iy, $ubc
158+
159+
LD88or %stack.0.pad, 506, $iy :: (volatile store (s16) into %ir.sunkaddr, !tbaa !6)
160+
$de = LD88ro %stack.0.pad, 504 :: (volatile dereferenceable load (s16) from %ir.sunkaddr4, !tbaa !6)
161+
LD88or %stack.2, 0, killed $iy
162+
$uhl = LD24ro %stack.1, 0
163+
$uiy = LD24rp killed $uhl :: (load (s16) from %ir.lsr.iv, !tbaa !6)
164+
$uhl = COPY killed $uiy
165+
$hl = ADD16ao $hl, killed $de, implicit-def dead $f, implicit killed $uhl, implicit-def $uhl
166+
$uiy = LD24ri @sink
167+
$de = LD88rp killed $uiy :: (volatile dereferenceable load (s16) from @sink, !tbaa !6)
168+
$hl = ADD16ao $hl, killed $de, implicit-def dead $f, implicit killed $uhl, implicit-def $uhl
169+
$ude = COPY killed $uhl
170+
$uhl = LD24ri @sink
171+
LD88pr killed $uhl, $de, implicit killed $ude :: (volatile store (s16) into @sink, !tbaa !6)
172+
$uiy = LD24ro %stack.1, 0
173+
$uiy = LEA24ro killed $uiy, 2
174+
LD24or %stack.1, 0, killed $uiy
175+
$iy = LD88ro %stack.2, 0
176+
$iy = INC16r killed $iy
177+
$ubc = DEC24r killed $ubc
178+
JQ %bb.1
179+
180+
...
181+
182+
# CHECK: bb.3.for.body:
183+
# CHECK-NEXT: successors: %bb.1(0x80000000)
184+
# CHECK-NEXT: liveins: $iy, $ubc
185+
# CHECK: PUSH24r $uix, implicit-def $spl, implicit $spl
186+
# CHECK-NEXT: PUSH24r $ude, implicit-def $spl, implicit $spl
187+
# CHECK-NEXT: $ude = LD24ri -524
188+
# CHECK-NEXT: $uix = ADD24ao $uix, killed $ude, implicit-def dead $f
189+
# CHECK-NEXT: $ude = POP24r implicit-def $spl, implicit $spl
190+
# CHECK-NEXT: LD88or $uix, -128, killed $iy
191+
# CHECK-NEXT: $uix = POP24r implicit-def $spl, implicit $spl
192+
# CHECK: $uiy = LEA24ro $uix, 0
193+
# CHECK-NEXT: PUSH24r $ude, implicit-def $spl, implicit $spl
194+
# CHECK-NEXT: $ude = LD24ri -522
195+
# CHECK-NEXT: $uiy = ADD24ao $uiy, killed $ude, implicit-def dead $f
196+
# CHECK-NEXT: $ude = POP24r implicit-def $spl, implicit $spl
197+
# CHECK-NEXT: $uhl = LD24ro $uiy, 0

0 commit comments

Comments
 (0)