449 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S -passes=loop-predication < %s 2>&1 | FileCheck %s3; RUN: opt -S -aa-pipeline=basic-aa -passes='require<aa>,require<scalar-evolution>,loop-mssa(loop-predication)' -verify-memoryssa < %s 2>&1 | FileCheck %s4 5declare void @llvm.experimental.guard(i1, ...)6 7@UNKNOWN = external global i18 9define i32 @neg_length_variant(ptr %array, ptr %length, i32 %n) {10; CHECK-LABEL: @neg_length_variant(11; CHECK-NEXT: entry:12; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 013; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]14; CHECK: loop.preheader:15; CHECK-NEXT: br label [[LOOP:%.*]]16; CHECK: loop:17; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]18; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]19; CHECK-NEXT: [[UNKNOWN:%.*]] = load volatile i1, ptr @UNKNOWN, align 120; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ]21; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LENGTH:%.*]], align 422; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LEN]]23; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]24; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i6425; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]26; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 427; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]28; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 129; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]30; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]31; CHECK: exit.loopexit:32; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]33; CHECK-NEXT: br label [[EXIT]]34; CHECK: exit:35; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]36; CHECK-NEXT: ret i32 [[RESULT]]37;38entry:39 %tmp5 = icmp eq i32 %n, 040 br i1 %tmp5, label %exit, label %loop.preheader41 42loop.preheader:43 br label %loop44 45loop:46 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]47 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]48 %unknown = load volatile i1, ptr @UNKNOWN49 call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ]50 %len = load i32, ptr %length, align 451 %within.bounds = icmp ult i32 %i, %len52 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]53 54 %i.i64 = zext i32 %i to i6455 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i6456 %array.i = load i32, ptr %array.i.ptr, align 457 %loop.acc.next = add i32 %loop.acc, %array.i58 59 %i.next = add nuw i32 %i, 160 %continue = icmp ult i32 %i.next, %n61 br i1 %continue, label %loop, label %exit62 63exit:64 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]65 ret i32 %result66}67 68define i32 @invariant_load_guard_limit(ptr %array, ptr %length, i32 %n) {69; CHECK-LABEL: @invariant_load_guard_limit(70; CHECK-NEXT: entry:71; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 072; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]73; CHECK: loop.preheader:74; CHECK-NEXT: br label [[LOOP:%.*]]75; CHECK: loop:76; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]77; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]78; CHECK-NEXT: [[UNKNOWN:%.*]] = load volatile i1, ptr @UNKNOWN, align 179; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ]80; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LENGTH:%.*]], align 4, !invariant.load !081; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LEN]]82; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LEN]]83; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LEN]]84; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]85; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]]86; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]87; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])88; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i6489; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]90; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 491; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]92; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 193; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]94; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]95; CHECK: exit.loopexit:96; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]97; CHECK-NEXT: br label [[EXIT]]98; CHECK: exit:99; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]100; CHECK-NEXT: ret i32 [[RESULT]]101;102entry:103 %tmp5 = icmp eq i32 %n, 0104 br i1 %tmp5, label %exit, label %loop.preheader105 106loop.preheader:107 br label %loop108 109loop:110 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]111 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]112 %unknown = load volatile i1, ptr @UNKNOWN113 call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ]114 %len = load i32, ptr %length, align 4, !invariant.load !{}115 %within.bounds = icmp ult i32 %i, %len116 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]117 118 %i.i64 = zext i32 %i to i64119 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64120 %array.i = load i32, ptr %array.i.ptr, align 4121 %loop.acc.next = add i32 %loop.acc, %array.i122 123 %i.next = add nuw i32 %i, 1124 %continue = icmp ult i32 %i.next, %n125 br i1 %continue, label %loop, label %exit126 127exit:128 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]129 ret i32 %result130}131 132; Case where we have an invariant load, but it's not loading from a loop133; invariant location.134define i32 @neg_varying_invariant_load_op(ptr %array, ptr %lengths, i32 %n) {135; CHECK-LABEL: @neg_varying_invariant_load_op(136; CHECK-NEXT: entry:137; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0138; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]139; CHECK: loop.preheader:140; CHECK-NEXT: br label [[LOOP:%.*]]141; CHECK: loop:142; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]143; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]144; CHECK-NEXT: [[UNKNOWN:%.*]] = load volatile i1, ptr @UNKNOWN, align 1145; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ]146; CHECK-NEXT: [[LENGTH_ADDR:%.*]] = getelementptr i32, ptr [[LENGTHS:%.*]], i32 [[I]]147; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LENGTH_ADDR]], align 4, !invariant.load !0148; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LEN]]149; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]150; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64151; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]152; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4153; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]154; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1155; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]156; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]157; CHECK: exit.loopexit:158; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]159; CHECK-NEXT: br label [[EXIT]]160; CHECK: exit:161; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]162; CHECK-NEXT: ret i32 [[RESULT]]163;164entry:165 %tmp5 = icmp eq i32 %n, 0166 br i1 %tmp5, label %exit, label %loop.preheader167 168loop.preheader:169 br label %loop170 171loop:172 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]173 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]174 %unknown = load volatile i1, ptr @UNKNOWN175 call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ]176 177 %length.addr = getelementptr i32, ptr %lengths, i32 %i178 %len = load i32, ptr %length.addr, align 4, !invariant.load !{}179 %within.bounds = icmp ult i32 %i, %len180 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]181 182 %i.i64 = zext i32 %i to i64183 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64184 %array.i = load i32, ptr %array.i.ptr, align 4185 %loop.acc.next = add i32 %loop.acc, %array.i186 187 %i.next = add nuw i32 %i, 1188 %continue = icmp ult i32 %i.next, %n189 br i1 %continue, label %loop, label %exit190 191exit:192 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]193 ret i32 %result194}195 196; This is a case where moving the load which provides the limit for the latch197; would be invalid, so we can't preform the tempting transform. Loading the198; latch limit may fault since we could always fail the guard.199define i32 @neg_invariant_load_latch_limit(ptr %array, ptr %length, i32 %n) {200; CHECK-LABEL: @neg_invariant_load_latch_limit(201; CHECK-NEXT: entry:202; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0203; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]204; CHECK: loop.preheader:205; CHECK-NEXT: br label [[LOOP:%.*]]206; CHECK: loop:207; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]208; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]209; CHECK-NEXT: [[UNKNOWN:%.*]] = load volatile i1, ptr @UNKNOWN, align 1210; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ]211; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[N]]212; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]213; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64214; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]215; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4216; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]217; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1218; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LENGTH:%.*]], align 4, !invariant.load !0219; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[LEN]]220; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]221; CHECK: exit.loopexit:222; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]223; CHECK-NEXT: br label [[EXIT]]224; CHECK: exit:225; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]226; CHECK-NEXT: ret i32 [[RESULT]]227;228entry:229 %tmp5 = icmp eq i32 %n, 0230 br i1 %tmp5, label %exit, label %loop.preheader231 232loop.preheader:233 br label %loop234 235loop:236 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]237 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]238 %unknown = load volatile i1, ptr @UNKNOWN239 call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ]240 %within.bounds = icmp ult i32 %i, %n241 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]242 243 %i.i64 = zext i32 %i to i64244 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64245 %array.i = load i32, ptr %array.i.ptr, align 4246 %loop.acc.next = add i32 %loop.acc, %array.i247 248 %i.next = add nuw i32 %i, 1249 %len = load i32, ptr %length, align 4, !invariant.load !{}250 %continue = icmp ult i32 %i.next, %len251 br i1 %continue, label %loop, label %exit252 253exit:254 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]255 ret i32 %result256}257 258define i32 @invariant_load_latch_limit(ptr %array,259; CHECK-LABEL: @invariant_load_latch_limit(260; CHECK-NEXT: entry:261; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0262; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]263; CHECK: loop.preheader:264; CHECK-NEXT: br label [[LOOP:%.*]]265; CHECK: loop:266; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]267; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]268; CHECK-NEXT: [[UNKNOWN:%.*]] = load volatile i1, ptr @UNKNOWN, align 1269; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ]270; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[N]]271; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]272; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64273; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]274; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4275; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]276; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1277; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LENGTH:%.*]], align 4, !invariant.load !0278; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[LEN]]279; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]280; CHECK: exit.loopexit:281; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]282; CHECK-NEXT: br label [[EXIT]]283; CHECK: exit:284; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]285; CHECK-NEXT: ret i32 [[RESULT]]286;287 ptr dereferenceable(4) %length,288 i32 %n) {289entry:290 %tmp5 = icmp eq i32 %n, 0291 br i1 %tmp5, label %exit, label %loop.preheader292 293loop.preheader:294 br label %loop295 296loop:297 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]298 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]299 %unknown = load volatile i1, ptr @UNKNOWN300 call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ]301 %within.bounds = icmp ult i32 %i, %n302 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]303 304 %i.i64 = zext i32 %i to i64305 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64306 %array.i = load i32, ptr %array.i.ptr, align 4307 %loop.acc.next = add i32 %loop.acc, %array.i308 309 %i.next = add nuw i32 %i, 1310 %len = load i32, ptr %length, align 4, !invariant.load !{}311 %continue = icmp ult i32 %i.next, %len312 br i1 %continue, label %loop, label %exit313 314exit:315 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]316 ret i32 %result317}318 319 320 321@Length = external constant i32322 323define i32 @constant_memory(ptr %array, i32 %n) {324; CHECK-LABEL: @constant_memory(325; CHECK-NEXT: entry:326; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0327; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]328; CHECK: loop.preheader:329; CHECK-NEXT: br label [[LOOP:%.*]]330; CHECK: loop:331; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]332; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]333; CHECK-NEXT: [[UNKNOWN:%.*]] = load volatile i1, ptr @UNKNOWN, align 1334; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ]335; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr @Length, align 4336; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LEN]]337; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LEN]]338; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LEN]]339; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]340; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]]341; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]342; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])343; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64344; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]345; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4346; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]347; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1348; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]349; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]350; CHECK: exit.loopexit:351; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]352; CHECK-NEXT: br label [[EXIT]]353; CHECK: exit:354; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]355; CHECK-NEXT: ret i32 [[RESULT]]356;357entry:358 %tmp5 = icmp eq i32 %n, 0359 br i1 %tmp5, label %exit, label %loop.preheader360 361loop.preheader:362 br label %loop363 364loop:365 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]366 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]367 %unknown = load volatile i1, ptr @UNKNOWN368 call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ]369 %len = load i32, ptr @Length, align 4370 %within.bounds = icmp ult i32 %i, %len371 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]372 373 %i.i64 = zext i32 %i to i64374 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64375 %array.i = load i32, ptr %array.i.ptr, align 4376 %loop.acc.next = add i32 %loop.acc, %array.i377 378 %i.next = add nuw i32 %i, 1379 %continue = icmp ult i32 %i.next, %n380 br i1 %continue, label %loop, label %exit381 382exit:383 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]384 ret i32 %result385}386 387define i32 @constant_length(ptr %array, i32 %n) {388; CHECK-LABEL: @constant_length(389; CHECK-NEXT: entry:390; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0391; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]392; CHECK: loop.preheader:393; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], 20394; CHECK-NEXT: [[TMP1:%.*]] = and i1 true, [[TMP0]]395; CHECK-NEXT: [[TMP2:%.*]] = freeze i1 [[TMP1]]396; CHECK-NEXT: br label [[LOOP:%.*]]397; CHECK: loop:398; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]399; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]400; CHECK-NEXT: [[UNKNOWN:%.*]] = load volatile i1, ptr @UNKNOWN, align 1401; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ]402; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], 20403; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]404; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]])405; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64406; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]407; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4408; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]409; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1410; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]411; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]412; CHECK: exit.loopexit:413; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]414; CHECK-NEXT: br label [[EXIT]]415; CHECK: exit:416; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]417; CHECK-NEXT: ret i32 [[RESULT]]418;419entry:420 %tmp5 = icmp eq i32 %n, 0421 br i1 %tmp5, label %exit, label %loop.preheader422 423loop.preheader:424 br label %loop425 426loop:427 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]428 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]429 %unknown = load volatile i1, ptr @UNKNOWN430 call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ]431 %within.bounds = icmp ult i32 %i, 20432 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]433 434 %i.i64 = zext i32 %i to i64435 %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64436 %array.i = load i32, ptr %array.i.ptr, align 4437 %loop.acc.next = add i32 %loop.acc, %array.i438 439 %i.next = add nuw i32 %i, 1440 %continue = icmp ult i32 %i.next, %n441 br i1 %continue, label %loop, label %exit442 443exit:444 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]445 ret i32 %result446}447 448 449