1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=licm < %s | FileCheck %s 3; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop-mssa(licm)' -S %s | FileCheck %s 4 5; Make sure we don't hoist the unsafe division to some executable block. 6define void @test_impossible_exit_in_untaken_block(i32 %a, i32 %b, ptr %p) { 7; CHECK-LABEL: @test_impossible_exit_in_untaken_block( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: br label [[LOOP:%.*]] 10; CHECK: loop: 11; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 12; CHECK-NEXT: br i1 false, label [[NEVER_TAKEN:%.*]], label [[BACKEDGE]] 13; CHECK: never_taken: 14; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A:%.*]], [[B:%.*]] 15; CHECK-NEXT: store i32 [[DIV]], ptr [[P:%.*]] 16; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[EXIT:%.*]] 17; CHECK: backedge: 18; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 19; CHECK-NEXT: br label [[LOOP]] 20; CHECK: exit: 21; CHECK-NEXT: ret void 22; 23entry: 24 br label %loop 25 26loop: 27 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 28 br i1 false, label %never_taken, label %backedge 29 30never_taken: 31 %div = sdiv i32 %a, %b 32 store i32 %div, ptr %p 33 br i1 true, label %backedge, label %exit 34 35backedge: 36 %iv.next = add i32 %iv, 1 37 br label %loop 38 39exit: 40 ret void 41} 42 43; The test above is UB in C++, because there is a requirement that any 44; thead should eventually terminate, execute volatile access operation, call IO 45; or synchronize. In spite of that, the behavior in the test above *might* be 46; correct. This one is equivalent to the test above, but it has a volatile 47; memory access in the loop's mustexec block, so the compiler no longer has a 48; right to assume that it must terminate. Show that the same problem persists, 49; and that it was a bug and not a cool optimization based on loop infinity. 50; By the moment when this test was added, it was accidentally correct due to 51; reasons not directly related to this piece of logic. Make sure that it keeps 52; correct in the future. 53define void @test_impossible_exit_in_untaken_block_no_ub(i32 %a, i32 %b, ptr noalias %p, ptr noalias %vp) { 54; CHECK-LABEL: @test_impossible_exit_in_untaken_block_no_ub( 55; CHECK-NEXT: entry: 56; CHECK-NEXT: br label [[LOOP:%.*]] 57; CHECK: loop: 58; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 59; CHECK-NEXT: [[TMP0:%.*]] = load volatile i32, ptr [[VP:%.*]] 60; CHECK-NEXT: br i1 false, label [[NEVER_TAKEN:%.*]], label [[BACKEDGE]] 61; CHECK: never_taken: 62; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A:%.*]], [[B:%.*]] 63; CHECK-NEXT: store i32 [[DIV]], ptr [[P:%.*]] 64; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[EXIT:%.*]] 65; CHECK: backedge: 66; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 67; CHECK-NEXT: br label [[LOOP]] 68; CHECK: exit: 69; CHECK-NEXT: ret void 70; 71entry: 72 br label %loop 73 74loop: 75 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 76 load volatile i32, ptr %vp 77 br i1 false, label %never_taken, label %backedge 78 79never_taken: 80 %div = sdiv i32 %a, %b 81 store i32 %div, ptr %p 82 br i1 true, label %backedge, label %exit 83 84backedge: 85 %iv.next = add i32 %iv, 1 86 br label %loop 87 88exit: 89 ret void 90} 91 92; Same as above, but the volatile access is in mustexecute backedge block. The 93; loop is no longer "finite by specification", make sure we don't hoist sdiv 94; from it no matter how general the MustThrow analysis is. 95define void @test_impossible_exit_in_untaken_block_no_ub_2(i32 %a, i32 %b, ptr noalias %p, ptr noalias %vp) { 96; CHECK-LABEL: @test_impossible_exit_in_untaken_block_no_ub_2( 97; CHECK-NEXT: entry: 98; CHECK-NEXT: br label [[LOOP:%.*]] 99; CHECK: loop: 100; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 101; CHECK-NEXT: br i1 false, label [[NEVER_TAKEN:%.*]], label [[BACKEDGE]] 102; CHECK: never_taken: 103; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A:%.*]], [[B:%.*]] 104; CHECK-NEXT: store i32 [[DIV]], ptr [[P:%.*]] 105; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[EXIT:%.*]] 106; CHECK: backedge: 107; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 108; CHECK-NEXT: [[TMP0:%.*]] = load volatile i32, ptr [[VP:%.*]] 109; CHECK-NEXT: br label [[LOOP]] 110; CHECK: exit: 111; CHECK-NEXT: ret void 112; 113entry: 114 br label %loop 115 116loop: 117 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 118 br i1 false, label %never_taken, label %backedge 119 120never_taken: 121 %div = sdiv i32 %a, %b 122 store i32 %div, ptr %p 123 br i1 true, label %backedge, label %exit 124 125backedge: 126 %iv.next = add i32 %iv, 1 127 load volatile i32, ptr %vp 128 br label %loop 129 130exit: 131 ret void 132} 133