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