1127 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=instcombine -S < %s | FileCheck %s3 4target datalayout = "e-p:64:64:64-p1:16:16:16-p2:32:32:32-p3:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"5 6declare ptr @getptr()7declare void @use(ptr)8declare void @use.i1(i1)9 10define i1 @eq_base(ptr %x, i64 %y) {11; CHECK-LABEL: @eq_base(12; CHECK-NEXT: [[R:%.*]] = icmp eq i64 [[Y:%.*]], 013; CHECK-NEXT: ret i1 [[R]]14;15 %g = getelementptr i8, ptr %x, i64 %y16 %r = icmp eq ptr %g, %x17 ret i1 %r18}19 20define i1 @ne_base_commute(i64 %y) {21; CHECK-LABEL: @ne_base_commute(22; CHECK-NEXT: [[X:%.*]] = call ptr @getptr()23; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[Y:%.*]], 024; CHECK-NEXT: ret i1 [[R]]25;26 %x = call ptr @getptr() ; thwart complexity-based canonicalization27 %g = getelementptr i8, ptr %x, i64 %y28 %r = icmp ne ptr %x, %g29 ret i1 %r30}31 32define i1 @ne_base_inbounds(ptr %x, i64 %y) {33; CHECK-LABEL: @ne_base_inbounds(34; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[Y:%.*]], 035; CHECK-NEXT: ret i1 [[R]]36;37 %g = getelementptr inbounds i8, ptr %x, i64 %y38 %r = icmp ne ptr %g, %x39 ret i1 %r40}41 42define i1 @eq_base_inbounds_commute(i64 %y) {43; CHECK-LABEL: @eq_base_inbounds_commute(44; CHECK-NEXT: [[X:%.*]] = call ptr @getptr()45; CHECK-NEXT: [[R:%.*]] = icmp eq i64 [[Y:%.*]], 046; CHECK-NEXT: ret i1 [[R]]47;48 %x = call ptr @getptr() ; thwart complexity-based canonicalization49 %g = getelementptr inbounds i8, ptr %x, i64 %y50 %r = icmp eq ptr %x, %g51 ret i1 %r52}53 54define i1 @slt_base(ptr %x, i64 %y) {55; CHECK-LABEL: @slt_base(56; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 [[Y:%.*]]57; CHECK-NEXT: [[R:%.*]] = icmp slt ptr [[G]], [[X]]58; CHECK-NEXT: ret i1 [[R]]59;60 %g = getelementptr i8, ptr %x, i64 %y61 %r = icmp slt ptr %g, %x62 ret i1 %r63}64 65define i1 @sgt_base_commute(i64 %y) {66; CHECK-LABEL: @sgt_base_commute(67; CHECK-NEXT: [[X:%.*]] = call ptr @getptr()68; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[X]], i64 [[Y:%.*]]69; CHECK-NEXT: [[R:%.*]] = icmp sgt ptr [[X]], [[G]]70; CHECK-NEXT: ret i1 [[R]]71;72 %x = call ptr @getptr() ; thwart complexity-based canonicalization73 %g = getelementptr i8, ptr %x, i64 %y74 %r = icmp sgt ptr %x, %g75 ret i1 %r76}77 78define i1 @slt_base_inbounds(ptr %x, i64 %y) {79; CHECK-LABEL: @slt_base_inbounds(80; CHECK-NEXT: [[G:%.*]] = getelementptr inbounds i8, ptr [[X:%.*]], i64 [[Y:%.*]]81; CHECK-NEXT: [[R:%.*]] = icmp slt ptr [[G]], [[X]]82; CHECK-NEXT: ret i1 [[R]]83;84 %g = getelementptr inbounds i8, ptr %x, i64 %y85 %r = icmp slt ptr %g, %x86 ret i1 %r87}88 89define i1 @sgt_base_inbounds_commute(i64 %y) {90; CHECK-LABEL: @sgt_base_inbounds_commute(91; CHECK-NEXT: [[X:%.*]] = call ptr @getptr()92; CHECK-NEXT: [[G:%.*]] = getelementptr inbounds i8, ptr [[X]], i64 [[Y:%.*]]93; CHECK-NEXT: [[R:%.*]] = icmp sgt ptr [[X]], [[G]]94; CHECK-NEXT: ret i1 [[R]]95;96 %x = call ptr @getptr() ; thwart complexity-based canonicalization97 %g = getelementptr inbounds i8, ptr %x, i64 %y98 %r = icmp sgt ptr %x, %g99 ret i1 %r100}101 102define i1 @ult_base(ptr %x, i64 %y) {103; CHECK-LABEL: @ult_base(104; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 [[Y:%.*]]105; CHECK-NEXT: [[R:%.*]] = icmp ult ptr [[G]], [[X]]106; CHECK-NEXT: ret i1 [[R]]107;108 %g = getelementptr i8, ptr %x, i64 %y109 %r = icmp ult ptr %g, %x110 ret i1 %r111}112 113define i1 @ugt_base_commute(i64 %y) {114; CHECK-LABEL: @ugt_base_commute(115; CHECK-NEXT: [[X:%.*]] = call ptr @getptr()116; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[X]], i64 [[Y:%.*]]117; CHECK-NEXT: [[R:%.*]] = icmp ugt ptr [[X]], [[G]]118; CHECK-NEXT: ret i1 [[R]]119;120 %x = call ptr @getptr() ; thwart complexity-based canonicalization121 %g = getelementptr i8, ptr %x, i64 %y122 %r = icmp ugt ptr %x, %g123 ret i1 %r124}125 126define i1 @ult_base_inbounds(ptr %x, i64 %y) {127; CHECK-LABEL: @ult_base_inbounds(128; CHECK-NEXT: [[R:%.*]] = icmp slt i64 [[Y:%.*]], 0129; CHECK-NEXT: ret i1 [[R]]130;131 %g = getelementptr inbounds i8, ptr %x, i64 %y132 %r = icmp ult ptr %g, %x133 ret i1 %r134}135 136define i1 @ult_base_nusw(ptr %x, i64 %y) {137; CHECK-LABEL: @ult_base_nusw(138; CHECK-NEXT: [[R:%.*]] = icmp slt i64 [[Y:%.*]], 0139; CHECK-NEXT: ret i1 [[R]]140;141 %g = getelementptr nusw i8, ptr %x, i64 %y142 %r = icmp ult ptr %g, %x143 ret i1 %r144}145 146define i1 @ugt_base_nuw(ptr %x, i64 %y) {147; CHECK-LABEL: @ugt_base_nuw(148; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[Y:%.*]], 0149; CHECK-NEXT: ret i1 [[R]]150;151 %g = getelementptr nuw i8, ptr %x, i64 %y152 %r = icmp ugt ptr %g, %x153 ret i1 %r154}155 156define i1 @ugt_base_nusw_nuw(ptr %x, i64 %y) {157; CHECK-LABEL: @ugt_base_nusw_nuw(158; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[Y:%.*]], 0159; CHECK-NEXT: ret i1 [[R]]160;161 %g = getelementptr nusw nuw i8, ptr %x, i64 %y162 %r = icmp ugt ptr %g, %x163 ret i1 %r164}165 166define i1 @uge_base_nuw(ptr %x, i64 %y) {167; CHECK-LABEL: @uge_base_nuw(168; CHECK-NEXT: ret i1 true169;170 %g = getelementptr nuw i8, ptr %x, i64 %y171 %r = icmp uge ptr %g, %x172 ret i1 %r173}174 175define i1 @uge_base_nusw_nuw(ptr %x, i64 %y) {176; CHECK-LABEL: @uge_base_nusw_nuw(177; CHECK-NEXT: ret i1 true178;179 %g = getelementptr nusw nuw i8, ptr %x, i64 %y180 %r = icmp uge ptr %g, %x181 ret i1 %r182}183 184define i1 @ugt_base_inbounds_commute(i64 %y) {185; CHECK-LABEL: @ugt_base_inbounds_commute(186; CHECK-NEXT: [[X:%.*]] = call ptr @getptr()187; CHECK-NEXT: [[R:%.*]] = icmp slt i64 [[Y:%.*]], 0188; CHECK-NEXT: ret i1 [[R]]189;190 %x = call ptr @getptr() ; thwart complexity-based canonicalization191 %g = getelementptr inbounds i8, ptr %x, i64 %y192 %r = icmp ugt ptr %x, %g193 ret i1 %r194}195 196define i1 @ne_base_inbounds_use(ptr %x, i64 %y) {197; CHECK-LABEL: @ne_base_inbounds_use(198; CHECK-NEXT: [[G:%.*]] = getelementptr inbounds i8, ptr [[X:%.*]], i64 [[Y:%.*]]199; CHECK-NEXT: call void @use(ptr [[G]])200; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[Y]], 0201; CHECK-NEXT: ret i1 [[R]]202;203 %g = getelementptr inbounds i8, ptr %x, i64 %y204 call void @use(ptr %g)205 %r = icmp ne ptr %g, %x206 ret i1 %r207}208 209define i1 @eq_base_inbounds_commute_use(i64 %y) {210; CHECK-LABEL: @eq_base_inbounds_commute_use(211; CHECK-NEXT: [[X:%.*]] = call ptr @getptr()212; CHECK-NEXT: [[G:%.*]] = getelementptr inbounds i8, ptr [[X]], i64 [[Y:%.*]]213; CHECK-NEXT: call void @use(ptr [[G]])214; CHECK-NEXT: [[R:%.*]] = icmp eq i64 [[Y]], 0215; CHECK-NEXT: ret i1 [[R]]216;217 %x = call ptr @getptr() ; thwart complexity-based canonicalization218 %g = getelementptr inbounds i8, ptr %x, i64 %y219 call void @use(ptr %g)220 %r = icmp eq ptr %x, %g221 ret i1 %r222}223 224define i1 @ne_base_inbounds_use_scaled(ptr %x, i64 %y) {225; CHECK-LABEL: @ne_base_inbounds_use_scaled(226; CHECK-NEXT: [[G_IDX:%.*]] = shl nsw i64 [[Y:%.*]], 3227; CHECK-NEXT: [[G:%.*]] = getelementptr inbounds i8, ptr [[X:%.*]], i64 [[G_IDX]]228; CHECK-NEXT: call void @use(ptr [[G]])229; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[Y]], 0230; CHECK-NEXT: ret i1 [[R]]231;232 %g = getelementptr inbounds i64, ptr %x, i64 %y233 call void @use(ptr %g)234 %r = icmp ne ptr %g, %x235 ret i1 %r236}237 238define i1 @ne_base_use_scaled(ptr %x, i64 %y) {239; CHECK-LABEL: @ne_base_use_scaled(240; CHECK-NEXT: [[G_IDX_MASK:%.*]] = shl i64 [[Y:%.*]], 3241; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 [[G_IDX_MASK]]242; CHECK-NEXT: call void @use(ptr [[G]])243; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[G_IDX_MASK]], 0244; CHECK-NEXT: ret i1 [[R]]245;246 %g = getelementptr i64, ptr %x, i64 %y247 call void @use(ptr %g)248 %r = icmp ne ptr %g, %x249 ret i1 %r250}251 252define i1 @eq_bitcast_base(ptr %p, i64 %x) {253; CHECK-LABEL: @eq_bitcast_base(254; CHECK-NEXT: [[GEP_IDX_MASK:%.*]] = and i64 [[X:%.*]], 9223372036854775807255; CHECK-NEXT: [[R:%.*]] = icmp eq i64 [[GEP_IDX_MASK]], 0256; CHECK-NEXT: ret i1 [[R]]257;258 %gep = getelementptr [2 x i8], ptr %p, i64 %x, i64 0259 %r = icmp eq ptr %gep, %p260 ret i1 %r261}262 263define i1 @eq_bitcast_base_inbounds(ptr %p, i64 %x) {264; CHECK-LABEL: @eq_bitcast_base_inbounds(265; CHECK-NEXT: [[R:%.*]] = icmp eq i64 [[X:%.*]], 0266; CHECK-NEXT: ret i1 [[R]]267;268 %gep = getelementptr inbounds [2 x i8], ptr %p, i64 %x, i64 0269 %r = icmp eq ptr %gep, %p270 ret i1 %r271}272 273@X = global [1000 x i32] zeroinitializer274 275define i1 @PR8882(i64 %i) {276; CHECK-LABEL: @PR8882(277; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[I:%.*]], 1000278; CHECK-NEXT: ret i1 [[CMP]]279;280 %p1 = getelementptr inbounds i32, ptr @X, i64 %i281 %cmp = icmp eq ptr %p1, getelementptr inbounds ([1000 x i32], ptr @X, i64 1, i64 0)282 ret i1 %cmp283}284 285@X_as1 = addrspace(1) global [1000 x i32] zeroinitializer286 287define i1 @test24_as1(i64 %i) {288; CHECK-LABEL: @test24_as1(289; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[TMP1:%.*]], 1000290; CHECK-NEXT: ret i1 [[CMP]]291;292 %p1 = getelementptr inbounds i32, ptr addrspace(1) @X_as1, i64 %i293 %cmp = icmp eq ptr addrspace(1) %p1, getelementptr inbounds ([1000 x i32], ptr addrspace(1) @X_as1, i64 1, i64 0)294 ret i1 %cmp295}296 297; PR16244298define i1 @test71(ptr %x) {299; CHECK-LABEL: @test71(300; CHECK-NEXT: ret i1 false301;302 %a = getelementptr i8, ptr %x, i64 8303 %b = getelementptr inbounds i8, ptr %x, i64 8304 %c = icmp ugt ptr %a, %b305 ret i1 %c306}307 308define i1 @test71_as1(ptr addrspace(1) %x) {309; CHECK-LABEL: @test71_as1(310; CHECK-NEXT: ret i1 false311;312 %a = getelementptr i8, ptr addrspace(1) %x, i64 8313 %b = getelementptr inbounds i8, ptr addrspace(1) %x, i64 8314 %c = icmp ugt ptr addrspace(1) %a, %b315 ret i1 %c316}317 318declare i32 @test58_d(i64)319 320define i1 @test59(ptr %foo) {321; CHECK-LABEL: @test59(322; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO:%.*]], i64 8323; CHECK-NEXT: [[USE:%.*]] = ptrtoint ptr [[GEP1]] to i64324; CHECK-NEXT: [[CALL:%.*]] = call i32 @test58_d(i64 [[USE]])325; CHECK-NEXT: ret i1 true326;327 %gep1 = getelementptr inbounds i32, ptr %foo, i64 2328 %gep2 = getelementptr inbounds i8, ptr %foo, i64 10329 %cmp = icmp ult ptr %gep1, %gep2330 %use = ptrtoint ptr %gep1 to i64331 %call = call i32 @test58_d(i64 %use)332 ret i1 %cmp333}334 335define i1 @test59_as1(ptr addrspace(1) %foo) {336; CHECK-LABEL: @test59_as1(337; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(1) [[FOO:%.*]], i16 8338; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr addrspace(1) [[GEP1]] to i16339; CHECK-NEXT: [[USE:%.*]] = zext i16 [[TMP1]] to i64340; CHECK-NEXT: [[CALL:%.*]] = call i32 @test58_d(i64 [[USE]])341; CHECK-NEXT: ret i1 true342;343 %gep1 = getelementptr inbounds i32, ptr addrspace(1) %foo, i64 2344 %gep2 = getelementptr inbounds i8, ptr addrspace(1) %foo, i64 10345 %cmp = icmp ult ptr addrspace(1) %gep1, %gep2346 %use = ptrtoint ptr addrspace(1) %gep1 to i64347 %call = call i32 @test58_d(i64 %use)348 ret i1 %cmp349}350 351define i1 @test60(ptr %foo, i64 %i, i64 %j) {352; CHECK-LABEL: @test60(353; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2354; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[J:%.*]]355; CHECK-NEXT: ret i1 [[CMP]]356;357 %gep1 = getelementptr inbounds i32, ptr %foo, i64 %i358 %gep2 = getelementptr inbounds i8, ptr %foo, i64 %j359 %cmp = icmp ult ptr %gep1, %gep2360 ret i1 %cmp361}362 363define i1 @test60_nusw(ptr %foo, i64 %i, i64 %j) {364; CHECK-LABEL: @test60_nusw(365; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2366; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[J:%.*]]367; CHECK-NEXT: ret i1 [[CMP]]368;369 %gep1 = getelementptr nusw i32, ptr %foo, i64 %i370 %gep2 = getelementptr nusw i8, ptr %foo, i64 %j371 %cmp = icmp ult ptr %gep1, %gep2372 ret i1 %cmp373}374 375define i1 @test60_nusw_inbounds(ptr %foo, i64 %i, i64 %j) {376; CHECK-LABEL: @test60_nusw_inbounds(377; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2378; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[J:%.*]]379; CHECK-NEXT: ret i1 [[CMP]]380;381 %gep1 = getelementptr nusw i32, ptr %foo, i64 %i382 %gep2 = getelementptr inbounds i8, ptr %foo, i64 %j383 %cmp = icmp ult ptr %gep1, %gep2384 ret i1 %cmp385}386 387define i1 @test60_nuw(ptr %foo, i64 %i, i64 %j) {388; CHECK-LABEL: @test60_nuw(389; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw i64 [[I:%.*]], 2390; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[GEP1_IDX]], [[J:%.*]]391; CHECK-NEXT: ret i1 [[CMP]]392;393 %gep1 = getelementptr nuw i32, ptr %foo, i64 %i394 %gep2 = getelementptr nuw i8, ptr %foo, i64 %j395 %cmp = icmp ult ptr %gep1, %gep2396 ret i1 %cmp397}398 399define i1 @test60_nusw_nuw(ptr %foo, i64 %i, i64 %j) {400; CHECK-LABEL: @test60_nusw_nuw(401; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw nsw i64 [[I:%.*]], 2402; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i64 [[GEP1_IDX]], [[J:%.*]]403; CHECK-NEXT: ret i1 [[CMP]]404;405 %gep1 = getelementptr nusw nuw i32, ptr %foo, i64 %i406 %gep2 = getelementptr nusw nuw i8, ptr %foo, i64 %j407 %cmp = icmp ult ptr %gep1, %gep2408 ret i1 %cmp409}410 411define i1 @test60_nusw_nuw_mix(ptr %foo, i64 %i, i64 %j) {412; CHECK-LABEL: @test60_nusw_nuw_mix(413; CHECK-NEXT: [[GEP1:%.*]] = getelementptr nuw i32, ptr [[FOO:%.*]], i64 [[I:%.*]]414; CHECK-NEXT: [[GEP2:%.*]] = getelementptr nusw i8, ptr [[FOO]], i64 [[J:%.*]]415; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[GEP1]], [[GEP2]]416; CHECK-NEXT: ret i1 [[CMP]]417;418 %gep1 = getelementptr nuw i32, ptr %foo, i64 %i419 %gep2 = getelementptr nusw i8, ptr %foo, i64 %j420 %cmp = icmp ult ptr %gep1, %gep2421 ret i1 %cmp422}423 424define i1 @test_gep_ult_no_inbounds(ptr %foo, i64 %i, i64 %j) {425; CHECK-LABEL: @test_gep_ult_no_inbounds(426; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, ptr [[FOO:%.*]], i64 [[I:%.*]]427; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr [[FOO]], i64 [[J:%.*]]428; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[GEP1]], [[GEP2]]429; CHECK-NEXT: ret i1 [[CMP]]430;431 %gep1 = getelementptr i32, ptr %foo, i64 %i432 %gep2 = getelementptr i8, ptr %foo, i64 %j433 %cmp = icmp ult ptr %gep1, %gep2434 ret i1 %cmp435}436 437define i1 @test_gep_eq_no_inbounds(ptr %foo, i64 %i, i64 %j) {438; CHECK-LABEL: @test_gep_eq_no_inbounds(439; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl i64 [[I:%.*]], 2440; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[GEP1_IDX]], [[J:%.*]]441; CHECK-NEXT: ret i1 [[CMP]]442;443 %gep1 = getelementptr i32, ptr %foo, i64 %i444 %gep2 = getelementptr i8, ptr %foo, i64 %j445 %cmp = icmp eq ptr %gep1, %gep2446 ret i1 %cmp447}448 449define i1 @test60_as1(ptr addrspace(1) %foo, i64 %i, i64 %j) {450; CHECK-LABEL: @test60_as1(451; CHECK-NEXT: [[TMP1:%.*]] = trunc nsw i64 [[I:%.*]] to i16452; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i16 [[TMP1]], 2453; CHECK-NEXT: [[TMP2:%.*]] = trunc nsw i64 [[J:%.*]] to i16454; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[GEP1_IDX]], [[TMP2]]455; CHECK-NEXT: ret i1 [[CMP]]456;457 %gep1 = getelementptr inbounds i32, ptr addrspace(1) %foo, i64 %i458 %gep2 = getelementptr inbounds i8, ptr addrspace(1) %foo, i64 %j459 %cmp = icmp ult ptr addrspace(1) %gep1, %gep2460 ret i1 %cmp461}462 463; Same as test60, but look through an addrspacecast instead of a464; bitcast. This uses the same sized addrspace.465define i1 @test60_addrspacecast(ptr %foo, i64 %i, i64 %j) {466; CHECK-LABEL: @test60_addrspacecast(467; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2468; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[J:%.*]], [[GEP1_IDX]]469; CHECK-NEXT: ret i1 [[CMP]]470;471 %bit = addrspacecast ptr %foo to ptr addrspace(3)472 %gep1 = getelementptr inbounds i32, ptr addrspace(3) %bit, i64 %i473 %gep2 = getelementptr inbounds i8, ptr %foo, i64 %j474 %cast1 = addrspacecast ptr addrspace(3) %gep1 to ptr475 %cmp = icmp ult ptr %cast1, %gep2476 ret i1 %cmp477}478 479define i1 @test60_addrspacecast_smaller(ptr %foo, i16 %i, i64 %j) {480; CHECK-LABEL: @test60_addrspacecast_smaller(481; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i16 [[I:%.*]], 2482; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[J:%.*]] to i16483; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[GEP1_IDX]], [[TMP1]]484; CHECK-NEXT: ret i1 [[CMP]]485;486 %bit = addrspacecast ptr %foo to ptr addrspace(1)487 %gep1 = getelementptr inbounds i32, ptr addrspace(1) %bit, i16 %i488 %gep2 = getelementptr inbounds i8, ptr %foo, i64 %j489 %cast1 = addrspacecast ptr addrspace(1) %gep1 to ptr490 %cmp = icmp ult ptr %cast1, %gep2491 ret i1 %cmp492}493 494define i1 @test60_addrspacecast_larger(ptr addrspace(1) %foo, i32 %i, i16 %j) {495; CHECK-LABEL: @test60_addrspacecast_larger(496; CHECK-NEXT: [[I_TR:%.*]] = trunc i32 [[I:%.*]] to i16497; CHECK-NEXT: [[TMP1:%.*]] = shl i16 [[I_TR]], 2498; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i16 [[J:%.*]], [[TMP1]]499; CHECK-NEXT: ret i1 [[CMP]]500;501 %bit = addrspacecast ptr addrspace(1) %foo to ptr addrspace(2)502 %gep1 = getelementptr inbounds i32, ptr addrspace(2) %bit, i32 %i503 %gep2 = getelementptr inbounds i8, ptr addrspace(1) %foo, i16 %j504 %cast1 = addrspacecast ptr addrspace(2) %gep1 to ptr addrspace(1)505 %cmp = icmp ult ptr addrspace(1) %cast1, %gep2506 ret i1 %cmp507}508 509define i1 @test61(ptr %foo, i64 %i, i64 %j) {510; CHECK-LABEL: @test61(511; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, ptr [[FOO:%.*]], i64 [[I:%.*]]512; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr [[FOO]], i64 [[J:%.*]]513; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[GEP1]], [[GEP2]]514; CHECK-NEXT: ret i1 [[CMP]]515;516 %gep1 = getelementptr i32, ptr %foo, i64 %i517 %gep2 = getelementptr i8, ptr %foo, i64 %j518 %cmp = icmp ult ptr %gep1, %gep2519 ret i1 %cmp520; Don't transform non-inbounds GEPs.521}522 523define i1 @test61_as1(ptr addrspace(1) %foo, i16 %i, i16 %j) {524; CHECK-LABEL: @test61_as1(525; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, ptr addrspace(1) [[FOO:%.*]], i16 [[I:%.*]]526; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr addrspace(1) [[FOO]], i16 [[J:%.*]]527; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr addrspace(1) [[GEP1]], [[GEP2]]528; CHECK-NEXT: ret i1 [[CMP]]529;530 %gep1 = getelementptr i32, ptr addrspace(1) %foo, i16 %i531 %gep2 = getelementptr i8, ptr addrspace(1) %foo, i16 %j532 %cmp = icmp ult ptr addrspace(1) %gep1, %gep2533 ret i1 %cmp534; Don't transform non-inbounds GEPs.535}536 537define i1 @test60_extra_use(ptr %foo, i64 %i, i64 %j) {538; CHECK-LABEL: @test60_extra_use(539; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2540; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[FOO:%.*]], i64 [[GEP1_IDX]]541; CHECK-NEXT: [[GEP2_IDX:%.*]] = shl nsw i64 [[J:%.*]], 1542; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[FOO]], i64 [[GEP2_IDX]]543; CHECK-NEXT: call void @use(ptr [[GEP1]])544; CHECK-NEXT: call void @use(ptr [[GEP2]])545; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[GEP2_IDX]]546; CHECK-NEXT: ret i1 [[CMP]]547;548 %gep1 = getelementptr inbounds i32, ptr %foo, i64 %i549 %gep2 = getelementptr inbounds i16, ptr %foo, i64 %j550 call void @use(ptr %gep1)551 call void @use(ptr %gep2)552 %cmp = icmp ult ptr %gep1, %gep2553 ret i1 %cmp554}555 556define i1 @test60_extra_use_const_operands_inbounds(ptr %foo, i64 %i, i64 %j) {557; CHECK-LABEL: @test60_extra_use_const_operands_inbounds(558; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO:%.*]], i64 4559; CHECK-NEXT: call void @use(ptr nonnull [[GEP1]])560; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[J:%.*]], 2561; CHECK-NEXT: ret i1 [[CMP]]562;563 %gep1 = getelementptr inbounds i32, ptr %foo, i64 1564 %gep2 = getelementptr inbounds i16, ptr %foo, i64 %j565 call void @use(ptr %gep1)566 %cmp = icmp eq ptr %gep1, %gep2567 ret i1 %cmp568}569 570define i1 @test60_extra_use_const_operands_no_inbounds(ptr %foo, i64 %i, i64 %j) {571; CHECK-LABEL: @test60_extra_use_const_operands_no_inbounds(572; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[FOO:%.*]], i64 4573; CHECK-NEXT: call void @use(ptr [[GEP1]])574; CHECK-NEXT: [[GEP2_IDX_MASK:%.*]] = and i64 [[J:%.*]], 9223372036854775807575; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[GEP2_IDX_MASK]], 2576; CHECK-NEXT: ret i1 [[CMP]]577;578 %gep1 = getelementptr i32, ptr %foo, i64 1579 %gep2 = getelementptr i16, ptr %foo, i64 %j580 call void @use(ptr %gep1)581 %cmp = icmp eq ptr %gep1, %gep2582 ret i1 %cmp583}584 585define void @test60_extra_use_fold(ptr %foo, i64 %start.idx, i64 %end.offset) {586; CHECK-LABEL: @test60_extra_use_fold(587; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[START_IDX:%.*]], 2588; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[FOO:%.*]], i64 [[GEP1_IDX]]589; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[FOO]], i64 [[END_OFFSET:%.*]]590; CHECK-NEXT: call void @use(ptr [[GEP1]])591; CHECK-NEXT: call void @use(ptr [[GEP2]])592; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i64 [[GEP1_IDX]], [[END_OFFSET]]593; CHECK-NEXT: call void @use.i1(i1 [[CMP1]])594; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i64 [[GEP1_IDX]], [[END_OFFSET]]595; CHECK-NEXT: call void @use.i1(i1 [[CMP2]])596; CHECK-NEXT: ret void597;598 %gep1 = getelementptr inbounds i32, ptr %foo, i64 %start.idx599 %gep2 = getelementptr inbounds i8, ptr %foo, i64 %end.offset600 call void @use(ptr %gep1)601 call void @use(ptr %gep2)602 %cmp1 = icmp eq ptr %gep1, %gep2603 call void @use.i1(i1 %cmp1)604 %cmp2 = icmp ult ptr %gep1, %gep2605 call void @use.i1(i1 %cmp2)606 ret void607}608 609define i1 @test_scalable_same(ptr %x) {610; CHECK-LABEL: @test_scalable_same(611; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()612; CHECK-NEXT: [[A_IDX:%.*]] = shl i64 [[TMP1]], 5613; CHECK-NEXT: [[A:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 [[A_IDX]]614; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64()615; CHECK-NEXT: [[B_IDX:%.*]] = shl i64 [[TMP2]], 5616; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[X]], i64 [[B_IDX]]617; CHECK-NEXT: [[C:%.*]] = icmp ugt ptr [[A]], [[B]]618; CHECK-NEXT: ret i1 [[C]]619;620 %a = getelementptr <vscale x 4 x i8>, ptr %x, i64 8621 %b = getelementptr inbounds <vscale x 4 x i8>, ptr %x, i64 8622 %c = icmp ugt ptr %a, %b623 ret i1 %c624}625 626define i1 @test_scalable_x(ptr %x) {627; CHECK-LABEL: @test_scalable_x(628; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()629; CHECK-NEXT: [[A_IDX_MASK:%.*]] = and i64 [[TMP1]], 576460752303423487630; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[A_IDX_MASK]], 0631; CHECK-NEXT: ret i1 [[C]]632;633 %a = getelementptr <vscale x 4 x i8>, ptr %x, i64 8634 %c = icmp eq ptr %a, %x635 ret i1 %c636}637 638define i1 @test_scalable_xc(ptr %x) {639; CHECK-LABEL: @test_scalable_xc(640; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()641; CHECK-NEXT: [[A_IDX_MASK:%.*]] = and i64 [[TMP1]], 576460752303423487642; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[A_IDX_MASK]], 0643; CHECK-NEXT: ret i1 [[C]]644;645 %a = getelementptr <vscale x 4 x i8>, ptr %x, i64 8646 %c = icmp eq ptr %x, %a647 ret i1 %c648}649 650define i1 @test_scalable_xy(ptr %foo, i64 %i, i64 %j) {651; CHECK-LABEL: @test_scalable_xy(652; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()653; CHECK-NEXT: [[TMP2:%.*]] = shl nuw i64 [[TMP1]], 4654; CHECK-NEXT: [[GEP1_IDX:%.*]] = mul nsw i64 [[I:%.*]], [[TMP2]]655; CHECK-NEXT: [[TMP3:%.*]] = call i64 @llvm.vscale.i64()656; CHECK-NEXT: [[TMP4:%.*]] = shl nuw i64 [[TMP3]], 2657; CHECK-NEXT: [[GEP2_IDX:%.*]] = mul nsw i64 [[J:%.*]], [[TMP4]]658; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[GEP2_IDX]], [[GEP1_IDX]]659; CHECK-NEXT: ret i1 [[CMP]]660;661 %bit = addrspacecast ptr %foo to ptr addrspace(3)662 %gep1 = getelementptr inbounds <vscale x 4 x i32>, ptr addrspace(3) %bit, i64 %i663 %gep2 = getelementptr inbounds <vscale x 4 x i8>, ptr %foo, i64 %j664 %cast1 = addrspacecast ptr addrspace(3) %gep1 to ptr665 %cmp = icmp ult ptr %cast1, %gep2666 ret i1 %cmp667}668 669define i1 @test_scalable_ij(ptr %foo, i64 %i, i64 %j) {670; CHECK-LABEL: @test_scalable_ij(671; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()672; CHECK-NEXT: [[TMP2:%.*]] = shl nuw i64 [[TMP1]], 4673; CHECK-NEXT: [[GEP1_IDX:%.*]] = mul nsw i64 [[I:%.*]], [[TMP2]]674; CHECK-NEXT: [[TMP3:%.*]] = call i64 @llvm.vscale.i64()675; CHECK-NEXT: [[TMP4:%.*]] = shl nuw i64 [[TMP3]], 2676; CHECK-NEXT: [[GEP2_IDX:%.*]] = mul nsw i64 [[J:%.*]], [[TMP4]]677; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[GEP2_IDX]]678; CHECK-NEXT: ret i1 [[CMP]]679;680 %gep1 = getelementptr inbounds <vscale x 4 x i32>, ptr %foo, i64 %i681 %gep2 = getelementptr inbounds <vscale x 4 x i8>, ptr %foo, i64 %j682 %cmp = icmp ult ptr %gep1, %gep2683 ret i1 %cmp684}685 686define i1 @gep_nuw(ptr %p, i64 %a, i64 %b, i64 %c, i64 %d) {687; CHECK-LABEL: @gep_nuw(688; CHECK-NEXT: [[GEP1_SPLIT_IDX:%.*]] = shl nuw i64 [[A:%.*]], 2689; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw i64 [[B:%.*]], 1690; CHECK-NEXT: [[TMP1:%.*]] = add nuw i64 [[GEP1_SPLIT_IDX]], [[GEP1_IDX]]691; CHECK-NEXT: [[GEP2_SPLIT_IDX:%.*]] = shl nuw i64 [[C:%.*]], 3692; CHECK-NEXT: [[GEP2_IDX:%.*]] = shl nuw i64 [[D:%.*]], 2693; CHECK-NEXT: [[TMP2:%.*]] = add nuw i64 [[GEP2_SPLIT_IDX]], [[GEP2_IDX]]694; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[TMP1]], [[TMP2]]695; CHECK-NEXT: ret i1 [[CMP]]696;697 %gep1 = getelementptr nuw [2 x i16], ptr %p, i64 %a, i64 %b698 %gep2 = getelementptr nuw [2 x i32], ptr %p, i64 %c, i64 %d699 %cmp = icmp eq ptr %gep1, %gep2700 ret i1 %cmp701}702 703define i1 @gep_nusw(ptr %p, i64 %a, i64 %b, i64 %c, i64 %d) {704; CHECK-LABEL: @gep_nusw(705; CHECK-NEXT: [[GEP1_SPLIT_IDX:%.*]] = shl nsw i64 [[A:%.*]], 2706; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[B:%.*]], 1707; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[GEP1_SPLIT_IDX]], [[GEP1_IDX]]708; CHECK-NEXT: [[GEP2_SPLIT_IDX:%.*]] = shl nsw i64 [[C:%.*]], 3709; CHECK-NEXT: [[GEP2_IDX:%.*]] = shl nsw i64 [[D:%.*]], 2710; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[GEP2_SPLIT_IDX]], [[GEP2_IDX]]711; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[TMP1]], [[TMP2]]712; CHECK-NEXT: ret i1 [[CMP]]713;714 %gep1 = getelementptr nusw [2 x i16], ptr %p, i64 %a, i64 %b715 %gep2 = getelementptr nusw [2 x i32], ptr %p, i64 %c, i64 %d716 %cmp = icmp eq ptr %gep1, %gep2717 ret i1 %cmp718}719 720define i1 @pointer_icmp_aligned_with_offset(ptr align 8 %a, ptr align 8 %a2) {721; CHECK-LABEL: @pointer_icmp_aligned_with_offset(722; CHECK-NEXT: ret i1 false723;724 %gep = getelementptr i8, ptr %a, i64 4725 %cmp = icmp eq ptr %gep, %a2726 ret i1 %cmp727}728 729define i1 @pointer_icmp_aligned_with_offset_negative(ptr align 8 %a, ptr align 8 %a2) {730; CHECK-LABEL: @pointer_icmp_aligned_with_offset_negative(731; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 8732; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[GEP]], [[A2:%.*]]733; CHECK-NEXT: ret i1 [[CMP]]734;735 %gep = getelementptr i8, ptr %a, i64 8736 %cmp = icmp eq ptr %gep, %a2737 ret i1 %cmp738}739 740define i1 @gep_diff_base_same_indices(ptr %x, ptr %y, i64 %z) {741; CHECK-LABEL: @gep_diff_base_same_indices(742; CHECK-NEXT: [[X:%.*]] = getelementptr i8, ptr [[X1:%.*]], i64 [[Z:%.*]]743; CHECK-NEXT: [[Y:%.*]] = getelementptr i8, ptr [[Y1:%.*]], i64 [[Z]]744; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[X]], [[Y]]745; CHECK-NEXT: ret i1 [[CMP]]746;747 %gep1 = getelementptr i8, ptr %x, i64 %z748 %gep2 = getelementptr i8, ptr %y, i64 %z749 %cmp = icmp ult ptr %gep1, %gep2750 ret i1 %cmp751}752 753define i1 @gep_diff_base_same_indices_nuw(ptr %x, ptr %y, i64 %z) {754; CHECK-LABEL: @gep_diff_base_same_indices_nuw(755; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[X:%.*]], [[Y:%.*]]756; CHECK-NEXT: ret i1 [[CMP]]757;758 %gep1 = getelementptr nuw i8, ptr %x, i64 %z759 %gep2 = getelementptr nuw i8, ptr %y, i64 %z760 %cmp = icmp ult ptr %gep1, %gep2761 ret i1 %cmp762}763 764define i1 @gep_diff_base_same_indices_nusw(ptr %x, ptr %y, i64 %z) {765; CHECK-LABEL: @gep_diff_base_same_indices_nusw(766; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[X:%.*]], [[Y:%.*]]767; CHECK-NEXT: ret i1 [[CMP]]768;769 %gep1 = getelementptr nusw i8, ptr %x, i64 %z770 %gep2 = getelementptr nusw i8, ptr %y, i64 %z771 %cmp = icmp ult ptr %gep1, %gep2772 ret i1 %cmp773}774 775define i1 @gep_diff_base_same_indices_nuw_nusw(ptr %x, ptr %y, i64 %z) {776; CHECK-LABEL: @gep_diff_base_same_indices_nuw_nusw(777; CHECK-NEXT: [[X:%.*]] = getelementptr nuw i8, ptr [[X1:%.*]], i64 [[Z:%.*]]778; CHECK-NEXT: [[Y:%.*]] = getelementptr nusw i8, ptr [[Y1:%.*]], i64 [[Z]]779; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[X]], [[Y]]780; CHECK-NEXT: ret i1 [[CMP]]781;782 %gep1 = getelementptr nuw i8, ptr %x, i64 %z783 %gep2 = getelementptr nusw i8, ptr %y, i64 %z784 %cmp = icmp ult ptr %gep1, %gep2785 ret i1 %cmp786}787 788define i1 @gep_multiple_eq(ptr %base, i64 %idx, i64 %idx2) {789; CHECK-LABEL: @gep_multiple_eq(790; CHECK-NEXT: [[GEP1_IDX1:%.*]] = add i64 [[IDX:%.*]], [[IDX2:%.*]]791; CHECK-NEXT: [[DOTMASK:%.*]] = and i64 [[GEP1_IDX1]], 4611686018427387903792; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[DOTMASK]], 0793; CHECK-NEXT: ret i1 [[CMP]]794;795 %gep1 = getelementptr i32, ptr %base, i64 %idx796 %gep2 = getelementptr i32, ptr %gep1, i64 %idx2797 %cmp = icmp eq ptr %gep2, %base798 ret i1 %cmp799}800 801define i1 @gep_multiple_eq_commuted(ptr %base, i64 %idx, i64 %idx2) {802; CHECK-LABEL: @gep_multiple_eq_commuted(803; CHECK-NEXT: [[GEP1_IDX1:%.*]] = add i64 [[IDX:%.*]], [[IDX2:%.*]]804; CHECK-NEXT: [[DOTMASK:%.*]] = and i64 [[GEP1_IDX1]], 4611686018427387903805; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[DOTMASK]], 0806; CHECK-NEXT: ret i1 [[CMP]]807;808 %gep1 = getelementptr i32, ptr %base, i64 %idx809 %gep2 = getelementptr i32, ptr %gep1, i64 %idx2810 %cmp = icmp eq ptr %base, %gep2811 ret i1 %cmp812}813 814define i1 @gep_mugtiple_ugt_nuw(ptr %base, i64 %idx, i64 %idx2) {815; CHECK-LABEL: @gep_mugtiple_ugt_nuw(816; CHECK-NEXT: [[GEP1_IDX1:%.*]] = sub i64 0, [[IDX2:%.*]]817; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[IDX:%.*]], [[GEP1_IDX1]]818; CHECK-NEXT: ret i1 [[CMP]]819;820 %gep1 = getelementptr nuw i32, ptr %base, i64 %idx821 %gep2 = getelementptr nuw i32, ptr %gep1, i64 %idx2822 %cmp = icmp ugt ptr %gep2, %base823 ret i1 %cmp824}825 826define i1 @gep_mugtiple_ugt_not_all_nuw(ptr %base, i64 %idx, i64 %idx2) {827; CHECK-LABEL: @gep_mugtiple_ugt_not_all_nuw(828; CHECK-NEXT: [[GEP1:%.*]] = getelementptr nuw i32, ptr [[BASE:%.*]], i64 [[IDX:%.*]]829; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i32, ptr [[GEP1]], i64 [[IDX2:%.*]]830; CHECK-NEXT: [[CMP:%.*]] = icmp ugt ptr [[GEP2]], [[BASE]]831; CHECK-NEXT: ret i1 [[CMP]]832;833 %gep1 = getelementptr nuw i32, ptr %base, i64 %idx834 %gep2 = getelementptr i32, ptr %gep1, i64 %idx2835 %cmp = icmp ugt ptr %gep2, %base836 ret i1 %cmp837}838 839define i1 @gep_mugtiple_ugt_inbounds_nusw(ptr %base, i64 %idx, i64 %idx2) {840; CHECK-LABEL: @gep_mugtiple_ugt_inbounds_nusw(841; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i32, ptr [[BASE:%.*]], i64 [[IDX:%.*]]842; CHECK-NEXT: [[GEP2:%.*]] = getelementptr nusw i32, ptr [[GEP1]], i64 [[IDX2:%.*]]843; CHECK-NEXT: [[CMP:%.*]] = icmp ugt ptr [[GEP2]], [[BASE]]844; CHECK-NEXT: ret i1 [[CMP]]845;846 %gep1 = getelementptr inbounds i32, ptr %base, i64 %idx847 %gep2 = getelementptr nusw i32, ptr %gep1, i64 %idx2848 %cmp = icmp ugt ptr %gep2, %base849 ret i1 %cmp850}851 852define i1 @gep_multiple_multi_use_below_limit(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3) {853; CHECK-LABEL: @gep_multiple_multi_use_below_limit(854; CHECK-NEXT: [[GEP3_IDX:%.*]] = shl i64 [[IDX3:%.*]], 2855; CHECK-NEXT: [[GEP3:%.*]] = getelementptr i8, ptr [[GEP2:%.*]], i64 [[GEP3_IDX]]856; CHECK-NEXT: call void @use(ptr [[GEP3]])857; CHECK-NEXT: [[GEP2_IDX:%.*]] = shl i64 [[IDX2:%.*]], 2858; CHECK-NEXT: [[GEP4:%.*]] = getelementptr i8, ptr [[GEP3]], i64 [[GEP2_IDX]]859; CHECK-NEXT: call void @use(ptr [[GEP4]])860; CHECK-NEXT: [[GEP3_IDX1:%.*]] = shl i64 [[IDX4:%.*]], 2861; CHECK-NEXT: [[GEP5:%.*]] = getelementptr i8, ptr [[GEP4]], i64 [[GEP3_IDX1]]862; CHECK-NEXT: call void @use(ptr [[GEP5]])863; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[GEP3_IDX]], [[GEP2_IDX]]864; CHECK-NEXT: [[TMP2:%.*]] = sub i64 0, [[GEP3_IDX1]]865; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[TMP1]], [[TMP2]]866; CHECK-NEXT: ret i1 [[CMP]]867;868 %gep1 = getelementptr i32, ptr %base, i64 %idx1869 call void @use(ptr %gep1)870 %gep2 = getelementptr i32, ptr %gep1, i64 %idx2871 call void @use(ptr %gep2)872 %gep3 = getelementptr i32, ptr %gep2, i64 %idx3873 call void @use(ptr %gep3)874 %cmp = icmp eq ptr %gep3, %base875 ret i1 %cmp876}877 878define i1 @gep_multiple_multi_use_below_limit_extra_one_use_gep1(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4) {879; CHECK-LABEL: @gep_multiple_multi_use_below_limit_extra_one_use_gep1(880; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl i64 [[IDX1:%.*]], 2881; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[BASE:%.*]], i64 [[GEP1_IDX]]882; CHECK-NEXT: call void @use(ptr [[GEP1]])883; CHECK-NEXT: [[GEP2_IDX:%.*]] = shl i64 [[IDX2:%.*]], 2884; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr [[GEP1]], i64 [[GEP2_IDX]]885; CHECK-NEXT: call void @use(ptr [[GEP2]])886; CHECK-NEXT: [[GEP3_IDX:%.*]] = shl i64 [[IDX3:%.*]], 2887; CHECK-NEXT: [[GEP3:%.*]] = getelementptr i8, ptr [[GEP2]], i64 [[GEP3_IDX]]888; CHECK-NEXT: call void @use(ptr [[GEP3]])889; CHECK-NEXT: [[GEP4_IDX_NEG:%.*]] = mul i64 [[IDX4:%.*]], -4890; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[GEP1_IDX]], [[GEP2_IDX]]891; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], [[GEP3_IDX]]892; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[TMP2]], [[GEP4_IDX_NEG]]893; CHECK-NEXT: ret i1 [[CMP]]894;895 %gep1 = getelementptr i32, ptr %base, i64 %idx1896 call void @use(ptr %gep1)897 %gep2 = getelementptr i32, ptr %gep1, i64 %idx2898 call void @use(ptr %gep2)899 %gep3 = getelementptr i32, ptr %gep2, i64 %idx3900 call void @use(ptr %gep3)901 %gep4 = getelementptr i32, ptr %gep3, i64 %idx4902 %cmp = icmp eq ptr %gep4, %base903 ret i1 %cmp904}905 906define i1 @gep_multiple_multi_use_below_limit_extra_one_use_gep2(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4) {907; CHECK-LABEL: @gep_multiple_multi_use_below_limit_extra_one_use_gep2(908; CHECK-NEXT: [[GEP1_IDX1:%.*]] = add i64 [[IDX1:%.*]], [[IDX2:%.*]]909; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[GEP1_IDX1]], 2910; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr [[BASE:%.*]], i64 [[TMP1]]911; CHECK-NEXT: call void @use(ptr [[GEP2]])912; CHECK-NEXT: [[GEP3_IDX:%.*]] = shl i64 [[IDX3:%.*]], 2913; CHECK-NEXT: [[GEP3:%.*]] = getelementptr i8, ptr [[GEP2]], i64 [[GEP3_IDX]]914; CHECK-NEXT: call void @use(ptr [[GEP3]])915; CHECK-NEXT: [[GEP4_IDX:%.*]] = shl i64 [[IDX4:%.*]], 2916; CHECK-NEXT: [[GEP4:%.*]] = getelementptr i8, ptr [[GEP3]], i64 [[GEP4_IDX]]917; CHECK-NEXT: call void @use(ptr [[GEP4]])918; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], [[GEP3_IDX]]919; CHECK-NEXT: [[GEP4_IDX_NEG:%.*]] = sub i64 0, [[GEP4_IDX]]920; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[TMP2]], [[GEP4_IDX_NEG]]921; CHECK-NEXT: ret i1 [[CMP]]922;923 %gep1 = getelementptr i32, ptr %base, i64 %idx1924 %gep2 = getelementptr i32, ptr %gep1, i64 %idx2925 call void @use(ptr %gep2)926 %gep3 = getelementptr i32, ptr %gep2, i64 %idx3927 call void @use(ptr %gep3)928 %gep4 = getelementptr i32, ptr %gep3, i64 %idx4929 call void @use(ptr %gep4)930 %cmp = icmp eq ptr %gep4, %base931 ret i1 %cmp932}933 934define i1 @gep_multiple_multi_above_below_limit_consts(ptr %base, i64 %idx1, i64 %idx2) {935; CHECK-LABEL: @gep_multiple_multi_above_below_limit_consts(936; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[BASE:%.*]], i64 16937; CHECK-NEXT: call void @use(ptr [[GEP1]])938; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i32, ptr [[GEP1]], i64 [[IDX1:%.*]]939; CHECK-NEXT: call void @use(ptr [[GEP2]])940; CHECK-NEXT: [[GEP3:%.*]] = getelementptr i8, ptr [[GEP2]], i64 16941; CHECK-NEXT: call void @use(ptr [[GEP3]])942; CHECK-NEXT: [[GEP4:%.*]] = getelementptr i32, ptr [[GEP3]], i64 [[IDX2:%.*]]943; CHECK-NEXT: call void @use(ptr [[GEP4]])944; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[GEP4]], [[BASE]]945; CHECK-NEXT: ret i1 [[CMP]]946;947 %gep1 = getelementptr i32, ptr %base, i64 4948 call void @use(ptr %gep1)949 %gep2 = getelementptr i32, ptr %gep1, i64 %idx1950 call void @use(ptr %gep2)951 %gep3 = getelementptr i32, ptr %gep2, i64 4952 call void @use(ptr %gep3)953 %gep4 = getelementptr i32, ptr %gep3, i64 %idx2954 call void @use(ptr %gep4)955 %cmp = icmp eq ptr %gep4, %base956 ret i1 %cmp957}958 959define i1 @gep_multiple_multi_use_above_limit(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4) {960; CHECK-LABEL: @gep_multiple_multi_use_above_limit(961; CHECK-NEXT: [[GEP4:%.*]] = getelementptr i32, ptr [[BASE:%.*]], i64 [[IDX1:%.*]]962; CHECK-NEXT: call void @use(ptr [[GEP4]])963; CHECK-NEXT: [[GEP3:%.*]] = getelementptr i32, ptr [[GEP4]], i64 [[IDX2:%.*]]964; CHECK-NEXT: call void @use(ptr [[GEP3]])965; CHECK-NEXT: [[GEP5:%.*]] = getelementptr i32, ptr [[GEP3]], i64 [[IDX3:%.*]]966; CHECK-NEXT: call void @use(ptr [[GEP5]])967; CHECK-NEXT: [[GEP6:%.*]] = getelementptr i32, ptr [[GEP5]], i64 [[IDX4:%.*]]968; CHECK-NEXT: call void @use(ptr [[GEP6]])969; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[GEP6]], [[BASE]]970; CHECK-NEXT: ret i1 [[CMP]]971;972 %gep1 = getelementptr i32, ptr %base, i64 %idx1973 call void @use(ptr %gep1)974 %gep2 = getelementptr i32, ptr %gep1, i64 %idx2975 call void @use(ptr %gep2)976 %gep3 = getelementptr i32, ptr %gep2, i64 %idx3977 call void @use(ptr %gep3)978 %gep4 = getelementptr i32, ptr %gep3, i64 %idx4979 call void @use(ptr %gep4)980 %cmp = icmp eq ptr %gep4, %base981 ret i1 %cmp982}983 984define i1 @gep_gep_multiple_eq(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4) {985; CHECK-LABEL: @gep_gep_multiple_eq(986; CHECK-NEXT: [[GEP1_IDX1:%.*]] = add i64 [[IDX1:%.*]], [[IDX2:%.*]]987; CHECK-NEXT: [[GEP3_IDX2:%.*]] = add i64 [[IDX3:%.*]], [[IDX4:%.*]]988; CHECK-NEXT: [[CMP_UNSHIFTED:%.*]] = xor i64 [[GEP1_IDX1]], [[GEP3_IDX2]]989; CHECK-NEXT: [[CMP_MASK:%.*]] = and i64 [[CMP_UNSHIFTED]], 4611686018427387903990; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[CMP_MASK]], 0991; CHECK-NEXT: ret i1 [[CMP]]992;993 %gep1 = getelementptr i32, ptr %base, i64 %idx1994 %gep2 = getelementptr i32, ptr %gep1, i64 %idx2995 %gep3 = getelementptr i32, ptr %base, i64 %idx3996 %gep4 = getelementptr i32, ptr %gep3, i64 %idx4997 %cmp = icmp eq ptr %gep2, %gep4998 ret i1 %cmp999}1000 1001define i1 @gep_gep_multiple_eq_nuw(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4) {1002; CHECK-LABEL: @gep_gep_multiple_eq_nuw(1003; CHECK-NEXT: [[GEP1_IDX1:%.*]] = add i64 [[IDX1:%.*]], [[IDX2:%.*]]1004; CHECK-NEXT: [[GEP3_IDX2:%.*]] = add i64 [[IDX3:%.*]], [[IDX4:%.*]]1005; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[GEP1_IDX1]], [[GEP3_IDX2]]1006; CHECK-NEXT: ret i1 [[CMP]]1007;1008 %gep1 = getelementptr nuw i32, ptr %base, i64 %idx11009 %gep2 = getelementptr nuw i32, ptr %gep1, i64 %idx21010 %gep3 = getelementptr nuw i32, ptr %base, i64 %idx31011 %gep4 = getelementptr nuw i32, ptr %gep3, i64 %idx41012 %cmp = icmp eq ptr %gep2, %gep41013 ret i1 %cmp1014}1015 1016define i1 @gep_gep_multiple_eq_nuw_different_scales(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4) {1017; CHECK-LABEL: @gep_gep_multiple_eq_nuw_different_scales(1018; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw i64 [[IDX1:%.*]], 21019; CHECK-NEXT: [[GEP2_IDX:%.*]] = shl nuw i64 [[IDX2:%.*]], 31020; CHECK-NEXT: [[TMP1:%.*]] = add nuw i64 [[GEP1_IDX]], [[GEP2_IDX]]1021; CHECK-NEXT: [[GEP3_IDX:%.*]] = shl nuw i64 [[IDX3:%.*]], 21022; CHECK-NEXT: [[GEP4_IDX:%.*]] = shl nuw i64 [[IDX4:%.*]], 31023; CHECK-NEXT: [[TMP2:%.*]] = add nuw i64 [[GEP3_IDX]], [[GEP4_IDX]]1024; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[TMP1]], [[TMP2]]1025; CHECK-NEXT: ret i1 [[CMP]]1026;1027 %gep1 = getelementptr nuw i32, ptr %base, i64 %idx11028 %gep2 = getelementptr nuw i64, ptr %gep1, i64 %idx21029 %gep3 = getelementptr nuw i32, ptr %base, i64 %idx31030 %gep4 = getelementptr nuw i64, ptr %gep3, i64 %idx41031 %cmp = icmp eq ptr %gep2, %gep41032 ret i1 %cmp1033}1034 1035define i1 @gep_gep_multiple_eq_partial_nuw_different_scales(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4) {1036; CHECK-LABEL: @gep_gep_multiple_eq_partial_nuw_different_scales(1037; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw i64 [[IDX1:%.*]], 21038; CHECK-NEXT: [[GEP2_IDX:%.*]] = shl nuw i64 [[IDX2:%.*]], 31039; CHECK-NEXT: [[TMP1:%.*]] = add nuw i64 [[GEP1_IDX]], [[GEP2_IDX]]1040; CHECK-NEXT: [[GEP3_IDX:%.*]] = shl nuw i64 [[IDX3:%.*]], 21041; CHECK-NEXT: [[GEP4_IDX:%.*]] = shl i64 [[IDX4:%.*]], 31042; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[GEP3_IDX]], [[GEP4_IDX]]1043; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[TMP1]], [[TMP2]]1044; CHECK-NEXT: ret i1 [[CMP]]1045;1046 %gep1 = getelementptr nuw i32, ptr %base, i64 %idx11047 %gep2 = getelementptr nuw i64, ptr %gep1, i64 %idx21048 %gep3 = getelementptr nuw i32, ptr %base, i64 %idx31049 %gep4 = getelementptr i64, ptr %gep3, i64 %idx41050 %cmp = icmp eq ptr %gep2, %gep41051 ret i1 %cmp1052}1053 1054define i1 @gep_gep_multiple_eq_partial_inbounds_different_scales(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4) {1055; CHECK-LABEL: @gep_gep_multiple_eq_partial_inbounds_different_scales(1056; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[IDX1:%.*]], 21057; CHECK-NEXT: [[GEP2_IDX:%.*]] = shl nsw i64 [[IDX2:%.*]], 31058; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[GEP1_IDX]], [[GEP2_IDX]]1059; CHECK-NEXT: [[GEP3_IDX:%.*]] = shl nsw i64 [[IDX3:%.*]], 21060; CHECK-NEXT: [[GEP4_IDX:%.*]] = shl i64 [[IDX4:%.*]], 31061; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[GEP3_IDX]], [[GEP4_IDX]]1062; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[TMP1]], [[TMP2]]1063; CHECK-NEXT: ret i1 [[CMP]]1064;1065 %gep1 = getelementptr inbounds i32, ptr %base, i64 %idx11066 %gep2 = getelementptr inbounds i64, ptr %gep1, i64 %idx21067 %gep3 = getelementptr inbounds i32, ptr %base, i64 %idx31068 %gep4 = getelementptr i64, ptr %gep3, i64 %idx41069 %cmp = icmp eq ptr %gep2, %gep41070 ret i1 %cmp1071}1072 1073define i1 @gep_gep_multiple_ult_nuw(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4) {1074; CHECK-LABEL: @gep_gep_multiple_ult_nuw(1075; CHECK-NEXT: [[GEP1_IDX1:%.*]] = add i64 [[IDX1:%.*]], [[IDX2:%.*]]1076; CHECK-NEXT: [[GEP3_IDX2:%.*]] = add i64 [[IDX3:%.*]], [[IDX4:%.*]]1077; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[GEP1_IDX1]], [[GEP3_IDX2]]1078; CHECK-NEXT: ret i1 [[CMP]]1079;1080 %gep1 = getelementptr nuw i32, ptr %base, i64 %idx11081 %gep2 = getelementptr nuw i32, ptr %gep1, i64 %idx21082 %gep3 = getelementptr nuw i32, ptr %base, i64 %idx31083 %gep4 = getelementptr nuw i32, ptr %gep3, i64 %idx41084 %cmp = icmp ult ptr %gep2, %gep41085 ret i1 %cmp1086}1087 1088define i1 @gep_gep_multiple_ult_missing_nuw(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4) {1089; CHECK-LABEL: @gep_gep_multiple_ult_missing_nuw(1090; CHECK-NEXT: [[GEP1:%.*]] = getelementptr nuw i32, ptr [[BASE:%.*]], i64 [[IDX1:%.*]]1091; CHECK-NEXT: [[GEP2:%.*]] = getelementptr nuw i32, ptr [[GEP1]], i64 [[IDX2:%.*]]1092; CHECK-NEXT: [[GEP3:%.*]] = getelementptr nuw i32, ptr [[BASE]], i64 [[IDX3:%.*]]1093; CHECK-NEXT: [[GEP4:%.*]] = getelementptr i32, ptr [[GEP3]], i64 [[IDX4:%.*]]1094; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[GEP2]], [[GEP4]]1095; CHECK-NEXT: ret i1 [[CMP]]1096;1097 %gep1 = getelementptr nuw i32, ptr %base, i64 %idx11098 %gep2 = getelementptr nuw i32, ptr %gep1, i64 %idx21099 %gep3 = getelementptr nuw i32, ptr %base, i64 %idx31100 %gep4 = getelementptr i32, ptr %gep3, i64 %idx41101 %cmp = icmp ult ptr %gep2, %gep41102 ret i1 %cmp1103}1104 1105define i1 @gep_gep_multiple_ult_nuw_multi_use(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4) {1106; CHECK-LABEL: @gep_gep_multiple_ult_nuw_multi_use(1107; CHECK-NEXT: [[IDX3:%.*]] = add i64 [[IDX1:%.*]], [[IDX2:%.*]]1108; CHECK-NEXT: [[GEP3_IDX:%.*]] = shl nuw i64 [[IDX3]], 21109; CHECK-NEXT: [[GEP3:%.*]] = getelementptr nuw i8, ptr [[BASE:%.*]], i64 [[GEP3_IDX]]1110; CHECK-NEXT: [[IDX4:%.*]] = add i64 [[IDX5:%.*]], [[IDX6:%.*]]1111; CHECK-NEXT: [[GEP4_IDX:%.*]] = shl nuw i64 [[IDX4]], 21112; CHECK-NEXT: [[GEP5:%.*]] = getelementptr nuw i8, ptr [[BASE]], i64 [[GEP4_IDX]]1113; CHECK-NEXT: call void @use(ptr [[GEP3]])1114; CHECK-NEXT: call void @use(ptr [[GEP5]])1115; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[GEP3_IDX]], [[GEP4_IDX]]1116; CHECK-NEXT: ret i1 [[CMP]]1117;1118 %gep1 = getelementptr nuw i32, ptr %base, i64 %idx11119 %gep2 = getelementptr nuw i32, ptr %gep1, i64 %idx21120 %gep3 = getelementptr nuw i32, ptr %base, i64 %idx31121 %gep4 = getelementptr nuw i32, ptr %gep3, i64 %idx41122 call void @use(ptr %gep2)1123 call void @use(ptr %gep4)1124 %cmp = icmp ult ptr %gep2, %gep41125 ret i1 %cmp1126}1127