360 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; Hot loop, frequently entered, should widen.5define i32 @test_intrinsic_very_profitable(i32 %n, i1 %cond.1, i1 %cond.2) {6; CHECK-LABEL: define i32 @test_intrinsic_very_profitable7; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {8; CHECK-NEXT: entry:9; CHECK-NEXT: [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]10; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]11; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()12; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]13; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0:![0-9]+]]14; CHECK: deopt:15; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]16; CHECK-NEXT: ret i32 [[DEOPTCALL]]17; CHECK: guarded:18; CHECK-NEXT: [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 10019; CHECK-NEXT: br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF0]]20; CHECK: loop:21; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[GUARDED]] ], [ [[IV_NEXT:%.*]], [[GUARDED1:%.*]] ]22; CHECK-NEXT: [[WIDENABLE_COND4:%.*]] = call i1 @llvm.experimental.widenable.condition()23; CHECK-NEXT: [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2_GW_FR]], [[WIDENABLE_COND4]]24; CHECK-NEXT: br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof [[PROF0]]25; CHECK: deopt2:26; CHECK-NEXT: [[DEOPTCALL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]27; CHECK-NEXT: ret i32 [[DEOPTCALL3]]28; CHECK: guarded1:29; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 130; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 10031; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1:![0-9]+]]32; CHECK: exit:33; CHECK-NEXT: ret i32 034; CHECK: failed:35; CHECK-NEXT: ret i32 -136;37entry:38 %widenable_cond = call i1 @llvm.experimental.widenable.condition()39 %exiplicit_guard_cond = and i1 %cond.1, %widenable_cond40 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !041 42deopt: ; preds = %entry43 %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]44 ret i32 %deoptcall45 46guarded: ; preds = %entry47 %loop.precondition = icmp uge i32 %n, 10048 br i1 %loop.precondition, label %loop, label %failed, !prof !049 50loop: ; preds = %guarded1, %guarded51 %iv = phi i32 [ 0, %guarded ], [ %iv.next, %guarded1 ]52 %widenable_cond4 = call i1 @llvm.experimental.widenable.condition()53 %exiplicit_guard_cond5 = and i1 %cond.2, %widenable_cond454 br i1 %exiplicit_guard_cond5, label %guarded1, label %deopt2, !prof !055 56deopt2: ; preds = %loop57 %deoptcall3 = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]58 ret i32 %deoptcall359 60guarded1: ; preds = %loop61 %iv.next = add nuw nsw i32 %iv, 162 %loop.cond = icmp ult i32 %iv.next, 10063 br i1 %loop.cond, label %loop, label %exit, !prof !164 65exit: ; preds = %guarded166 ret i32 067 68failed: ; preds = %guarded69 ret i32 -170}71 72; Even though the loop is rarely entered, it has so many iterations that the widening73; is still profitable.74define i32 @test_intrinsic_profitable(i32 %n, i1 %cond.1, i1 %cond.2) {75; CHECK-LABEL: define i32 @test_intrinsic_profitable76; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {77; CHECK-NEXT: entry:78; CHECK-NEXT: [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]79; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]80; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()81; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]82; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]83; CHECK: deopt:84; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]85; CHECK-NEXT: ret i32 [[DEOPTCALL]]86; CHECK: guarded:87; CHECK-NEXT: [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 10088; CHECK-NEXT: br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF2:![0-9]+]]89; CHECK: loop:90; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[GUARDED]] ], [ [[IV_NEXT:%.*]], [[GUARDED1:%.*]] ]91; CHECK-NEXT: [[WIDENABLE_COND4:%.*]] = call i1 @llvm.experimental.widenable.condition()92; CHECK-NEXT: [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2_GW_FR]], [[WIDENABLE_COND4]]93; CHECK-NEXT: br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof [[PROF0]]94; CHECK: deopt2:95; CHECK-NEXT: [[DEOPTCALL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]96; CHECK-NEXT: ret i32 [[DEOPTCALL3]]97; CHECK: guarded1:98; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 199; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 100100; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1]]101; CHECK: exit:102; CHECK-NEXT: ret i32 0103; CHECK: failed:104; CHECK-NEXT: ret i32 -1105;106entry:107 %widenable_cond = call i1 @llvm.experimental.widenable.condition()108 %exiplicit_guard_cond = and i1 %cond.1, %widenable_cond109 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0110 111deopt: ; preds = %entry112 %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]113 ret i32 %deoptcall114 115guarded: ; preds = %entry116 %loop.precondition = icmp uge i32 %n, 100117 br i1 %loop.precondition, label %loop, label %failed, !prof !2118 119loop: ; preds = %guarded1, %guarded120 %iv = phi i32 [ 0, %guarded ], [ %iv.next, %guarded1 ]121 %widenable_cond4 = call i1 @llvm.experimental.widenable.condition()122 %exiplicit_guard_cond5 = and i1 %cond.2, %widenable_cond4123 br i1 %exiplicit_guard_cond5, label %guarded1, label %deopt2, !prof !0124 125deopt2: ; preds = %loop126 %deoptcall3 = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]127 ret i32 %deoptcall3128 129guarded1: ; preds = %loop130 %iv.next = add nuw nsw i32 %iv, 1131 %loop.cond = icmp ult i32 %iv.next, 100132 br i1 %loop.cond, label %loop, label %exit, !prof !1133 134exit: ; preds = %guarded1135 ret i32 0136 137failed: ; preds = %guarded138 ret i32 -1139}140 141; Loop's hotness compensates rareness of its entrance. We still want to widen, because142; it may open up some optimization opportunities.143define i32 @test_intrinsic_neutral(i32 %n, i1 %cond.1, i1 %cond.2) {144; CHECK-LABEL: define i32 @test_intrinsic_neutral145; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {146; CHECK-NEXT: entry:147; CHECK-NEXT: [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]148; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]149; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()150; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]151; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]152; CHECK: deopt:153; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]154; CHECK-NEXT: ret i32 [[DEOPTCALL]]155; CHECK: guarded:156; CHECK-NEXT: [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100157; CHECK-NEXT: br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF3:![0-9]+]]158; CHECK: loop:159; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[GUARDED]] ], [ [[IV_NEXT:%.*]], [[GUARDED1:%.*]] ]160; CHECK-NEXT: [[WIDENABLE_COND4:%.*]] = call i1 @llvm.experimental.widenable.condition()161; CHECK-NEXT: [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2_GW_FR]], [[WIDENABLE_COND4]]162; CHECK-NEXT: br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof [[PROF0]]163; CHECK: deopt2:164; CHECK-NEXT: [[DEOPTCALL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]165; CHECK-NEXT: ret i32 [[DEOPTCALL3]]166; CHECK: guarded1:167; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1168; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 100169; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1]]170; CHECK: exit:171; CHECK-NEXT: ret i32 0172; CHECK: failed:173; CHECK-NEXT: ret i32 -1174;175entry:176 %widenable_cond = call i1 @llvm.experimental.widenable.condition()177 %exiplicit_guard_cond = and i1 %cond.1, %widenable_cond178 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0179 180deopt: ; preds = %entry181 %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]182 ret i32 %deoptcall183 184guarded: ; preds = %entry185 %loop.precondition = icmp uge i32 %n, 100186 br i1 %loop.precondition, label %loop, label %failed, !prof !3187 188loop: ; preds = %guarded1, %guarded189 %iv = phi i32 [ 0, %guarded ], [ %iv.next, %guarded1 ]190 %widenable_cond4 = call i1 @llvm.experimental.widenable.condition()191 %exiplicit_guard_cond5 = and i1 %cond.2, %widenable_cond4192 br i1 %exiplicit_guard_cond5, label %guarded1, label %deopt2, !prof !0193 194deopt2: ; preds = %loop195 %deoptcall3 = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]196 ret i32 %deoptcall3197 198guarded1: ; preds = %loop199 %iv.next = add nuw nsw i32 %iv, 1200 %loop.cond = icmp ult i32 %iv.next, 100201 br i1 %loop.cond, label %loop, label %exit, !prof !1202 203exit: ; preds = %guarded1204 ret i32 0205 206failed: ; preds = %guarded207 ret i32 -1208}209 210; FIXME: This loop is so rarely entered, that we don't want to widen here.211define i32 @test_intrinsic_very_unprofitable(i32 %n, i1 %cond.1, i1 %cond.2) {212; CHECK-LABEL: define i32 @test_intrinsic_very_unprofitable213; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {214; CHECK-NEXT: entry:215; CHECK-NEXT: [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]216; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]217; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()218; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]219; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]220; CHECK: deopt:221; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]222; CHECK-NEXT: ret i32 [[DEOPTCALL]]223; CHECK: guarded:224; CHECK-NEXT: [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100225; CHECK-NEXT: br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF4:![0-9]+]]226; CHECK: loop:227; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[GUARDED]] ], [ [[IV_NEXT:%.*]], [[GUARDED1:%.*]] ]228; CHECK-NEXT: [[WIDENABLE_COND4:%.*]] = call i1 @llvm.experimental.widenable.condition()229; CHECK-NEXT: [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2_GW_FR]], [[WIDENABLE_COND4]]230; CHECK-NEXT: br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof [[PROF0]]231; CHECK: deopt2:232; CHECK-NEXT: [[DEOPTCALL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]233; CHECK-NEXT: ret i32 [[DEOPTCALL3]]234; CHECK: guarded1:235; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1236; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 100237; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1]]238; CHECK: exit:239; CHECK-NEXT: ret i32 0240; CHECK: failed:241; CHECK-NEXT: ret i32 -1242;243entry:244 %widenable_cond = call i1 @llvm.experimental.widenable.condition()245 %exiplicit_guard_cond = and i1 %cond.1, %widenable_cond246 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0247 248deopt: ; preds = %entry249 %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]250 ret i32 %deoptcall251 252guarded: ; preds = %entry253 %loop.precondition = icmp uge i32 %n, 100254 br i1 %loop.precondition, label %loop, label %failed, !prof !4255 256loop: ; preds = %guarded1, %guarded257 %iv = phi i32 [ 0, %guarded ], [ %iv.next, %guarded1 ]258 %widenable_cond4 = call i1 @llvm.experimental.widenable.condition()259 %exiplicit_guard_cond5 = and i1 %cond.2, %widenable_cond4260 br i1 %exiplicit_guard_cond5, label %guarded1, label %deopt2, !prof !0261 262deopt2: ; preds = %loop263 %deoptcall3 = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]264 ret i32 %deoptcall3265 266guarded1: ; preds = %loop267 %iv.next = add nuw nsw i32 %iv, 1268 %loop.cond = icmp ult i32 %iv.next, 100269 br i1 %loop.cond, label %loop, label %exit, !prof !1270 271exit: ; preds = %guarded1272 ret i32 0273 274failed: ; preds = %guarded275 ret i32 -1276}277 278; FIXME: This loop is so rarely entered, that we don't want to widen here.279define i32 @test_intrinsic_unprofitable(i32 %n, i1 %cond.1, i1 %cond.2) {280; CHECK-LABEL: define i32 @test_intrinsic_unprofitable281; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {282; CHECK-NEXT: entry:283; CHECK-NEXT: [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]284; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]285; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()286; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]287; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]288; CHECK: deopt:289; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]290; CHECK-NEXT: ret i32 [[DEOPTCALL]]291; CHECK: guarded:292; CHECK-NEXT: [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100293; CHECK-NEXT: br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF5:![0-9]+]]294; CHECK: loop:295; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[GUARDED]] ], [ [[IV_NEXT:%.*]], [[GUARDED1:%.*]] ]296; CHECK-NEXT: [[WIDENABLE_COND4:%.*]] = call i1 @llvm.experimental.widenable.condition()297; CHECK-NEXT: [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2_GW_FR]], [[WIDENABLE_COND4]]298; CHECK-NEXT: br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof [[PROF0]]299; CHECK: deopt2:300; CHECK-NEXT: [[DEOPTCALL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]301; CHECK-NEXT: ret i32 [[DEOPTCALL3]]302; CHECK: guarded1:303; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1304; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 100305; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1]]306; CHECK: exit:307; CHECK-NEXT: ret i32 0308; CHECK: failed:309; CHECK-NEXT: ret i32 -1310;311entry:312 %widenable_cond = call i1 @llvm.experimental.widenable.condition()313 %exiplicit_guard_cond = and i1 %cond.1, %widenable_cond314 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0315 316deopt: ; preds = %entry317 %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]318 ret i32 %deoptcall319 320guarded: ; preds = %entry321 %loop.precondition = icmp uge i32 %n, 100322 br i1 %loop.precondition, label %loop, label %failed, !prof !5323 324loop: ; preds = %guarded1, %guarded325 %iv = phi i32 [ 0, %guarded ], [ %iv.next, %guarded1 ]326 %widenable_cond4 = call i1 @llvm.experimental.widenable.condition()327 %exiplicit_guard_cond5 = and i1 %cond.2, %widenable_cond4328 br i1 %exiplicit_guard_cond5, label %guarded1, label %deopt2, !prof !0329 330deopt2: ; preds = %loop331 %deoptcall3 = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]332 ret i32 %deoptcall3333 334guarded1: ; preds = %loop335 %iv.next = add nuw nsw i32 %iv, 1336 %loop.cond = icmp ult i32 %iv.next, 100337 br i1 %loop.cond, label %loop, label %exit, !prof !1338 339exit: ; preds = %guarded1340 ret i32 0341 342failed: ; preds = %guarded343 ret i32 -1344}345 346declare i32 @llvm.experimental.deoptimize.i32(...)347 348; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite)349declare noundef i1 @llvm.experimental.widenable.condition() #1350 351attributes #0 = { nocallback nofree nosync willreturn }352attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite) }353 354!0 = !{!"branch_weights", i32 1048576, i32 1}355!1 = !{!"branch_weights", i32 99, i32 1}356!2 = !{!"branch_weights", i32 1, i32 10}357!3 = !{!"branch_weights", i32 1, i32 99}358!4 = !{!"branch_weights", i32 1, i32 1048576}359!5 = !{!"branch_weights", i32 1, i32 1000}360