1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S < %s -passes=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(
10 ; CHECK-NEXT: ret i1 false
13 %cnd = icmp ne ptr null, null
17 define i1 @test_ne_constants_nonnull() {
18 ; CHECK-LABEL: @test_ne_constants_nonnull(
20 ; CHECK-NEXT: ret i1 true
23 %gep = getelementptr inbounds i8, ptr null, i64 1
24 %cnd = icmp ne ptr %gep, null
28 define i1 @test_eq_constants_null() {
29 ; CHECK-LABEL: @test_eq_constants_null(
31 ; CHECK-NEXT: ret i1 true
34 %cnd = icmp eq ptr null, null
38 define i1 @test_eq_constants_nonnull() {
39 ; CHECK-LABEL: @test_eq_constants_nonnull(
41 ; CHECK-NEXT: ret i1 false
44 %gep = getelementptr inbounds i8, ptr null, i64 1
45 %cnd = icmp eq ptr %gep, null
49 ;; Then show the results for non-constants. These use the inbounds provided
50 ;; UB fact to ignore the possible overflow cases.
52 define i1 @test_ne(ptr %base, i64 %idx) {
53 ; CHECK-LABEL: @test_ne(
55 ; CHECK-NEXT: [[CND:%.*]] = icmp ne ptr [[BASE:%.*]], null
56 ; CHECK-NEXT: ret i1 [[CND]]
59 %gep = getelementptr inbounds i8, ptr %base, i64 %idx
60 %cnd = icmp ne ptr %gep, null
64 define i1 @test_eq(ptr %base, i64 %idx) {
65 ; CHECK-LABEL: @test_eq(
67 ; CHECK-NEXT: [[CND:%.*]] = icmp eq ptr [[BASE:%.*]], null
68 ; CHECK-NEXT: ret i1 [[CND]]
71 %gep = getelementptr inbounds i8, ptr %base, i64 %idx
72 %cnd = icmp eq ptr %gep, null
76 define <2 x i1> @test_vector_base(<2 x ptr> %base, i64 %idx) {
77 ; CHECK-LABEL: @test_vector_base(
79 ; CHECK-NEXT: [[CND:%.*]] = icmp eq <2 x ptr> [[BASE:%.*]], zeroinitializer
80 ; CHECK-NEXT: ret <2 x i1> [[CND]]
83 %gep = getelementptr inbounds i8, <2 x ptr> %base, i64 %idx
84 %cnd = icmp eq <2 x ptr> %gep, zeroinitializer
88 define <2 x i1> @test_vector_index(ptr %base, <2 x i64> %idx) {
89 ; CHECK-LABEL: @test_vector_index(
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]]
97 %gep = getelementptr inbounds i8, ptr %base, <2 x i64> %idx
98 %cnd = icmp eq <2 x ptr> %gep, zeroinitializer
102 define <2 x i1> @test_vector_both(<2 x ptr> %base, <2 x i64> %idx) {
103 ; CHECK-LABEL: @test_vector_both(
105 ; CHECK-NEXT: [[CND:%.*]] = icmp eq <2 x ptr> [[BASE:%.*]], zeroinitializer
106 ; CHECK-NEXT: ret <2 x i1> [[CND]]
109 %gep = getelementptr inbounds i8, <2 x ptr> %base, <2 x i64> %idx
110 %cnd = icmp eq <2 x ptr> %gep, zeroinitializer
114 ;; These two show instsimplify's reasoning getting to the non-zero offsets
115 ;; before instcombine does.
117 define i1 @test_eq_pos_idx(ptr %base) {
118 ; CHECK-LABEL: @test_eq_pos_idx(
120 ; CHECK-NEXT: ret i1 false
123 %gep = getelementptr inbounds i8, ptr %base, i64 1
124 %cnd = icmp eq ptr %gep, null
128 define i1 @test_eq_neg_idx(ptr %base) {
129 ; CHECK-LABEL: @test_eq_neg_idx(
131 ; CHECK-NEXT: ret i1 false
134 %gep = getelementptr inbounds i8, ptr %base, i64 -1
135 %cnd = icmp eq ptr %gep, null
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
143 define i1 @test_size0(ptr %base, i64 %idx) {
144 ; CHECK-LABEL: @test_size0(
146 ; CHECK-NEXT: [[CND:%.*]] = icmp ne ptr [[BASE:%.*]], null
147 ; CHECK-NEXT: ret i1 [[CND]]
150 %gep = getelementptr inbounds {}, ptr %base, i64 %idx
151 %cnd = icmp ne ptr %gep, null
154 define i1 @test_size0_nonzero_offset(ptr %base) {
155 ; CHECK-LABEL: @test_size0_nonzero_offset(
157 ; CHECK-NEXT: [[CND:%.*]] = icmp ne ptr [[BASE:%.*]], null
158 ; CHECK-NEXT: ret i1 [[CND]]
161 %gep = getelementptr inbounds {}, ptr %base, i64 15
162 %cnd = icmp ne ptr %gep, null
167 define i1 @test_index_type(ptr %base, i64 %idx) {
168 ; CHECK-LABEL: @test_index_type(
170 ; CHECK-NEXT: [[CND:%.*]] = icmp eq ptr [[BASE:%.*]], null
171 ; CHECK-NEXT: ret i1 [[CND]]
174 %gep = getelementptr inbounds [10 x i8], ptr %base, i64 %idx, i64 %idx
175 %cnd = icmp eq ptr %gep, null
180 ;; Finally, some negative tests for basic correctness checking.
182 define i1 @neq_noinbounds(ptr %base, i64 %idx) {
183 ; CHECK-LABEL: @neq_noinbounds(
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]]
190 %gep = getelementptr i8, ptr %base, i64 %idx
191 %cnd = icmp ne ptr %gep, null
195 define i1 @neg_objectatnull(ptr addrspace(2) %base, i64 %idx) {
196 ; CHECK-LABEL: @neg_objectatnull(
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]]
203 %gep = getelementptr inbounds i8, ptr addrspace(2) %base, i64 %idx
204 %cnd = icmp eq ptr addrspace(2) %gep, null
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
212 define i1 @invalid_bitcast_icmp_addrspacecast_as0_null(ptr addrspace(5) %ptr) {
213 ; CHECK-LABEL: @invalid_bitcast_icmp_addrspacecast_as0_null(
215 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq ptr addrspace(5) [[PTR:%.*]], addrspacecast (ptr null to ptr addrspace(5))
216 ; CHECK-NEXT: ret i1 [[TMP2]]
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))
224 define i1 @invalid_bitcast_icmp_addrspacecast_as0_null_var(ptr addrspace(5) %ptr, i32 %idx) {
225 ; CHECK-LABEL: @invalid_bitcast_icmp_addrspacecast_as0_null_var(
227 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq ptr addrspace(5) [[PTR:%.*]], addrspacecast (ptr null to ptr addrspace(5))
228 ; CHECK-NEXT: ret i1 [[TMP2]]
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))