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