212 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 22; RUN: opt -S -passes=guard-widening < %s | FileCheck %s3 4; Function Attrs: nocallback nofree nosync willreturn5declare void @llvm.experimental.guard(i1, ...) #06 7; Hot loop, frequently entered, should widen.8define i32 @test_intrinsic_very_profitable(i32 %n, i1 %cond.1, i1 %cond.2) {9; CHECK-LABEL: define i32 @test_intrinsic_very_profitable10; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {11; CHECK-NEXT: entry:12; CHECK-NEXT: [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]13; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]14; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]15; CHECK-NEXT: [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 10016; CHECK-NEXT: br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF0:![0-9]+]]17; CHECK: loop:18; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]19; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 120; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 10021; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1:![0-9]+]]22; CHECK: exit:23; CHECK-NEXT: ret i32 024; CHECK: failed:25; CHECK-NEXT: ret i32 -126;27entry:28 call void (i1, ...) @llvm.experimental.guard(i1 %cond.1) [ "deopt"() ]29 %loop.precondition = icmp uge i32 %n, 10030 br i1 %loop.precondition, label %loop, label %failed, !prof !031 32loop: ; preds = %loop, %entry33 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]34 call void (i1, ...) @llvm.experimental.guard(i1 %cond.2) [ "deopt"() ]35 %iv.next = add nuw nsw i32 %iv, 136 %loop.cond = icmp ult i32 %iv.next, 10037 br i1 %loop.cond, label %loop, label %exit, !prof !138 39exit: ; preds = %loop40 ret i32 041 42failed: ; preds = %entry43 ret i32 -144}45 46; Even though the loop is rarely entered, it has so many iterations that the widening47; is still profitable.48define i32 @test_intrinsic_profitable(i32 %n, i1 %cond.1, i1 %cond.2) {49; CHECK-LABEL: define i32 @test_intrinsic_profitable50; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {51; CHECK-NEXT: entry:52; CHECK-NEXT: [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]53; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]54; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]55; CHECK-NEXT: [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 10056; CHECK-NEXT: br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF2:![0-9]+]]57; CHECK: loop:58; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]59; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 160; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 10061; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1]]62; CHECK: exit:63; CHECK-NEXT: ret i32 064; CHECK: failed:65; CHECK-NEXT: ret i32 -166;67entry:68 call void (i1, ...) @llvm.experimental.guard(i1 %cond.1) [ "deopt"() ]69 %loop.precondition = icmp uge i32 %n, 10070 br i1 %loop.precondition, label %loop, label %failed, !prof !271 72loop: ; preds = %loop, %entry73 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]74 call void (i1, ...) @llvm.experimental.guard(i1 %cond.2) [ "deopt"() ]75 %iv.next = add nuw nsw i32 %iv, 176 %loop.cond = icmp ult i32 %iv.next, 10077 br i1 %loop.cond, label %loop, label %exit, !prof !178 79exit: ; preds = %loop80 ret i32 081 82failed: ; preds = %entry83 ret i32 -184}85 86; Loop's hotness compensates rareness of its entrance. We still want to widen, because87; it may open up some optimization opportunities.88define i32 @test_intrinsic_neutral(i32 %n, i1 %cond.1, i1 %cond.2) {89; CHECK-LABEL: define i32 @test_intrinsic_neutral90; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {91; CHECK-NEXT: entry:92; CHECK-NEXT: [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]93; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]94; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]95; CHECK-NEXT: [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 10096; CHECK-NEXT: br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF3:![0-9]+]]97; CHECK: loop:98; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]99; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1100; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 100101; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1]]102; CHECK: exit:103; CHECK-NEXT: ret i32 0104; CHECK: failed:105; CHECK-NEXT: ret i32 -1106;107entry:108 call void (i1, ...) @llvm.experimental.guard(i1 %cond.1) [ "deopt"() ]109 %loop.precondition = icmp uge i32 %n, 100110 br i1 %loop.precondition, label %loop, label %failed, !prof !3111 112loop: ; preds = %loop, %entry113 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]114 call void (i1, ...) @llvm.experimental.guard(i1 %cond.2) [ "deopt"() ]115 %iv.next = add nuw nsw i32 %iv, 1116 %loop.cond = icmp ult i32 %iv.next, 100117 br i1 %loop.cond, label %loop, label %exit, !prof !1118 119exit: ; preds = %loop120 ret i32 0121 122failed: ; preds = %entry123 ret i32 -1124}125 126; FIXME: This loop is so rarely entered, that we don't want to widen here.127define i32 @test_intrinsic_very_unprofitable(i32 %n, i1 %cond.1, i1 %cond.2) {128; CHECK-LABEL: define i32 @test_intrinsic_very_unprofitable129; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {130; CHECK-NEXT: entry:131; CHECK-NEXT: [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]132; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]133; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]134; CHECK-NEXT: [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100135; CHECK-NEXT: br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF4:![0-9]+]]136; CHECK: loop:137; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]138; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1139; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 100140; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1]]141; CHECK: exit:142; CHECK-NEXT: ret i32 0143; CHECK: failed:144; CHECK-NEXT: ret i32 -1145;146entry:147 call void (i1, ...) @llvm.experimental.guard(i1 %cond.1) [ "deopt"() ]148 %loop.precondition = icmp uge i32 %n, 100149 br i1 %loop.precondition, label %loop, label %failed, !prof !4150 151loop: ; preds = %loop, %entry152 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]153 call void (i1, ...) @llvm.experimental.guard(i1 %cond.2) [ "deopt"() ]154 %iv.next = add nuw nsw i32 %iv, 1155 %loop.cond = icmp ult i32 %iv.next, 100156 br i1 %loop.cond, label %loop, label %exit, !prof !1157 158exit: ; preds = %loop159 ret i32 0160 161failed: ; preds = %entry162 ret i32 -1163}164 165; FIXME: This loop is so rarely entered, that we don't want to widen here.166define i32 @test_intrinsic_unprofitable(i32 %n, i1 %cond.1, i1 %cond.2) {167; CHECK-LABEL: define i32 @test_intrinsic_unprofitable168; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {169; CHECK-NEXT: entry:170; CHECK-NEXT: [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]171; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]172; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]173; CHECK-NEXT: [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100174; CHECK-NEXT: br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF5:![0-9]+]]175; CHECK: loop:176; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]177; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1178; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 100179; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1]]180; CHECK: exit:181; CHECK-NEXT: ret i32 0182; CHECK: failed:183; CHECK-NEXT: ret i32 -1184;185entry:186 call void (i1, ...) @llvm.experimental.guard(i1 %cond.1) [ "deopt"() ]187 %loop.precondition = icmp uge i32 %n, 100188 br i1 %loop.precondition, label %loop, label %failed, !prof !5189 190loop: ; preds = %loop, %entry191 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]192 call void (i1, ...) @llvm.experimental.guard(i1 %cond.2) [ "deopt"() ]193 %iv.next = add nuw nsw i32 %iv, 1194 %loop.cond = icmp ult i32 %iv.next, 100195 br i1 %loop.cond, label %loop, label %exit, !prof !1196 197exit: ; preds = %loop198 ret i32 0199 200failed: ; preds = %entry201 ret i32 -1202}203 204attributes #0 = { nocallback nofree nosync willreturn }205 206!0 = !{!"branch_weights", i32 1048576, i32 1}207!1 = !{!"branch_weights", i32 99, i32 1}208!2 = !{!"branch_weights", i32 1, i32 10}209!3 = !{!"branch_weights", i32 1, i32 99}210!4 = !{!"branch_weights", i32 1, i32 1048576}211!5 = !{!"branch_weights", i32 1, i32 1000}212