brintos

brintos / llvm-project-archived public Read only

0
0
Text · 20.3 KiB · 08bb40e Raw
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