xref: /llvm-project/llvm/test/Transforms/InstCombine/gep-inbounds-null.ll (revision 4ab40eca080965c65802710e39adbb78c4ce7bde)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S < %s -passes=instcombine | FileCheck %s
3
4;; Start by showing the results of constant folding (which doesn't use
5;; the poison implied by gep for the nonnull cases).
6
7define i1 @test_ne_constants_null() {
8; CHECK-LABEL: @test_ne_constants_null(
9; CHECK-NEXT:  entry:
10; CHECK-NEXT:    ret i1 false
11;
12entry:
13  %cnd = icmp ne ptr null, null
14  ret i1 %cnd
15}
16
17define i1 @test_ne_constants_nonnull() {
18; CHECK-LABEL: @test_ne_constants_nonnull(
19; CHECK-NEXT:  entry:
20; CHECK-NEXT:    ret i1 true
21;
22entry:
23  %gep = getelementptr inbounds i8, ptr null, i64 1
24  %cnd = icmp ne ptr %gep, null
25  ret i1 %cnd
26}
27
28define i1 @test_eq_constants_null() {
29; CHECK-LABEL: @test_eq_constants_null(
30; CHECK-NEXT:  entry:
31; CHECK-NEXT:    ret i1 true
32;
33entry:
34  %cnd = icmp eq ptr null, null
35  ret i1 %cnd
36}
37
38define i1 @test_eq_constants_nonnull() {
39; CHECK-LABEL: @test_eq_constants_nonnull(
40; CHECK-NEXT:  entry:
41; CHECK-NEXT:    ret i1 false
42;
43entry:
44  %gep = getelementptr inbounds i8, ptr null, i64 1
45  %cnd = icmp eq ptr %gep, null
46  ret i1 %cnd
47}
48
49;; Then show the results for non-constants.  These use the inbounds provided
50;; UB fact to ignore the possible overflow cases.
51
52define i1 @test_ne(ptr %base, i64 %idx) {
53; CHECK-LABEL: @test_ne(
54; CHECK-NEXT:  entry:
55; CHECK-NEXT:    [[CND:%.*]] = icmp ne ptr [[BASE:%.*]], null
56; CHECK-NEXT:    ret i1 [[CND]]
57;
58entry:
59  %gep = getelementptr inbounds i8, ptr %base, i64 %idx
60  %cnd = icmp ne ptr %gep, null
61  ret i1 %cnd
62}
63
64define i1 @test_eq(ptr %base, i64 %idx) {
65; CHECK-LABEL: @test_eq(
66; CHECK-NEXT:  entry:
67; CHECK-NEXT:    [[CND:%.*]] = icmp eq ptr [[BASE:%.*]], null
68; CHECK-NEXT:    ret i1 [[CND]]
69;
70entry:
71  %gep = getelementptr inbounds i8, ptr %base, i64 %idx
72  %cnd = icmp eq ptr %gep, null
73  ret i1 %cnd
74}
75
76define <2 x i1> @test_vector_base(<2 x ptr> %base, i64 %idx) {
77; CHECK-LABEL: @test_vector_base(
78; CHECK-NEXT:  entry:
79; CHECK-NEXT:    [[CND:%.*]] = icmp eq <2 x ptr> [[BASE:%.*]], zeroinitializer
80; CHECK-NEXT:    ret <2 x i1> [[CND]]
81;
82entry:
83  %gep = getelementptr inbounds i8, <2 x ptr> %base, i64 %idx
84  %cnd = icmp eq <2 x ptr> %gep, zeroinitializer
85  ret <2 x i1> %cnd
86}
87
88define <2 x i1> @test_vector_index(ptr %base, <2 x i64> %idx) {
89; CHECK-LABEL: @test_vector_index(
90; CHECK-NEXT:  entry:
91; CHECK-NEXT:    [[DOTSPLATINSERT:%.*]] = insertelement <2 x ptr> poison, ptr [[BASE:%.*]], i64 0
92; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq <2 x ptr> [[DOTSPLATINSERT]], zeroinitializer
93; CHECK-NEXT:    [[CND:%.*]] = shufflevector <2 x i1> [[TMP0]], <2 x i1> poison, <2 x i32> zeroinitializer
94; CHECK-NEXT:    ret <2 x i1> [[CND]]
95;
96entry:
97  %gep = getelementptr inbounds i8, ptr %base, <2 x i64> %idx
98  %cnd = icmp eq <2 x ptr> %gep, zeroinitializer
99  ret <2 x i1> %cnd
100}
101
102define <2 x i1> @test_vector_both(<2 x ptr> %base, <2 x i64> %idx) {
103; CHECK-LABEL: @test_vector_both(
104; CHECK-NEXT:  entry:
105; CHECK-NEXT:    [[CND:%.*]] = icmp eq <2 x ptr> [[BASE:%.*]], zeroinitializer
106; CHECK-NEXT:    ret <2 x i1> [[CND]]
107;
108entry:
109  %gep = getelementptr inbounds i8, <2 x ptr> %base, <2 x i64> %idx
110  %cnd = icmp eq <2 x ptr> %gep, zeroinitializer
111  ret <2 x i1> %cnd
112}
113
114;; These two show instsimplify's reasoning getting to the non-zero offsets
115;; before instcombine does.
116
117define i1 @test_eq_pos_idx(ptr %base) {
118; CHECK-LABEL: @test_eq_pos_idx(
119; CHECK-NEXT:  entry:
120; CHECK-NEXT:    ret i1 false
121;
122entry:
123  %gep = getelementptr inbounds i8, ptr %base, i64 1
124  %cnd = icmp eq ptr %gep, null
125  ret i1 %cnd
126}
127
128define i1 @test_eq_neg_idx(ptr %base) {
129; CHECK-LABEL: @test_eq_neg_idx(
130; CHECK-NEXT:  entry:
131; CHECK-NEXT:    ret i1 false
132;
133entry:
134  %gep = getelementptr inbounds i8, ptr %base, i64 -1
135  %cnd = icmp eq ptr %gep, null
136  ret i1 %cnd
137}
138
139;; Show an example with a zero sized type since that's
140;; a cornercase which keeps getting mentioned.  The GEP
141;; produces %base regardless of the value of the index
142;; expression.
143define i1 @test_size0(ptr %base, i64 %idx) {
144; CHECK-LABEL: @test_size0(
145; CHECK-NEXT:  entry:
146; CHECK-NEXT:    [[CND:%.*]] = icmp ne ptr [[BASE:%.*]], null
147; CHECK-NEXT:    ret i1 [[CND]]
148;
149entry:
150  %gep = getelementptr inbounds {}, ptr %base, i64 %idx
151  %cnd = icmp ne ptr %gep, null
152  ret i1 %cnd
153}
154define i1 @test_size0_nonzero_offset(ptr %base) {
155; CHECK-LABEL: @test_size0_nonzero_offset(
156; CHECK-NEXT:  entry:
157; CHECK-NEXT:    [[CND:%.*]] = icmp ne ptr [[BASE:%.*]], null
158; CHECK-NEXT:    ret i1 [[CND]]
159;
160entry:
161  %gep = getelementptr inbounds {}, ptr %base, i64 15
162  %cnd = icmp ne ptr %gep, null
163  ret i1 %cnd
164}
165
166
167define i1 @test_index_type(ptr %base, i64 %idx) {
168; CHECK-LABEL: @test_index_type(
169; CHECK-NEXT:  entry:
170; CHECK-NEXT:    [[CND:%.*]] = icmp eq ptr [[BASE:%.*]], null
171; CHECK-NEXT:    ret i1 [[CND]]
172;
173entry:
174  %gep = getelementptr inbounds [10 x i8], ptr %base, i64 %idx, i64 %idx
175  %cnd = icmp eq ptr %gep, null
176  ret i1 %cnd
177}
178
179
180;; Finally, some negative tests for basic correctness checking.
181
182define i1 @neq_noinbounds(ptr %base, i64 %idx) {
183; CHECK-LABEL: @neq_noinbounds(
184; CHECK-NEXT:  entry:
185; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[BASE:%.*]], i64 [[IDX:%.*]]
186; CHECK-NEXT:    [[CND:%.*]] = icmp ne ptr [[GEP]], null
187; CHECK-NEXT:    ret i1 [[CND]]
188;
189entry:
190  %gep = getelementptr i8, ptr %base, i64 %idx
191  %cnd = icmp ne ptr %gep, null
192  ret i1 %cnd
193}
194
195define i1 @neg_objectatnull(ptr addrspace(2) %base, i64 %idx) {
196; CHECK-LABEL: @neg_objectatnull(
197; CHECK-NEXT:  entry:
198; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i8, ptr addrspace(2) [[BASE:%.*]], i64 [[IDX:%.*]]
199; CHECK-NEXT:    [[CND:%.*]] = icmp eq ptr addrspace(2) [[GEP]], null
200; CHECK-NEXT:    ret i1 [[CND]]
201;
202entry:
203  %gep = getelementptr inbounds i8, ptr addrspace(2) %base, i64 %idx
204  %cnd = icmp eq ptr addrspace(2) %gep, null
205  ret i1 %cnd
206}
207
208; Test for an assert from trying to create an invalid constantexpr
209; bitcast between different address spaces. The addrspacecast is
210; stripped off and the addrspace(0) null can be treated as invalid.
211; FIXME: This should be able to fold to ret i1 false
212define i1 @invalid_bitcast_icmp_addrspacecast_as0_null(ptr addrspace(5) %ptr) {
213; CHECK-LABEL: @invalid_bitcast_icmp_addrspacecast_as0_null(
214; CHECK-NEXT:  bb:
215; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq ptr addrspace(5) [[PTR:%.*]], addrspacecast (ptr null to ptr addrspace(5))
216; CHECK-NEXT:    ret i1 [[TMP2]]
217;
218bb:
219  %tmp1 = getelementptr inbounds i32, ptr addrspace(5) %ptr, i32 1
220  %tmp2 = icmp eq ptr addrspace(5) %tmp1, addrspacecast (ptr null to ptr addrspace(5))
221  ret i1 %tmp2
222}
223
224define i1 @invalid_bitcast_icmp_addrspacecast_as0_null_var(ptr addrspace(5) %ptr, i32 %idx) {
225; CHECK-LABEL: @invalid_bitcast_icmp_addrspacecast_as0_null_var(
226; CHECK-NEXT:  bb:
227; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq ptr addrspace(5) [[PTR:%.*]], addrspacecast (ptr null to ptr addrspace(5))
228; CHECK-NEXT:    ret i1 [[TMP2]]
229;
230bb:
231  %tmp1 = getelementptr inbounds i32, ptr addrspace(5) %ptr, i32 %idx
232  %tmp2 = icmp eq ptr addrspace(5) %tmp1, addrspacecast (ptr null to ptr addrspace(5))
233  ret i1 %tmp2
234}
235