Skip to content

Commit b97cdc0

Browse files
author
git apple-llvm automerger
committed
Merge commit 'faed8f9e042a' from apple/main into swift/next
2 parents ad18833 + faed8f9 commit b97cdc0

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt < %s -gvn --basic-aa -S | FileCheck %s
3+
4+
; load may be speculated, adress is not null using context search.
5+
; There is a critical edge.
6+
define i32 @loadpre_critical_edge(i32* align 8 dereferenceable_or_null(48) %arg, i32 %N) {
7+
; CHECK-LABEL: @loadpre_critical_edge(
8+
; CHECK-NEXT: entry:
9+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32* [[ARG:%.*]], null
10+
; CHECK-NEXT: br i1 [[CMP]], label [[NULL_EXIT:%.*]], label [[HEADER:%.*]]
11+
; CHECK: header:
12+
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[HEADER]] ]
13+
; CHECK-NEXT: [[NEW_V:%.*]] = call i32 @foo(i32 [[IV]])
14+
; CHECK-NEXT: [[V:%.*]] = load i32, i32* [[ARG]], align 4
15+
; CHECK-NEXT: [[SUM:%.*]] = add i32 [[NEW_V]], [[V]]
16+
; CHECK-NEXT: store i32 [[SUM]], i32* [[ARG]], align 4
17+
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
18+
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[IV_NEXT]], [[N:%.*]]
19+
; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[HEADER]]
20+
; CHECK: exit:
21+
; CHECK-NEXT: ret i32 [[SUM]]
22+
; CHECK: null_exit:
23+
; CHECK-NEXT: ret i32 0
24+
;
25+
entry:
26+
%cmp = icmp eq i32* %arg, null
27+
br i1 %cmp, label %null_exit, label %header
28+
29+
header:
30+
%iv = phi i32 [0, %entry], [%iv.next, %header]
31+
%new_v = call i32 @foo(i32 %iv)
32+
%v = load i32, i32* %arg
33+
%sum = add i32 %new_v, %v
34+
store i32 %sum, i32* %arg
35+
%iv.next = add i32 %iv, 1
36+
%cond = icmp eq i32 %iv.next, %N
37+
br i1 %cond, label %exit, label %header
38+
39+
exit:
40+
ret i32 %sum
41+
42+
null_exit:
43+
ret i32 0
44+
}
45+
46+
; load may be speculated, adress is not null using context search.
47+
define i32 @loadpre_basic(i32* align 8 dereferenceable_or_null(48) %arg, i32 %N) {
48+
; CHECK-LABEL: @loadpre_basic(
49+
; CHECK-NEXT: entry:
50+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32* [[ARG:%.*]], null
51+
; CHECK-NEXT: br i1 [[CMP]], label [[NULL_EXIT:%.*]], label [[PREHEADER:%.*]]
52+
; CHECK: preheader:
53+
; CHECK-NEXT: br label [[HEADER:%.*]]
54+
; CHECK: header:
55+
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[IV_NEXT:%.*]], [[HEADER]] ]
56+
; CHECK-NEXT: [[NEW_V:%.*]] = call i32 @foo(i32 [[IV]])
57+
; CHECK-NEXT: [[V:%.*]] = load i32, i32* [[ARG]], align 4
58+
; CHECK-NEXT: [[SUM:%.*]] = add i32 [[NEW_V]], [[V]]
59+
; CHECK-NEXT: store i32 [[SUM]], i32* [[ARG]], align 4
60+
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
61+
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[IV_NEXT]], [[N:%.*]]
62+
; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[HEADER]]
63+
; CHECK: exit:
64+
; CHECK-NEXT: ret i32 [[SUM]]
65+
; CHECK: null_exit:
66+
; CHECK-NEXT: ret i32 0
67+
;
68+
entry:
69+
%cmp = icmp eq i32* %arg, null
70+
br i1 %cmp, label %null_exit, label %preheader
71+
72+
preheader:
73+
br label %header
74+
75+
header:
76+
%iv = phi i32 [0, %preheader], [%iv.next, %header]
77+
%new_v = call i32 @foo(i32 %iv)
78+
%v = load i32, i32* %arg
79+
%sum = add i32 %new_v, %v
80+
store i32 %sum, i32* %arg
81+
%iv.next = add i32 %iv, 1
82+
%cond = icmp eq i32 %iv.next, %N
83+
br i1 %cond, label %exit, label %header
84+
85+
exit:
86+
ret i32 %sum
87+
88+
null_exit:
89+
ret i32 0
90+
}
91+
92+
; load cannot be speculated, adress is not null check does not dominate the loop.
93+
define i32 @loadpre_maybe_null(i32* align 8 dereferenceable_or_null(48) %arg, i32 %N, i1 %c) {
94+
; CHECK-LABEL: @loadpre_maybe_null(
95+
; CHECK-NEXT: entry:
96+
; CHECK-NEXT: br i1 [[C:%.*]], label [[NULL_CHECK:%.*]], label [[PREHEADER:%.*]]
97+
; CHECK: null_check:
98+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32* [[ARG:%.*]], null
99+
; CHECK-NEXT: br i1 [[CMP]], label [[NULL_EXIT:%.*]], label [[PREHEADER]]
100+
; CHECK: preheader:
101+
; CHECK-NEXT: br label [[HEADER:%.*]]
102+
; CHECK: header:
103+
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[IV_NEXT:%.*]], [[HEADER]] ]
104+
; CHECK-NEXT: [[NEW_V:%.*]] = call i32 @foo(i32 [[IV]])
105+
; CHECK-NEXT: [[V:%.*]] = load i32, i32* [[ARG]], align 4
106+
; CHECK-NEXT: [[SUM:%.*]] = add i32 [[NEW_V]], [[V]]
107+
; CHECK-NEXT: store i32 [[SUM]], i32* [[ARG]], align 4
108+
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
109+
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[IV_NEXT]], [[N:%.*]]
110+
; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[HEADER]]
111+
; CHECK: exit:
112+
; CHECK-NEXT: ret i32 [[SUM]]
113+
; CHECK: null_exit:
114+
; CHECK-NEXT: ret i32 0
115+
;
116+
entry:
117+
br i1 %c, label %null_check, label %preheader
118+
119+
null_check:
120+
%cmp = icmp eq i32* %arg, null
121+
br i1 %cmp, label %null_exit, label %preheader
122+
123+
preheader:
124+
br label %header
125+
126+
header:
127+
%iv = phi i32 [0, %preheader], [%iv.next, %header]
128+
%new_v = call i32 @foo(i32 %iv)
129+
%v = load i32, i32* %arg
130+
%sum = add i32 %new_v, %v
131+
store i32 %sum, i32* %arg
132+
%iv.next = add i32 %iv, 1
133+
%cond = icmp eq i32 %iv.next, %N
134+
br i1 %cond, label %exit, label %header
135+
136+
exit:
137+
ret i32 %sum
138+
139+
null_exit:
140+
ret i32 0
141+
}
142+
143+
; Does not guarantee that returns.
144+
declare i32 @foo(i32) readnone

0 commit comments

Comments
 (0)