202 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=guard-widening -S < %s | FileCheck %s3 4declare i32 @llvm.experimental.deoptimize.i32(...)5 6; Make sure the two loop-invariant conditions can be widened together,7; and the widening point is outside the loop.8define i32 @test_01(i32 %start, i32 %x) {9; CHECK-LABEL: @test_01(10; CHECK-NEXT: entry:11; CHECK-NEXT: [[START_GW_FR:%.*]] = freeze i32 [[START:%.*]]12; CHECK-NEXT: [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]13; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[START_GW_FR]], [[X_GW_FR]]14; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 true, [[COND]]15; CHECK-NEXT: [[WC1:%.*]] = call i1 @llvm.experimental.widenable.condition()16; CHECK-NEXT: br label [[LOOP:%.*]]17; CHECK: loop:18; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START_GW_FR]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]19; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[WIDE_CHK]], [[WC1]]20; CHECK-NEXT: br i1 [[TMP0]], label [[GUARD_BLOCK:%.*]], label [[EXIT_BY_WC:%.*]]21; CHECK: exit_by_wc:22; CHECK-NEXT: [[RVAL1:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ]23; CHECK-NEXT: ret i32 [[RVAL1]]24; CHECK: guard_block:25; CHECK-NEXT: [[WC2:%.*]] = call i1 @llvm.experimental.widenable.condition()26; CHECK-NEXT: [[GUARD:%.*]] = and i1 [[COND]], [[WC2]]27; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[FAILURE:%.*]]28; CHECK: backedge:29; CHECK-NEXT: call void @side_effect()30; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 131; CHECK-NEXT: br label [[LOOP]]32; CHECK: exit:33; CHECK-NEXT: ret i32 -134; CHECK: failure:35; CHECK-NEXT: [[RVAL2:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ]36; CHECK-NEXT: ret i32 [[RVAL2]]37;38entry:39 %cond = icmp eq i32 %start, %x40 %wc1 = call i1 @llvm.experimental.widenable.condition()41 br label %loop42 43loop:44 %iv = phi i32 [ %start, %entry ], [ %iv.next, %backedge ]45 br i1 %wc1, label %guard_block, label %exit_by_wc46 47exit_by_wc:48 %rval1 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ]49 ret i32 %rval150 51guard_block:52 %wc2 = call i1 @llvm.experimental.widenable.condition()53 %guard = and i1 %cond, %wc254 br i1 %guard, label %backedge, label %failure55 56backedge:57 call void @side_effect()58 %iv.next = add i32 %iv, 159 br label %loop60 61exit:62 ret i32 -163 64failure:65 %rval2 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ]66 ret i32 %rval267}68 69 70; Make sure the loop-variant condition is not widened into loop-invariant.71define i32 @test_02(i32 %start, i32 %x) {72; CHECK-LABEL: @test_02(73; CHECK-NEXT: entry:74; CHECK-NEXT: [[WC1:%.*]] = call i1 @llvm.experimental.widenable.condition()75; CHECK-NEXT: br label [[LOOP:%.*]]76; CHECK: loop:77; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]78; CHECK-NEXT: br i1 [[WC1]], label [[GUARD_BLOCK:%.*]], label [[EXIT_BY_WC:%.*]]79; CHECK: exit_by_wc:80; CHECK-NEXT: [[RVAL1:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ]81; CHECK-NEXT: ret i32 [[RVAL1]]82; CHECK: guard_block:83; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[IV]], [[X:%.*]]84; CHECK-NEXT: [[WC2:%.*]] = call i1 @llvm.experimental.widenable.condition()85; CHECK-NEXT: [[GUARD:%.*]] = and i1 [[COND]], [[WC2]]86; CHECK-NEXT: br i1 [[GUARD]], label [[BACKEDGE]], label [[FAILURE:%.*]]87; CHECK: backedge:88; CHECK-NEXT: call void @side_effect()89; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 190; CHECK-NEXT: br label [[LOOP]]91; CHECK: exit:92; CHECK-NEXT: ret i32 -193; CHECK: failure:94; CHECK-NEXT: [[RVAL2:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ]95; CHECK-NEXT: ret i32 [[RVAL2]]96;97entry:98 %wc1 = call i1 @llvm.experimental.widenable.condition()99 br label %loop100 101loop:102 %iv = phi i32 [ %start, %entry ], [ %iv.next, %backedge ]103 br i1 %wc1, label %guard_block, label %exit_by_wc104 105exit_by_wc:106 %rval1 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ]107 ret i32 %rval1108 109guard_block:110 %cond = icmp eq i32 %iv, %x111 %wc2 = call i1 @llvm.experimental.widenable.condition()112 %guard = and i1 %cond, %wc2113 br i1 %guard, label %backedge, label %failure114 115backedge:116 call void @side_effect()117 %iv.next = add i32 %iv, 1118 br label %loop119 120exit:121 ret i32 -1122 123failure:124 %rval2 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ]125 ret i32 %rval2126}127 128; Same as test_01, but the initial condition is not immediately WC.129define i32 @test_03(i32 %start, i32 %x, i1 %c) {130; CHECK-LABEL: @test_03(131; CHECK-NEXT: entry:132; CHECK-NEXT: [[START_GW_FR:%.*]] = freeze i32 [[START:%.*]]133; CHECK-NEXT: [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]134; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[START_GW_FR]], [[X_GW_FR]]135; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[C:%.*]], [[COND]]136; CHECK-NEXT: [[WC1:%.*]] = call i1 @llvm.experimental.widenable.condition()137; CHECK-NEXT: br label [[LOOP:%.*]]138; CHECK: loop:139; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START_GW_FR]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]140; CHECK-NEXT: [[INVARIANT:%.*]] = and i1 [[WIDE_CHK]], [[WC1]]141; CHECK-NEXT: br i1 [[INVARIANT]], label [[GUARD_BLOCK:%.*]], label [[EXIT_BY_WC:%.*]]142; CHECK: exit_by_wc:143; CHECK-NEXT: [[RVAL1:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ]144; CHECK-NEXT: ret i32 [[RVAL1]]145; CHECK: guard_block:146; CHECK-NEXT: [[WC2:%.*]] = call i1 @llvm.experimental.widenable.condition()147; CHECK-NEXT: [[GUARD:%.*]] = and i1 [[COND]], [[WC2]]148; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[FAILURE:%.*]]149; CHECK: backedge:150; CHECK-NEXT: call void @side_effect()151; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1152; CHECK-NEXT: br label [[LOOP]]153; CHECK: exit:154; CHECK-NEXT: ret i32 -1155; CHECK: failure:156; CHECK-NEXT: [[RVAL2:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ]157; CHECK-NEXT: ret i32 [[RVAL2]]158; CHECK: early_failure:159; CHECK-NEXT: [[RVAL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[X_GW_FR]]) ]160; CHECK-NEXT: ret i32 [[RVAL3]]161;162entry:163 %cond = icmp eq i32 %start, %x164 %wc1 = call i1 @llvm.experimental.widenable.condition()165 %invariant = and i1 %c, %wc1166 br label %loop167 168loop:169 %iv = phi i32 [ %start, %entry ], [ %iv.next, %backedge ]170 br i1 %invariant, label %guard_block, label %exit_by_wc171 172exit_by_wc:173 %rval1 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ]174 ret i32 %rval1175 176guard_block:177 %wc2 = call i1 @llvm.experimental.widenable.condition()178 %guard = and i1 %cond, %wc2179 br i1 %guard, label %backedge, label %failure180 181backedge:182 call void @side_effect()183 %iv.next = add i32 %iv, 1184 br label %loop185 186exit:187 ret i32 -1188 189failure:190 %rval2 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ]191 ret i32 %rval2192 193early_failure:194 %rval3 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %x) ]195 ret i32 %rval3196}197 198; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite)199declare i1 @llvm.experimental.widenable.condition()200 201declare void @side_effect()202