235 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S < %s -passes=instcombine | FileCheck %s3 4;; Start by showing the results of constant folding (which doesn't use5;; 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 false11;12entry:13 %cnd = icmp ne ptr null, null14 ret i1 %cnd15}16 17define i1 @test_ne_constants_nonnull() {18; CHECK-LABEL: @test_ne_constants_nonnull(19; CHECK-NEXT: entry:20; CHECK-NEXT: ret i1 true21;22entry:23 %gep = getelementptr inbounds i8, ptr null, i64 124 %cnd = icmp ne ptr %gep, null25 ret i1 %cnd26}27 28define i1 @test_eq_constants_null() {29; CHECK-LABEL: @test_eq_constants_null(30; CHECK-NEXT: entry:31; CHECK-NEXT: ret i1 true32;33entry:34 %cnd = icmp eq ptr null, null35 ret i1 %cnd36}37 38define i1 @test_eq_constants_nonnull() {39; CHECK-LABEL: @test_eq_constants_nonnull(40; CHECK-NEXT: entry:41; CHECK-NEXT: ret i1 false42;43entry:44 %gep = getelementptr inbounds i8, ptr null, i64 145 %cnd = icmp eq ptr %gep, null46 ret i1 %cnd47}48 49;; Then show the results for non-constants. These use the inbounds provided50;; 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:%.*]], null56; CHECK-NEXT: ret i1 [[CND]]57;58entry:59 %gep = getelementptr inbounds i8, ptr %base, i64 %idx60 %cnd = icmp ne ptr %gep, null61 ret i1 %cnd62}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:%.*]], null68; CHECK-NEXT: ret i1 [[CND]]69;70entry:71 %gep = getelementptr inbounds i8, ptr %base, i64 %idx72 %cnd = icmp eq ptr %gep, null73 ret i1 %cnd74}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:%.*]], zeroinitializer80; CHECK-NEXT: ret <2 x i1> [[CND]]81;82entry:83 %gep = getelementptr inbounds i8, <2 x ptr> %base, i64 %idx84 %cnd = icmp eq <2 x ptr> %gep, zeroinitializer85 ret <2 x i1> %cnd86}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 092; CHECK-NEXT: [[TMP0:%.*]] = icmp eq <2 x ptr> [[DOTSPLATINSERT]], zeroinitializer93; CHECK-NEXT: [[CND:%.*]] = shufflevector <2 x i1> [[TMP0]], <2 x i1> poison, <2 x i32> zeroinitializer94; CHECK-NEXT: ret <2 x i1> [[CND]]95;96entry:97 %gep = getelementptr inbounds i8, ptr %base, <2 x i64> %idx98 %cnd = icmp eq <2 x ptr> %gep, zeroinitializer99 ret <2 x i1> %cnd100}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:%.*]], zeroinitializer106; CHECK-NEXT: ret <2 x i1> [[CND]]107;108entry:109 %gep = getelementptr inbounds i8, <2 x ptr> %base, <2 x i64> %idx110 %cnd = icmp eq <2 x ptr> %gep, zeroinitializer111 ret <2 x i1> %cnd112}113 114;; These two show instsimplify's reasoning getting to the non-zero offsets115;; 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 false121;122entry:123 %gep = getelementptr inbounds i8, ptr %base, i64 1124 %cnd = icmp eq ptr %gep, null125 ret i1 %cnd126}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 false132;133entry:134 %gep = getelementptr inbounds i8, ptr %base, i64 -1135 %cnd = icmp eq ptr %gep, null136 ret i1 %cnd137}138 139;; Show an example with a zero sized type since that's140;; a cornercase which keeps getting mentioned. The GEP141;; produces %base regardless of the value of the index142;; 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:%.*]], null147; CHECK-NEXT: ret i1 [[CND]]148;149entry:150 %gep = getelementptr inbounds {}, ptr %base, i64 %idx151 %cnd = icmp ne ptr %gep, null152 ret i1 %cnd153}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:%.*]], null158; CHECK-NEXT: ret i1 [[CND]]159;160entry:161 %gep = getelementptr inbounds {}, ptr %base, i64 15162 %cnd = icmp ne ptr %gep, null163 ret i1 %cnd164}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:%.*]], null171; CHECK-NEXT: ret i1 [[CND]]172;173entry:174 %gep = getelementptr inbounds [10 x i8], ptr %base, i64 %idx, i64 %idx175 %cnd = icmp eq ptr %gep, null176 ret i1 %cnd177}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]], null187; CHECK-NEXT: ret i1 [[CND]]188;189entry:190 %gep = getelementptr i8, ptr %base, i64 %idx191 %cnd = icmp ne ptr %gep, null192 ret i1 %cnd193}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]], null200; CHECK-NEXT: ret i1 [[CND]]201;202entry:203 %gep = getelementptr inbounds i8, ptr addrspace(2) %base, i64 %idx204 %cnd = icmp eq ptr addrspace(2) %gep, null205 ret i1 %cnd206}207 208; Test for an assert from trying to create an invalid constantexpr209; bitcast between different address spaces. The addrspacecast is210; stripped off and the addrspace(0) null can be treated as invalid.211; FIXME: This should be able to fold to ret i1 false212define 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 1220 %tmp2 = icmp eq ptr addrspace(5) %tmp1, addrspacecast (ptr null to ptr addrspace(5))221 ret i1 %tmp2222}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 %idx232 %tmp2 = icmp eq ptr addrspace(5) %tmp1, addrspacecast (ptr null to ptr addrspace(5))233 ret i1 %tmp2234}235