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