1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=gvn < %s | FileCheck %s
5 declare void @use.i32(i32)
7 define void @gep_cse(ptr %p) {
8 ; CHECK-LABEL: @gep_cse(
9 ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 1
10 ; CHECK-NEXT: [[GEP3:%.*]] = getelementptr i64, ptr [[P]], i64 1
11 ; CHECK-NEXT: call void @use(ptr [[GEP1]])
12 ; CHECK-NEXT: call void @use(ptr [[GEP1]])
13 ; CHECK-NEXT: call void @use(ptr [[GEP3]])
14 ; CHECK-NEXT: ret void
16 %gep1 = getelementptr i32, ptr %p, i64 1
17 %gep2 = getelementptr i32, ptr %p, i64 1
18 %gep3 = getelementptr i64, ptr %p, i64 1
19 call void @use(ptr %gep1)
20 call void @use(ptr %gep2)
21 call void @use(ptr %gep3)
25 define void @gep_cse_offset_canonicalization(ptr %p, i64 %idx, i64 %idx2) {
26 ; CHECK-LABEL: @gep_cse_offset_canonicalization(
27 ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i64, ptr [[P:%.*]], i64 1
28 ; CHECK-NEXT: [[GEP1_DIFFERENT:%.*]] = getelementptr i8, ptr [[P]], i64 12
29 ; CHECK-NEXT: call void @use(ptr [[GEP1]])
30 ; CHECK-NEXT: call void @use(ptr [[GEP1]])
31 ; CHECK-NEXT: call void @use(ptr [[GEP1]])
32 ; CHECK-NEXT: call void @use(ptr [[GEP1_DIFFERENT]])
33 ; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i64, ptr [[P]], i64 [[IDX:%.*]]
34 ; CHECK-NEXT: [[GEP2_DIFFERENT:%.*]] = getelementptr { i32, i32, i32 }, ptr [[P]], i64 [[IDX]]
35 ; CHECK-NEXT: call void @use(ptr [[GEP2]])
36 ; CHECK-NEXT: call void @use(ptr [[GEP2]])
37 ; CHECK-NEXT: call void @use(ptr [[GEP2_DIFFERENT]])
38 ; CHECK-NEXT: [[GEP3:%.*]] = getelementptr { [0 x i32], [0 x i32] }, ptr [[P]], i64 0, i32 0, i64 [[IDX]]
39 ; CHECK-NEXT: [[GEP3_DIFFERENT:%.*]] = getelementptr { [0 x i32], [0 x i32] }, ptr [[P]], i64 0, i32 0, i64 [[IDX2:%.*]]
40 ; CHECK-NEXT: call void @use(ptr [[GEP3]])
41 ; CHECK-NEXT: call void @use(ptr [[GEP3]])
42 ; CHECK-NEXT: call void @use(ptr [[GEP3]])
43 ; CHECK-NEXT: call void @use(ptr [[GEP3_DIFFERENT]])
44 ; CHECK-NEXT: [[GEP4:%.*]] = getelementptr [4 x i32], ptr [[P]], i64 [[IDX]], i64 [[IDX2]]
45 ; CHECK-NEXT: [[GEP4_DIFFERENT:%.*]] = getelementptr [4 x float], ptr [[P]], i64 [[IDX2]], i64 [[IDX]]
46 ; CHECK-NEXT: call void @use(ptr [[GEP4]])
47 ; CHECK-NEXT: call void @use(ptr [[GEP4]])
48 ; CHECK-NEXT: call void @use(ptr [[GEP4_DIFFERENT]])
49 ; CHECK-NEXT: [[GEP5:%.*]] = getelementptr <vscale x 2 x i32>, ptr [[P]], i64 1
50 ; CHECK-NEXT: [[GEP5_SAME:%.*]] = getelementptr <vscale x 2 x float>, ptr [[P]], i64 1
51 ; CHECK-NEXT: [[GEP5_DIFFERENT:%.*]] = getelementptr <vscale x 2 x i64>, ptr [[P]], i64 1
52 ; CHECK-NEXT: call void @use(ptr [[GEP5]])
53 ; CHECK-NEXT: call void @use(ptr [[GEP5_SAME]])
54 ; CHECK-NEXT: call void @use(ptr [[GEP5_DIFFERENT]])
55 ; CHECK-NEXT: [[GEP6:%.*]] = getelementptr [4 x <vscale x 4 x i32>], ptr [[P]], i64 [[IDX]], i64 1
56 ; CHECK-NEXT: [[GEP6_SAME:%.*]] = getelementptr [4 x <vscale x 4 x float>], ptr [[P]], i64 [[IDX]], i64 1
57 ; CHECK-NEXT: [[GEP6_DIFFERENT:%.*]] = getelementptr [4 x <vscale x 4 x float>], ptr [[P]], i64 [[IDX2]], i64 1
58 ; CHECK-NEXT: call void @use(ptr [[GEP6]])
59 ; CHECK-NEXT: call void @use(ptr [[GEP6_SAME]])
60 ; CHECK-NEXT: call void @use(ptr [[GEP6_DIFFERENT]])
61 ; CHECK-NEXT: ret void
63 %gep1 = getelementptr i64, ptr %p, i64 1
64 %gep1.same1 = getelementptr i32, ptr %p, i64 2
65 %gep1.same2 = getelementptr i8, ptr %p, i64 8
66 %gep1.different = getelementptr i8, ptr %p, i64 12
67 call void @use(ptr %gep1)
68 call void @use(ptr %gep1.same1)
69 call void @use(ptr %gep1.same2)
70 call void @use(ptr %gep1.different)
71 %gep2 = getelementptr i64, ptr %p, i64 %idx
72 %gep2.same = getelementptr { i32, i32 }, ptr %p, i64 %idx
73 %gep2.different = getelementptr { i32, i32, i32 }, ptr %p, i64 %idx
74 call void @use(ptr %gep2)
75 call void @use(ptr %gep2.same)
76 call void @use(ptr %gep2.different)
77 %gep3 = getelementptr { [0 x i32], [0 x i32] }, ptr %p, i64 0, i32 0, i64 %idx
78 %gep3.same1 = getelementptr { [0 x i32], [0 x i32] }, ptr %p, i64 0, i32 1, i64 %idx
79 %gep3.same2 = getelementptr { [0 x i32], [0 x i32] }, ptr %p, i64 1, i32 0, i64 %idx
80 %gep3.different = getelementptr { [0 x i32], [0 x i32] }, ptr %p, i64 0, i32 0, i64 %idx2
81 call void @use(ptr %gep3)
82 call void @use(ptr %gep3.same1)
83 call void @use(ptr %gep3.same2)
84 call void @use(ptr %gep3.different)
85 %gep4 = getelementptr [4 x i32], ptr %p, i64 %idx, i64 %idx2
86 %gep4.same = getelementptr [4 x float], ptr %p, i64 %idx, i64 %idx2
87 %gep4.different = getelementptr [4 x float], ptr %p, i64 %idx2, i64 %idx
88 call void @use(ptr %gep4)
89 call void @use(ptr %gep4.same)
90 call void @use(ptr %gep4.different)
91 ; TODO: %gep5 and %gep5.same are equivalent as well.
92 %gep5 = getelementptr <vscale x 2 x i32>, ptr %p, i64 1
93 %gep5.same = getelementptr <vscale x 2 x float>, ptr %p, i64 1
94 %gep5.different = getelementptr <vscale x 2 x i64>, ptr %p, i64 1
95 call void @use(ptr %gep5)
96 call void @use(ptr %gep5.same)
97 call void @use(ptr %gep5.different)
98 %gep6 = getelementptr [4 x <vscale x 4 x i32>], ptr %p, i64 %idx, i64 1
99 %gep6.same = getelementptr [4 x <vscale x 4 x float>], ptr %p, i64 %idx, i64 1
100 %gep6.different = getelementptr [4 x <vscale x 4 x float>], ptr %p, i64 %idx2, i64 1
101 call void @use(ptr %gep6)
102 call void @use(ptr %gep6.same)
103 call void @use(ptr %gep6.different)
107 define i32 @phi_trans(i1 %c, ptr %p1, ptr %p2) {
108 ; CHECK-LABEL: @phi_trans(
109 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
111 ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, ptr [[P1:%.*]], i64 1
112 ; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[GEP1]], align 4
113 ; CHECK-NEXT: call void @use(i32 [[V1]]) #[[ATTR0:[0-9]+]]
114 ; CHECK-NEXT: br label [[JOIN:%.*]]
116 ; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i32, ptr [[P2:%.*]], i64 1
117 ; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[GEP2]], align 4
118 ; CHECK-NEXT: call void @use(i32 [[V2]]) #[[ATTR0]]
119 ; CHECK-NEXT: br label [[JOIN]]
121 ; CHECK-NEXT: [[V:%.*]] = phi i32 [ [[V1]], [[IF]] ], [ [[V2]], [[ELSE]] ]
122 ; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[P1]], [[IF]] ], [ [[P2]], [[ELSE]] ]
123 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[PHI]], i64 1
124 ; CHECK-NEXT: ret i32 [[V]]
126 br i1 %c, label %if, label %else
129 %gep1 = getelementptr i32, ptr %p1, i64 1
130 %v1 = load i32, ptr %gep1
131 call void @use(i32 %v1) readnone
135 %gep2 = getelementptr i32, ptr %p2, i64 1
136 %v2 = load i32, ptr %gep2
137 call void @use(i32 %v2) readnone
141 %phi = phi ptr [ %p1, %if ], [ %p2, %else ]
142 %gep = getelementptr i32, ptr %phi, i64 1
143 %v = load i32, ptr %gep
147 define i32 @phi_trans_different_types(i1 %c, ptr %p1, ptr %p2) {
148 ; CHECK-LABEL: @phi_trans_different_types(
149 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
151 ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, ptr [[P1:%.*]], i64 1
152 ; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[GEP1]], align 4
153 ; CHECK-NEXT: call void @use.i32(i32 [[V1]]) #[[ATTR0]]
154 ; CHECK-NEXT: br label [[JOIN:%.*]]
156 ; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i64, ptr [[P2:%.*]], i64 1
157 ; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[GEP2]], align 4
158 ; CHECK-NEXT: call void @use.i32(i32 [[V2]]) #[[ATTR0]]
159 ; CHECK-NEXT: [[GEP_PHI_TRANS_INSERT:%.*]] = getelementptr i32, ptr [[P2]], i64 1
160 ; CHECK-NEXT: [[V_PRE:%.*]] = load i32, ptr [[GEP_PHI_TRANS_INSERT]], align 4
161 ; CHECK-NEXT: br label [[JOIN]]
163 ; CHECK-NEXT: [[V:%.*]] = phi i32 [ [[V1]], [[IF]] ], [ [[V_PRE]], [[ELSE]] ]
164 ; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[P1]], [[IF]] ], [ [[P2]], [[ELSE]] ]
165 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[PHI]], i64 1
166 ; CHECK-NEXT: ret i32 [[V]]
168 br i1 %c, label %if, label %else
171 %gep1 = getelementptr i32, ptr %p1, i64 1
172 %v1 = load i32, ptr %gep1
173 call void @use.i32(i32 %v1) readnone
177 %gep2 = getelementptr i64, ptr %p2, i64 1
178 %v2 = load i32, ptr %gep2
179 call void @use.i32(i32 %v2) readnone
183 %phi = phi ptr [ %p1, %if ], [ %p2, %else ]
184 %gep = getelementptr i32, ptr %phi, i64 1
185 %v = load i32, ptr %gep
189 define i32 @select_pre(ptr %px, ptr %py) {
190 ; CHECK-LABEL: @select_pre(
191 ; CHECK-NEXT: [[T2:%.*]] = load i32, ptr [[PY:%.*]], align 4
192 ; CHECK-NEXT: [[T3:%.*]] = load i32, ptr [[PX:%.*]], align 4
193 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[T2]], [[T3]]
194 ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[CMP]], i32 [[T3]], i32 [[T2]]
195 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], ptr [[PX]], ptr [[PY]]
196 ; CHECK-NEXT: ret i32 [[TMP1]]
198 %t2 = load i32, ptr %py, align 4
199 %t3 = load i32, ptr %px, align 4
200 %cmp = icmp slt i32 %t2, %t3
201 %select = select i1 %cmp, ptr %px, ptr %py
202 %r = load i32, ptr %select, align 4
206 define i64 @select_pre_different_types(ptr %px, ptr %py) {
207 ; CHECK-LABEL: @select_pre_different_types(
208 ; CHECK-NEXT: [[T2:%.*]] = load i32, ptr [[PY:%.*]], align 4
209 ; CHECK-NEXT: [[T3:%.*]] = load i32, ptr [[PX:%.*]], align 4
210 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[T2]], [[T3]]
211 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], ptr [[PX]], ptr [[PY]]
212 ; CHECK-NEXT: [[R:%.*]] = load i64, ptr [[SELECT]], align 4
213 ; CHECK-NEXT: ret i64 [[R]]
215 %t2 = load i32, ptr %py, align 4
216 %t3 = load i32, ptr %px, align 4
217 %cmp = icmp slt i32 %t2, %t3
218 %select = select i1 %cmp, ptr %px, ptr %py
219 %r = load i64, ptr %select, align 4