427 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes='instcombine<no-verify-fixpoint>' -S < %s | FileCheck %s3 4; In many of these tests nuw can be inferred on the sunk GEP in the exit5; block. However, the condition is only converted into the necessary form6; after it has been sunk and revisited already.7 8target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:64"9 10define ptr@test1(ptr %A, i32 %Offset) {11; CHECK-LABEL: @test1(12; CHECK-NEXT: entry:13; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 214; CHECK-NEXT: br label [[BB:%.*]]15; CHECK: bb:16; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]17; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 418; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 40019; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]20; CHECK: bb2:21; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i32 [[RHS_IDX]]22; CHECK-NEXT: ret ptr [[RHS_PTR]]23;24entry:25 %tmp = getelementptr inbounds i32, ptr %A, i32 %Offset26 br label %bb27 28bb:29 %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]30 %LHS = getelementptr inbounds i32, ptr %A, i32 10031 %RHS.next = getelementptr inbounds i32, ptr %RHS, i64 132 %cond = icmp ult ptr %LHS, %RHS33 br i1 %cond, label %bb2, label %bb34 35bb2:36 ret ptr %RHS37}38 39define ptr @test1_nuw(ptr %A, i32 %Offset) {40; CHECK-LABEL: @test1_nuw(41; CHECK-NEXT: entry:42; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nuw nsw i32 [[OFFSET:%.*]], 243; CHECK-NEXT: br label [[BB:%.*]]44; CHECK: bb:45; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]46; CHECK-NEXT: [[RHS_ADD]] = add nuw nsw i32 [[RHS_IDX]], 447; CHECK-NEXT: [[COND:%.*]] = icmp samesign ugt i32 [[RHS_IDX]], 40048; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]49; CHECK: bb2:50; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds nuw i8, ptr [[A:%.*]], i32 [[RHS_IDX]]51; CHECK-NEXT: ret ptr [[RHS_PTR]]52;53entry:54 %tmp = getelementptr inbounds nuw i32, ptr %A, i32 %Offset55 br label %bb56 57bb:58 %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]59 %LHS = getelementptr inbounds nuw i32, ptr %A, i32 10060 %RHS.next = getelementptr inbounds nuw i32, ptr %RHS, i64 161 %cond = icmp ult ptr %LHS, %RHS62 br i1 %cond, label %bb2, label %bb63 64bb2:65 ret ptr %RHS66}67 68define ptr @test1_not_all_nuw(ptr %A, i32 %Offset) {69; CHECK-LABEL: @test1_not_all_nuw(70; CHECK-NEXT: entry:71; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 272; CHECK-NEXT: br label [[BB:%.*]]73; CHECK: bb:74; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]75; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 476; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 40077; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]78; CHECK: bb2:79; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i32 [[RHS_IDX]]80; CHECK-NEXT: ret ptr [[RHS_PTR]]81;82entry:83 %tmp = getelementptr inbounds i32, ptr %A, i32 %Offset84 br label %bb85 86bb:87 %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]88 %LHS = getelementptr inbounds nuw i32, ptr %A, i32 10089 %RHS.next = getelementptr inbounds nuw i32, ptr %RHS, i64 190 %cond = icmp ult ptr %LHS, %RHS91 br i1 %cond, label %bb2, label %bb92 93bb2:94 ret ptr %RHS95}96 97define ptr@test2(i32 %A, i32 %Offset) {98; CHECK-LABEL: @test2(99; CHECK-NEXT: entry:100; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2101; CHECK-NEXT: br label [[BB:%.*]]102; CHECK: bb:103; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]104; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4105; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400106; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]107; CHECK: bb2:108; CHECK-NEXT: [[A_PTR:%.*]] = inttoptr i32 [[A:%.*]] to ptr109; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A_PTR]], i32 [[RHS_IDX]]110; CHECK-NEXT: ret ptr [[RHS_PTR]]111;112entry:113 %A.ptr = inttoptr i32 %A to ptr114 %tmp = getelementptr inbounds i32, ptr %A.ptr, i32 %Offset115 br label %bb116 117bb:118 %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]119 %LHS = getelementptr inbounds i32, ptr %A.ptr, i32 100120 %RHS.next = getelementptr inbounds i32, ptr %RHS, i64 1121 %cmp0 = ptrtoint ptr %LHS to i32122 %cmp1 = ptrtoint ptr %RHS to i32123 %cond = icmp ult i32 %cmp0, %cmp1124 br i1 %cond, label %bb2, label %bb125 126bb2:127 ret ptr %RHS128}129 130; Perform the transformation only if we know that the GEPs used are inbounds.131define ptr @test3_no_inbounds1(ptr %A, i32 %Offset) {132; CHECK-LABEL: @test3_no_inbounds1(133; CHECK-NEXT: entry:134; CHECK-NEXT: [[TMP:%.*]] = getelementptr i32, ptr [[A:%.*]], i32 [[OFFSET:%.*]]135; CHECK-NEXT: br label [[BB:%.*]]136; CHECK: bb:137; CHECK-NEXT: [[RHS:%.*]] = phi ptr [ [[RHS_NEXT:%.*]], [[BB]] ], [ [[TMP]], [[ENTRY:%.*]] ]138; CHECK-NEXT: [[LHS:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i32 400139; CHECK-NEXT: [[RHS_NEXT]] = getelementptr inbounds nuw i8, ptr [[RHS]], i32 4140; CHECK-NEXT: [[COND:%.*]] = icmp ult ptr [[LHS]], [[RHS]]141; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]142; CHECK: bb2:143; CHECK-NEXT: ret ptr [[RHS]]144;145entry:146 %tmp = getelementptr i32, ptr %A, i32 %Offset147 br label %bb148 149bb:150 %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]151 %LHS = getelementptr inbounds i32, ptr %A, i32 100152 %RHS.next = getelementptr inbounds i32, ptr %RHS, i64 1153 %cond = icmp ult ptr %LHS, %RHS154 br i1 %cond, label %bb2, label %bb155 156bb2:157 ret ptr %RHS158}159 160define ptr @test3_no_inbounds2(ptr %A, i32 %Offset) {161; CHECK-LABEL: @test3_no_inbounds2(162; CHECK-NEXT: entry:163; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[OFFSET:%.*]]164; CHECK-NEXT: br label [[BB:%.*]]165; CHECK: bb:166; CHECK-NEXT: [[RHS:%.*]] = phi ptr [ [[RHS_NEXT:%.*]], [[BB]] ], [ [[TMP]], [[ENTRY:%.*]] ]167; CHECK-NEXT: [[LHS:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i32 400168; CHECK-NEXT: [[RHS_NEXT]] = getelementptr i8, ptr [[RHS]], i32 4169; CHECK-NEXT: [[COND:%.*]] = icmp ult ptr [[LHS]], [[RHS]]170; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]171; CHECK: bb2:172; CHECK-NEXT: ret ptr [[RHS]]173;174entry:175 %tmp = getelementptr inbounds i32, ptr %A, i32 %Offset176 br label %bb177 178bb:179 %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]180 %LHS = getelementptr inbounds i32, ptr %A, i32 100181 %RHS.next = getelementptr i32, ptr %RHS, i64 1182 %cond = icmp ult ptr %LHS, %RHS183 br i1 %cond, label %bb2, label %bb184 185bb2:186 ret ptr %RHS187}188 189define ptr @test3_no_inbounds3(ptr %A, i32 %Offset) {190; CHECK-LABEL: @test3_no_inbounds3(191; CHECK-NEXT: entry:192; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[OFFSET:%.*]]193; CHECK-NEXT: br label [[BB:%.*]]194; CHECK: bb:195; CHECK-NEXT: [[RHS:%.*]] = phi ptr [ [[RHS_NEXT:%.*]], [[BB]] ], [ [[TMP]], [[ENTRY:%.*]] ]196; CHECK-NEXT: [[LHS:%.*]] = getelementptr i8, ptr [[A]], i32 400197; CHECK-NEXT: [[RHS_NEXT]] = getelementptr inbounds nuw i8, ptr [[RHS]], i32 4198; CHECK-NEXT: [[COND:%.*]] = icmp ult ptr [[LHS]], [[RHS]]199; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]200; CHECK: bb2:201; CHECK-NEXT: ret ptr [[RHS]]202;203entry:204 %tmp = getelementptr inbounds i32, ptr %A, i32 %Offset205 br label %bb206 207bb:208 %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]209 %LHS = getelementptr i32, ptr %A, i32 100210 %RHS.next = getelementptr inbounds i32, ptr %RHS, i64 1211 %cond = icmp ult ptr %LHS, %RHS212 br i1 %cond, label %bb2, label %bb213 214bb2:215 ret ptr %RHS216}217 218; An inttoptr that requires an extension or truncation will be opaque when determining219; the base pointer. In this case we can still perform the transformation by considering220; A.ptr as being the base pointer.221define ptr@test4(i16 %A, i32 %Offset) {222; CHECK-LABEL: @test4(223; CHECK-NEXT: entry:224; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2225; CHECK-NEXT: br label [[BB:%.*]]226; CHECK: bb:227; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]228; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4229; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400230; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]231; CHECK: bb2:232; CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[A:%.*]] to i32233; CHECK-NEXT: [[A_PTR:%.*]] = inttoptr i32 [[TMP0]] to ptr234; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A_PTR]], i32 [[RHS_IDX]]235; CHECK-NEXT: ret ptr [[RHS_PTR]]236;237entry:238 %A.ptr = inttoptr i16 %A to ptr239 %tmp = getelementptr inbounds i32, ptr %A.ptr, i32 %Offset240 br label %bb241 242bb:243 %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]244 %LHS = getelementptr inbounds i32, ptr %A.ptr, i32 100245 %RHS.next = getelementptr inbounds i32, ptr %RHS, i64 1246 %cmp0 = ptrtoint ptr %LHS to i32247 %cmp1 = ptrtoint ptr %RHS to i32248 %cond = icmp ult i32 %cmp0, %cmp1249 br i1 %cond, label %bb2, label %bb250 251bb2:252 ret ptr %RHS253}254 255declare ptr @fun_ptr()256 257define ptr@test5(i32 %Offset) personality ptr @__gxx_personality_v0 {258; CHECK-LABEL: @test5(259; CHECK-NEXT: entry:260; CHECK-NEXT: [[A:%.*]] = invoke ptr @fun_ptr()261; CHECK-NEXT: to label [[CONT:%.*]] unwind label [[LPAD:%.*]]262; CHECK: cont:263; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2264; CHECK-NEXT: br label [[BB:%.*]]265; CHECK: bb:266; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[CONT]] ]267; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4268; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400269; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]270; CHECK: bb2:271; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A]], i32 [[RHS_IDX]]272; CHECK-NEXT: ret ptr [[RHS_PTR]]273; CHECK: lpad:274; CHECK-NEXT: [[L:%.*]] = landingpad { ptr, i32 }275; CHECK-NEXT: cleanup276; CHECK-NEXT: ret ptr null277;278entry:279 %A = invoke ptr@fun_ptr() to label %cont unwind label %lpad280 281cont:282 %tmp = getelementptr inbounds i32, ptr %A, i32 %Offset283 br label %bb284 285bb:286 %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %cont ]287 %LHS = getelementptr inbounds i32, ptr %A, i32 100288 %RHS.next = getelementptr inbounds i32, ptr %RHS, i64 1289 %cond = icmp ult ptr %LHS, %RHS290 br i1 %cond, label %bb2, label %bb291 292bb2:293 ret ptr %RHS294 295lpad:296 %l = landingpad { ptr, i32 } cleanup297 ret ptr null298}299 300declare i32 @fun_i32()301 302define ptr@test6(i32 %Offset) personality ptr @__gxx_personality_v0 {303; CHECK-LABEL: @test6(304; CHECK-NEXT: entry:305; CHECK-NEXT: [[A:%.*]] = invoke i32 @fun_i32()306; CHECK-NEXT: to label [[CONT:%.*]] unwind label [[LPAD:%.*]]307; CHECK: cont:308; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2309; CHECK-NEXT: br label [[BB:%.*]]310; CHECK: bb:311; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[CONT]] ]312; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4313; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400314; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]315; CHECK: bb2:316; CHECK-NEXT: [[A_PTR:%.*]] = inttoptr i32 [[A]] to ptr317; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A_PTR]], i32 [[RHS_IDX]]318; CHECK-NEXT: ret ptr [[RHS_PTR]]319; CHECK: lpad:320; CHECK-NEXT: [[L:%.*]] = landingpad { ptr, i32 }321; CHECK-NEXT: cleanup322; CHECK-NEXT: ret ptr null323;324entry:325 %A = invoke i32 @fun_i32() to label %cont unwind label %lpad326 327cont:328 %A.ptr = inttoptr i32 %A to ptr329 %tmp = getelementptr inbounds i32, ptr %A.ptr, i32 %Offset330 br label %bb331 332bb:333 %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %cont ]334 %LHS = getelementptr inbounds i32, ptr %A.ptr, i32 100335 %RHS.next = getelementptr inbounds i32, ptr %RHS, i64 1336 %cond = icmp ult ptr %LHS, %RHS337 br i1 %cond, label %bb2, label %bb338 339bb2:340 ret ptr %RHS341 342lpad:343 %l = landingpad { ptr, i32 } cleanup344 ret ptr null345}346 347 348@pr30402 = constant i64 3349define i1 @test7() {350; CHECK-LABEL: @test7(351; CHECK-NEXT: entry:352; CHECK-NEXT: br label [[BB7:%.*]]353; CHECK: bb7:354; CHECK-NEXT: [[CMP:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ true, [[BB7]] ]355; CHECK-NEXT: br i1 [[CMP]], label [[BB10:%.*]], label [[BB7]]356; CHECK: bb10:357; CHECK-NEXT: ret i1 true358;359entry:360 br label %bb7361 362bb7: ; preds = %bb10, %entry-block363 %phi = phi ptr [ @pr30402, %entry ], [ getelementptr inbounds (i64, ptr @pr30402, i32 1), %bb7 ]364 %cmp = icmp eq ptr %phi, getelementptr inbounds (i64, ptr @pr30402, i32 1)365 br i1 %cmp, label %bb10, label %bb7366 367bb10:368 ret i1 %cmp369}370 371declare i32 @__gxx_personality_v0(...)372 373define i1 @test8(ptr %in, i64 %offset) {374; CHECK-LABEL: @test8(375; CHECK-NEXT: entry:376; CHECK-NEXT: [[LD:%.*]] = load i64, ptr [[IN:%.*]], align 8377; CHECK-NEXT: [[TMP0:%.*]] = trunc i64 [[LD]] to i32378; CHECK-NEXT: [[CASTI8:%.*]] = inttoptr i32 [[TMP0]] to ptr379; CHECK-NEXT: [[TMP1:%.*]] = trunc nsw i64 [[OFFSET:%.*]] to i32380; CHECK-NEXT: [[GEPI8:%.*]] = getelementptr inbounds i8, ptr [[CASTI8]], i32 [[TMP1]]381; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[LD]] to i32382; CHECK-NEXT: [[PTRCAST:%.*]] = inttoptr i32 [[TMP2]] to ptr383; CHECK-NEXT: [[GEPI32:%.*]] = getelementptr inbounds nuw i8, ptr [[PTRCAST]], i32 4384; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[GEPI32]], [[GEPI8]]385; CHECK-NEXT: ret i1 [[CMP]]386;387entry:388 %ld = load i64, ptr %in, align 8389 %casti8 = inttoptr i64 %ld to ptr390 %gepi8 = getelementptr inbounds i8, ptr %casti8, i64 %offset391 %ptrcast = inttoptr i64 %ld to ptr392 %gepi32 = getelementptr inbounds ptr, ptr %ptrcast, i64 1393 %cmp = icmp eq ptr %gepi32, %gepi8394 ret i1 %cmp395}396 397define void @test_zero_offset_cycle(ptr %arg) {398; CHECK-LABEL: @test_zero_offset_cycle(399; CHECK-NEXT: entry:400; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[ARG:%.*]], i32 8401; CHECK-NEXT: [[GEP_INT:%.*]] = ptrtoint ptr [[GEP]] to i32402; CHECK-NEXT: br label [[LOOP:%.*]]403; CHECK: loop:404; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[GEP_INT]], [[ENTRY:%.*]] ], [ [[GEP_INT2:%.*]], [[LOOP_CONT:%.*]] ], [ [[PHI]], [[LOOP]] ]405; CHECK-NEXT: [[PHI_PTR:%.*]] = inttoptr i32 [[PHI]] to ptr406; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[GEP]], [[PHI_PTR]]407; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[LOOP_CONT]]408; CHECK: loop.cont:409; CHECK-NEXT: [[GEP_INT2]] = ptrtoint ptr [[GEP]] to i32410; CHECK-NEXT: br label [[LOOP]]411;412entry:413 %gep = getelementptr inbounds { i64, i64 }, ptr %arg, i32 0, i32 1414 %gep.int = ptrtoint ptr %gep to i32415 br label %loop416 417loop:418 %phi = phi i32 [ %gep.int, %entry ], [ %gep.int2, %loop.cont ], [ %phi, %loop ]419 %phi.ptr = inttoptr i32 %phi to ptr420 %cmp = icmp eq ptr %gep, %phi.ptr421 br i1 %cmp, label %loop, label %loop.cont422 423loop.cont:424 %gep.int2 = ptrtoint ptr %gep to i32425 br label %loop426}427