Skip to content

Commit 94ed57d

Browse files
committed
[PhaseOrdering] Add test for #85551.
Add test for missed hoisting of checks from std::span #85551
1 parent f2ade91 commit 94ed57d

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed

llvm/test/Transforms/PhaseOrdering/AArch64/hoist-runtime-checks.ll

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,151 @@ for.end: ; preds = %for.cond.cleanup
9191
ret i32 %9
9292
}
9393

94+
%"class.std::__1::span" = type { ptr, i64 }
95+
%"class.std::__1::__wrap_iter" = type { ptr }
96+
97+
define dso_local noundef i32 @sum_prefix_with_sum(ptr %s.coerce0, i64 %s.coerce1, i64 noundef %n) {
98+
; CHECK-LABEL: define dso_local noundef i32 @sum_prefix_with_sum(
99+
; CHECK-SAME: ptr nocapture readonly [[S_COERCE0:%.*]], i64 [[S_COERCE1:%.*]], i64 noundef [[N:%.*]]) local_unnamed_addr #[[ATTR0]] {
100+
; CHECK-NEXT: entry:
101+
; CHECK-NEXT: [[CMP5_NOT:%.*]] = icmp eq i64 [[N]], 0
102+
; CHECK-NEXT: br i1 [[CMP5_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
103+
; CHECK: for.body.preheader:
104+
; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N]], -1
105+
; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i64 [[TMP0]], [[S_COERCE1]]
106+
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
107+
; CHECK: for.cond.cleanup:
108+
; CHECK-NEXT: [[RET_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[SPAN_CHECKED_ACCESS_EXIT:%.*]] ]
109+
; CHECK-NEXT: ret i32 [[RET_0_LCSSA]]
110+
; CHECK: for.body:
111+
; CHECK-NEXT: [[I_07:%.*]] = phi i64 [ [[INC:%.*]], [[SPAN_CHECKED_ACCESS_EXIT]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
112+
; CHECK-NEXT: [[RET_06:%.*]] = phi i32 [ [[ADD]], [[SPAN_CHECKED_ACCESS_EXIT]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
113+
; CHECK-NEXT: br i1 [[DOTNOT_NOT]], label [[SPAN_CHECKED_ACCESS_EXIT]], label [[COND_FALSE_I:%.*]], !prof [[PROF0:![0-9]+]]
114+
; CHECK: cond.false.i:
115+
; CHECK-NEXT: tail call void @llvm.trap()
116+
; CHECK-NEXT: unreachable
117+
; CHECK: span_checked_access.exit:
118+
; CHECK-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr inbounds i32, ptr [[S_COERCE0]], i64 [[I_07]]
119+
; CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[ARRAYIDX_I]], align 4
120+
; CHECK-NEXT: [[ADD]] = add nsw i32 [[TMP7]], [[RET_06]]
121+
; CHECK-NEXT: [[INC]] = add nuw i64 [[I_07]], 1
122+
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INC]], [[N]]
123+
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]]
124+
;
125+
entry:
126+
%s = alloca %"class.std::__1::span", align 8
127+
%n.addr = alloca i64, align 8
128+
%ret = alloca i32, align 4
129+
%i = alloca i64, align 8
130+
%0 = getelementptr inbounds { ptr, i64 }, ptr %s, i32 0, i32 0
131+
store ptr %s.coerce0, ptr %0, align 8
132+
%1 = getelementptr inbounds { ptr, i64 }, ptr %s, i32 0, i32 1
133+
store i64 %s.coerce1, ptr %1, align 8
134+
store i64 %n, ptr %n.addr, align 8
135+
call void @llvm.lifetime.start.p0(i64 4, ptr %ret) #7
136+
store i32 0, ptr %ret, align 4
137+
call void @llvm.lifetime.start.p0(i64 8, ptr %i) #7
138+
store i64 0, ptr %i, align 8
139+
br label %for.cond
140+
141+
for.cond: ; preds = %for.inc, %entry
142+
%2 = load i64, ptr %i, align 8
143+
%3 = load i64, ptr %n.addr, align 8
144+
%cmp = icmp ult i64 %2, %3
145+
br i1 %cmp, label %for.body, label %for.cond.cleanup
146+
147+
for.cond.cleanup: ; preds = %for.cond
148+
call void @llvm.lifetime.end.p0(i64 8, ptr %i) #7
149+
br label %for.end
150+
151+
for.body: ; preds = %for.cond
152+
%4 = load i64, ptr %i, align 8
153+
%call = call noundef nonnull align 4 dereferenceable(4) ptr @span_checked_access(ptr noundef nonnull align 8 dereferenceable(16) %s, i64 noundef %4) #7
154+
%5 = load i32, ptr %call, align 4
155+
%6 = load i32, ptr %ret, align 4
156+
%add = add nsw i32 %6, %5
157+
store i32 %add, ptr %ret, align 4
158+
br label %for.inc
159+
160+
for.inc: ; preds = %for.body
161+
%7 = load i64, ptr %i, align 8
162+
%inc = add i64 %7, 1
163+
store i64 %inc, ptr %i, align 8
164+
br label %for.cond
165+
166+
for.end: ; preds = %for.cond.cleanup
167+
%8 = load i32, ptr %ret, align 4
168+
call void @llvm.lifetime.end.p0(i64 4, ptr %ret)
169+
ret i32 %8
170+
}
171+
172+
define hidden noundef nonnull align 4 dereferenceable(4) ptr @span_checked_access(ptr noundef nonnull align 8 dereferenceable(16) %this, i64 noundef %__idx) {
173+
; CHECK-LABEL: define hidden noundef nonnull align 4 dereferenceable(4) ptr @span_checked_access(
174+
; CHECK-SAME: ptr nocapture noundef nonnull readonly align 8 dereferenceable(16) [[THIS:%.*]], i64 noundef [[__IDX:%.*]]) local_unnamed_addr #[[ATTR0]] {
175+
; CHECK-NEXT: entry:
176+
; CHECK-NEXT: [[__SIZE__I:%.*]] = getelementptr inbounds i8, ptr [[THIS]], i64 8
177+
; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[__SIZE__I]], align 8
178+
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[TMP0]], [[__IDX]]
179+
; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]], !prof [[PROF0]]
180+
; CHECK: cond.false:
181+
; CHECK-NEXT: tail call void @llvm.trap()
182+
; CHECK-NEXT: unreachable
183+
; CHECK: cond.end:
184+
; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[THIS]], align 8
185+
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 [[__IDX]]
186+
; CHECK-NEXT: ret ptr [[ARRAYIDX]]
187+
;
188+
entry:
189+
%this.addr = alloca ptr, align 8
190+
%__idx.addr = alloca i64, align 8
191+
store ptr %this, ptr %this.addr, align 8
192+
store i64 %__idx, ptr %__idx.addr, align 8
193+
%this1 = load ptr, ptr %this.addr, align 8
194+
%0 = load i64, ptr %__idx.addr, align 8
195+
%call = call noundef i64 @span_access(ptr noundef nonnull align 8 dereferenceable(16) %this1)
196+
%cmp = icmp ult i64 %0, %call
197+
%conv = zext i1 %cmp to i64
198+
%expval = call i64 @llvm.expect.i64(i64 %conv, i64 1)
199+
%tobool = icmp ne i64 %expval, 0
200+
br i1 %tobool, label %cond.true, label %cond.false
201+
202+
cond.true: ; preds = %entry
203+
br label %cond.end
204+
205+
cond.false: ; preds = %entry
206+
call void @llvm.trap()
207+
br label %cond.end
208+
209+
cond.end: ; preds = %cond.false, %cond.true
210+
%__data_ = getelementptr inbounds %"class.std::__1::span", ptr %this1, i32 0, i32 0
211+
%1 = load ptr, ptr %__data_, align 8
212+
%2 = load i64, ptr %__idx.addr, align 8
213+
%arrayidx = getelementptr inbounds i32, ptr %1, i64 %2
214+
ret ptr %arrayidx
215+
}
216+
217+
define hidden noundef i64 @span_access(ptr noundef nonnull align 8 dereferenceable(16) %this) {
218+
; CHECK-LABEL: define hidden noundef i64 @span_access(
219+
; CHECK-SAME: ptr nocapture noundef nonnull readonly align 8 dereferenceable(16) [[THIS:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
220+
; CHECK-NEXT: entry:
221+
; CHECK-NEXT: [[__SIZE_:%.*]] = getelementptr inbounds i8, ptr [[THIS]], i64 8
222+
; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[__SIZE_]], align 8
223+
; CHECK-NEXT: ret i64 [[TMP0]]
224+
;
225+
entry:
226+
%this.addr = alloca ptr, align 8
227+
store ptr %this, ptr %this.addr, align 8
228+
%this1 = load ptr, ptr %this.addr, align 8
229+
%__size_ = getelementptr inbounds %"class.std::__1::span", ptr %this1, i32 0, i32 1
230+
%0 = load i64, ptr %__size_, align 8
231+
ret i64 %0
232+
}
233+
94234
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture)
95235

96236
declare void @llvm.trap()
97237

98238
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)
239+
;.
240+
; CHECK: [[PROF0]] = !{!"branch_weights", i32 2000, i32 1}
241+
;.

0 commit comments

Comments
 (0)