352 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 52; RUN: opt -passes='loop(simple-loop-unswitch<nontrivial>),verify<loops>' -simple-loop-unswitch-guards -S < %s | FileCheck %s3; RUN: opt -passes='simple-loop-unswitch<nontrivial>' -simple-loop-unswitch-guards -S < %s | FileCheck %s4; RUN: opt -passes='loop-mssa(simple-loop-unswitch<nontrivial>),verify<loops>' -simple-loop-unswitch-guards -verify-memoryssa -verify-loop-info -S < %s | FileCheck %s5 6declare void @llvm.experimental.guard(i1, ...)7 8define void @test_simple_case(i1 %cond, i32 %N) !prof !0 {9; CHECK-LABEL: define void @test_simple_case(10; CHECK-SAME: i1 [[COND:%.*]], i32 [[N:%.*]]) !prof [[PROF0:![0-9]+]] {11; CHECK-NEXT: [[ENTRY:.*:]]12; CHECK-NEXT: br i1 [[COND]], label %[[ENTRY_SPLIT_US:.*]], label %[[ENTRY_SPLIT:.*]], !prof [[PROF1:![0-9]+]]13; CHECK: [[ENTRY_SPLIT_US]]:14; CHECK-NEXT: br label %[[LOOP_US:.*]]15; CHECK: [[LOOP_US]]:16; CHECK-NEXT: [[IV_US:%.*]] = phi i32 [ 0, %[[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], %[[GUARDED_US:.*]] ]17; CHECK-NEXT: br label %[[GUARDED_US]]18; CHECK: [[GUARDED_US]]:19; CHECK-NEXT: [[IV_NEXT_US]] = add i32 [[IV_US]], 120; CHECK-NEXT: [[LOOP_COND_US:%.*]] = icmp slt i32 [[IV_NEXT_US]], [[N]]21; CHECK-NEXT: br i1 [[LOOP_COND_US]], label %[[LOOP_US]], label %[[EXIT_SPLIT_US:.*]]22; CHECK: [[EXIT_SPLIT_US]]:23; CHECK-NEXT: br label %[[EXIT:.*]]24; CHECK: [[ENTRY_SPLIT]]:25; CHECK-NEXT: br label %[[LOOP:.*]]26; CHECK: [[LOOP]]:27; CHECK-NEXT: br label %[[DEOPT:.*]]28; CHECK: [[DEOPT]]:29; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]30; CHECK-NEXT: unreachable31; CHECK: [[EXIT]]:32; CHECK-NEXT: ret void33;34 35entry:36 br label %loop37 38loop:39 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]40 call void (i1, ...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]41 %iv.next = add i32 %iv, 142 %loop.cond = icmp slt i32 %iv.next, %N43 br i1 %loop.cond, label %loop, label %exit44 45exit:46 ret void47}48 49define void @test_two_guards(i1 %cond1, i1 %cond2, i32 %N) {50; CHECK-LABEL: define void @test_two_guards(51; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], i32 [[N:%.*]]) {52; CHECK-NEXT: [[ENTRY:.*:]]53; CHECK-NEXT: br i1 [[COND1]], label %[[ENTRY_SPLIT_US:.*]], label %[[ENTRY_SPLIT:.*]], !prof [[PROF1]]54; CHECK: [[ENTRY_SPLIT_US]]:55; CHECK-NEXT: br i1 [[COND2]], label %[[ENTRY_SPLIT_US_SPLIT_US:.*]], label %[[ENTRY_SPLIT_US_SPLIT:.*]], !prof [[PROF1]]56; CHECK: [[ENTRY_SPLIT_US_SPLIT_US]]:57; CHECK-NEXT: br label %[[LOOP_US_US:.*]]58; CHECK: [[LOOP_US_US]]:59; CHECK-NEXT: [[IV_US_US:%.*]] = phi i32 [ 0, %[[ENTRY_SPLIT_US_SPLIT_US]] ], [ [[IV_NEXT_US_US:%.*]], %[[GUARDED_US2:.*]] ]60; CHECK-NEXT: br label %[[GUARDED_US_US:.*]]61; CHECK: [[GUARDED_US_US]]:62; CHECK-NEXT: br label %[[GUARDED_US2]]63; CHECK: [[GUARDED_US2]]:64; CHECK-NEXT: [[IV_NEXT_US_US]] = add i32 [[IV_US_US]], 165; CHECK-NEXT: [[LOOP_COND_US_US:%.*]] = icmp slt i32 [[IV_NEXT_US_US]], [[N]]66; CHECK-NEXT: br i1 [[LOOP_COND_US_US]], label %[[LOOP_US_US]], label %[[EXIT_SPLIT_US_SPLIT_US:.*]]67; CHECK: [[EXIT_SPLIT_US_SPLIT_US]]:68; CHECK-NEXT: br label %[[EXIT_SPLIT_US:.*]]69; CHECK: [[ENTRY_SPLIT_US_SPLIT]]:70; CHECK-NEXT: br label %[[LOOP_US:.*]]71; CHECK: [[LOOP_US]]:72; CHECK-NEXT: br label %[[GUARDED_US:.*]]73; CHECK: [[GUARDED_US]]:74; CHECK-NEXT: br label %[[DEOPT1:.*]]75; CHECK: [[DEOPT1]]:76; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]77; CHECK-NEXT: unreachable78; CHECK: [[EXIT_SPLIT_US]]:79; CHECK-NEXT: br label %[[EXIT:.*]]80; CHECK: [[ENTRY_SPLIT]]:81; CHECK-NEXT: br label %[[LOOP:.*]]82; CHECK: [[LOOP]]:83; CHECK-NEXT: br label %[[DEOPT:.*]]84; CHECK: [[DEOPT]]:85; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]86; CHECK-NEXT: unreachable87; CHECK: [[EXIT]]:88; CHECK-NEXT: ret void89;90 91entry:92 br label %loop93 94loop:95 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]96 call void (i1, ...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ]97 call void (i1, ...) @llvm.experimental.guard(i1 %cond2) [ "deopt"() ]98 %iv.next = add i32 %iv, 199 %loop.cond = icmp slt i32 %iv.next, %N100 br i1 %loop.cond, label %loop, label %exit101 102exit:103 ret void104}105 106define void @test_conditional_guards(i1 %cond, i32 %N) {107; CHECK-LABEL: define void @test_conditional_guards(108; CHECK-SAME: i1 [[COND:%.*]], i32 [[N:%.*]]) {109; CHECK-NEXT: [[ENTRY:.*:]]110; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]111; CHECK-NEXT: br i1 [[COND_FR]], label %[[ENTRY_SPLIT_US:.*]], label %[[ENTRY_SPLIT:.*]], !prof [[PROF1]]112; CHECK: [[ENTRY_SPLIT_US]]:113; CHECK-NEXT: br label %[[LOOP_US:.*]]114; CHECK: [[LOOP_US]]:115; CHECK-NEXT: [[IV_US:%.*]] = phi i32 [ 0, %[[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], %[[BACKEDGE_US:.*]] ]116; CHECK-NEXT: [[CONDITION_US:%.*]] = icmp eq i32 [[IV_US]], 123117; CHECK-NEXT: br i1 [[CONDITION_US]], label %[[GUARD_US:.*]], label %[[BACKEDGE_US]]118; CHECK: [[GUARD_US]]:119; CHECK-NEXT: br label %[[GUARDED_US:.*]]120; CHECK: [[BACKEDGE_US]]:121; CHECK-NEXT: [[IV_NEXT_US]] = add i32 [[IV_US]], 1122; CHECK-NEXT: [[LOOP_COND_US:%.*]] = icmp slt i32 [[IV_NEXT_US]], [[N]]123; CHECK-NEXT: br i1 [[LOOP_COND_US]], label %[[LOOP_US]], label %[[EXIT_SPLIT_US:.*]]124; CHECK: [[GUARDED_US]]:125; CHECK-NEXT: br label %[[BACKEDGE_US]]126; CHECK: [[EXIT_SPLIT_US]]:127; CHECK-NEXT: br label %[[EXIT:.*]]128; CHECK: [[ENTRY_SPLIT]]:129; CHECK-NEXT: br label %[[LOOP:.*]]130; CHECK: [[LOOP]]:131; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], %[[BACKEDGE:.*]] ]132; CHECK-NEXT: [[CONDITION:%.*]] = icmp eq i32 [[IV]], 123133; CHECK-NEXT: br i1 [[CONDITION]], label %[[GUARD:.*]], label %[[BACKEDGE]]134; CHECK: [[GUARD]]:135; CHECK-NEXT: br label %[[DEOPT:.*]]136; CHECK: [[DEOPT]]:137; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]138; CHECK-NEXT: unreachable139; CHECK: [[BACKEDGE]]:140; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1141; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N]]142; CHECK-NEXT: br i1 [[LOOP_COND]], label %[[LOOP]], label %[[EXIT_SPLIT:.*]]143; CHECK: [[EXIT_SPLIT]]:144; CHECK-NEXT: br label %[[EXIT]]145; CHECK: [[EXIT]]:146; CHECK-NEXT: ret void147;148 149entry:150 br label %loop151 152loop:153 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]154 %condition = icmp eq i32 %iv, 123155 br i1 %condition, label %guard, label %backedge156 157guard:158 call void (i1, ...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]159 br label %backedge160 161backedge:162 %iv.next = add i32 %iv, 1163 %loop.cond = icmp slt i32 %iv.next, %N164 br i1 %loop.cond, label %loop, label %exit165 166exit:167 ret void168}169 170define void @test_nested_loop(i1 %cond, i32 %N, i1 %arg) {171; CHECK-LABEL: define void @test_nested_loop(172; CHECK-SAME: i1 [[COND:%.*]], i32 [[N:%.*]], i1 [[ARG:%.*]]) {173; CHECK-NEXT: [[ENTRY:.*:]]174; CHECK-NEXT: br i1 [[COND]], label %[[ENTRY_SPLIT:.*]], label %[[OUTER_LOOP_SPLIT:.*]], !prof [[PROF1]]175; CHECK: [[ENTRY_SPLIT]]:176; CHECK-NEXT: br i1 [[ARG]], label %[[ENTRY_SPLIT_SPLIT_US:.*]], label %[[ENTRY_SPLIT_SPLIT:.*]]177; CHECK: [[ENTRY_SPLIT_SPLIT_US]]:178; CHECK-NEXT: br label %[[OUTER_LOOP_US:.*]]179; CHECK: [[OUTER_LOOP_US]]:180; CHECK-NEXT: br label %[[OUTER_LOOP_SPLIT_US_US:.*]]181; CHECK: [[OUTER_BACKEDGE_US:.*]]:182; CHECK-NEXT: br label %[[OUTER_LOOP_US]]183; CHECK: [[OUTER_LOOP_SPLIT_US_US]]:184; CHECK-NEXT: br label %[[LOOP_US_US:.*]]185; CHECK: [[LOOP_US_US]]:186; CHECK-NEXT: [[IV_US_US:%.*]] = phi i32 [ 0, %[[OUTER_LOOP_SPLIT_US_US]] ], [ [[IV_NEXT_US_US:%.*]], %[[GUARDED_US_US:.*]] ]187; CHECK-NEXT: br label %[[GUARDED_US_US]]188; CHECK: [[GUARDED_US_US]]:189; CHECK-NEXT: [[IV_NEXT_US_US]] = add i32 [[IV_US_US]], 1190; CHECK-NEXT: [[LOOP_COND_US_US:%.*]] = icmp slt i32 [[IV_NEXT_US_US]], [[N]]191; CHECK-NEXT: br i1 [[LOOP_COND_US_US]], label %[[LOOP_US_US]], label %[[OUTER_BACKEDGE_SPLIT_US_US:.*]]192; CHECK: [[OUTER_BACKEDGE_SPLIT_US_US]]:193; CHECK-NEXT: br label %[[OUTER_BACKEDGE_US]]194; CHECK: [[ENTRY_SPLIT_SPLIT]]:195; CHECK-NEXT: br label %[[OUTER_LOOP:.*]]196; CHECK: [[OUTER_LOOP]]:197; CHECK-NEXT: br label %[[OUTER_LOOP_SPLIT_US:.*]]198; CHECK: [[OUTER_LOOP_SPLIT_US]]:199; CHECK-NEXT: br label %[[LOOP_US:.*]]200; CHECK: [[LOOP_US]]:201; CHECK-NEXT: [[IV_US:%.*]] = phi i32 [ 0, %[[OUTER_LOOP_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], %[[GUARDED_US:.*]] ]202; CHECK-NEXT: br label %[[GUARDED_US]]203; CHECK: [[GUARDED_US]]:204; CHECK-NEXT: [[IV_NEXT_US]] = add i32 [[IV_US]], 1205; CHECK-NEXT: [[LOOP_COND_US:%.*]] = icmp slt i32 [[IV_NEXT_US]], [[N]]206; CHECK-NEXT: br i1 [[LOOP_COND_US]], label %[[LOOP_US]], label %[[OUTER_BACKEDGE_SPLIT_US:.*]]207; CHECK: [[OUTER_BACKEDGE_SPLIT_US]]:208; CHECK-NEXT: br label %[[OUTER_BACKEDGE:.*]]209; CHECK: [[OUTER_LOOP_SPLIT]]:210; CHECK-NEXT: br label %[[LOOP:.*]]211; CHECK: [[LOOP]]:212; CHECK-NEXT: br label %[[DEOPT:.*]]213; CHECK: [[DEOPT]]:214; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]215; CHECK-NEXT: unreachable216; CHECK: [[OUTER_BACKEDGE]]:217; CHECK-NEXT: br label %[[EXIT:.*]]218; CHECK: [[EXIT]]:219; CHECK-NEXT: ret void220;221 222entry:223 br label %outer_loop224 225outer_loop:226 br label %loop227 228loop:229 %iv = phi i32 [ 0, %outer_loop ], [ %iv.next, %loop ]230 call void (i1, ...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]231 %iv.next = add i32 %iv, 1232 %loop.cond = icmp slt i32 %iv.next, %N233 br i1 %loop.cond, label %loop, label %outer_backedge234 235outer_backedge:236 br i1 %arg, label %outer_loop, label %exit237 238exit:239 ret void240}241 242define void @test_sibling_loops(i1 %cond1, i1 %cond2, i32 %N) {243; CHECK-LABEL: define void @test_sibling_loops(244; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], i32 [[N:%.*]]) {245; CHECK-NEXT: [[ENTRY:.*:]]246; CHECK-NEXT: br i1 [[COND1]], label %[[ENTRY_SPLIT_US:.*]], label %[[ENTRY_SPLIT:.*]], !prof [[PROF1]]247; CHECK: [[ENTRY_SPLIT_US]]:248; CHECK-NEXT: br label %[[LOOP1_US:.*]]249; CHECK: [[LOOP1_US]]:250; CHECK-NEXT: [[IV1_US:%.*]] = phi i32 [ 0, %[[ENTRY_SPLIT_US]] ], [ [[IV1_NEXT_US:%.*]], %[[GUARDED_US:.*]] ]251; CHECK-NEXT: br label %[[GUARDED_US]]252; CHECK: [[GUARDED_US]]:253; CHECK-NEXT: [[IV1_NEXT_US]] = add i32 [[IV1_US]], 1254; CHECK-NEXT: [[LOOP1_COND_US:%.*]] = icmp slt i32 [[IV1_NEXT_US]], [[N]]255; CHECK-NEXT: br i1 [[LOOP1_COND_US]], label %[[LOOP1_US]], label %[[BETWEEN_SPLIT_US:.*]]256; CHECK: [[BETWEEN_SPLIT_US]]:257; CHECK-NEXT: br label %[[BETWEEN:.*]]258; CHECK: [[ENTRY_SPLIT]]:259; CHECK-NEXT: br label %[[LOOP1:.*]]260; CHECK: [[LOOP1]]:261; CHECK-NEXT: br label %[[DEOPT:.*]]262; CHECK: [[DEOPT]]:263; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]264; CHECK-NEXT: unreachable265; CHECK: [[BETWEEN]]:266; CHECK-NEXT: br i1 [[COND2]], label %[[BETWEEN_SPLIT_US2:.*]], label %[[BETWEEN_SPLIT:.*]], !prof [[PROF1]]267; CHECK: [[BETWEEN_SPLIT_US2]]:268; CHECK-NEXT: br label %[[LOOP2_US:.*]]269; CHECK: [[LOOP2_US]]:270; CHECK-NEXT: [[IV2_US:%.*]] = phi i32 [ 0, %[[BETWEEN_SPLIT_US2]] ], [ [[IV2_NEXT_US:%.*]], %[[GUARDED_US3:.*]] ]271; CHECK-NEXT: br label %[[GUARDED_US3]]272; CHECK: [[GUARDED_US3]]:273; CHECK-NEXT: [[IV2_NEXT_US]] = add i32 [[IV2_US]], 1274; CHECK-NEXT: [[LOOP2_COND_US:%.*]] = icmp slt i32 [[IV2_NEXT_US]], [[N]]275; CHECK-NEXT: br i1 [[LOOP2_COND_US]], label %[[LOOP2_US]], label %[[EXIT_SPLIT_US:.*]]276; CHECK: [[EXIT_SPLIT_US]]:277; CHECK-NEXT: br label %[[EXIT:.*]]278; CHECK: [[BETWEEN_SPLIT]]:279; CHECK-NEXT: br label %[[LOOP2:.*]]280; CHECK: [[LOOP2]]:281; CHECK-NEXT: br label %[[DEOPT1:.*]]282; CHECK: [[DEOPT1]]:283; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]284; CHECK-NEXT: unreachable285; CHECK: [[EXIT]]:286; CHECK-NEXT: ret void287;288 289entry:290 br label %loop1291 292loop1:293 %iv1 = phi i32 [ 0, %entry ], [ %iv1.next, %loop1 ]294 call void (i1, ...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ]295 %iv1.next = add i32 %iv1, 1296 %loop1.cond = icmp slt i32 %iv1.next, %N297 br i1 %loop1.cond, label %loop1, label %between298 299between:300 br label %loop2301 302loop2:303 %iv2 = phi i32 [ 0, %between ], [ %iv2.next, %loop2 ]304 call void (i1, ...) @llvm.experimental.guard(i1 %cond2) [ "deopt"() ]305 %iv2.next = add i32 %iv2, 1306 %loop2.cond = icmp slt i32 %iv2.next, %N307 br i1 %loop2.cond, label %loop2, label %exit308 309exit:310 ret void311}312 313; Check that we don't do anything because of cleanuppad.314define void @test_cleanuppad(i1 %cond, i32 %N) personality ptr @__CxxFrameHandler3 {315; CHECK-LABEL: define void @test_cleanuppad(316; CHECK-SAME: i1 [[COND:%.*]], i32 [[N:%.*]]) personality ptr @__CxxFrameHandler3 {317; CHECK-NEXT: [[ENTRY:.*]]:318; CHECK-NEXT: br label %[[LOOP:.*]]319; CHECK: [[LOOP]]:320; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]321; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND]]) [ "deopt"() ]322; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1323; CHECK-NEXT: invoke void @may_throw(i32 [[IV]])324; CHECK-NEXT: to label %[[LOOP]] unwind label %[[EXIT:.*]]325; CHECK: [[EXIT]]:326; CHECK-NEXT: [[CP:%.*]] = cleanuppad within none []327; CHECK-NEXT: cleanupret from [[CP]] unwind to caller328;329entry:330 br label %loop331 332loop:333 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]334 call void (i1, ...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]335 %iv.next = add i32 %iv, 1336 invoke void @may_throw(i32 %iv) to label %loop unwind label %exit337 338exit:339 %cp = cleanuppad within none []340 cleanupret from %cp unwind to caller341 342}343 344declare void @may_throw(i32 %i)345declare i32 @__CxxFrameHandler3(...)346 347!0 = !{!"function_entry_count", i32 10}348;.349; CHECK: [[PROF0]] = !{!"function_entry_count", i32 10}350; CHECK: [[PROF1]] = !{!"branch_weights", i32 1048575, i32 1}351;.352