1 ; RUN: opt -S -licm < %s | FileCheck %s 2 ; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' -S %s | FileCheck %s 3 4 declare void @use_nothrow(i64 %a) nounwind 5 declare void @use(i64 %a) 6 declare void @maythrow() 7 8 define void @nothrow(i64 %x, i64 %y, i1* %cond) { 9 ; CHECK-LABEL: nothrow 10 ; CHECK-LABEL: entry 11 ; CHECK: %div = udiv i64 %x, %y 12 ; CHECK-LABEL: loop 13 ; CHECK: call void @use_nothrow(i64 %div) 14 entry: 15 br label %loop 16 17 loop: ; preds = %entry, %for.inc 18 %div = udiv i64 %x, %y 19 br label %loop2 20 21 loop2: 22 call void @use_nothrow(i64 %div) 23 br label %loop 24 } 25 26 ; The udiv is guarantee to execute if the loop is 27 define void @throw_header_after(i64 %x, i64 %y, i1* %cond) { 28 ; CHECK-LABEL: throw_header_after 29 ; CHECK: %div = udiv i64 %x, %y 30 ; CHECK-LABEL: loop 31 ; CHECK: call void @use(i64 %div) 32 entry: 33 br label %loop 34 35 loop: ; preds = %entry, %for.inc 36 %div = udiv i64 %x, %y 37 call void @use(i64 %div) 38 br label %loop 39 } 40 define void @throw_header_after_rec(i64* %xp, i64* %yp, i1* %cond) { 41 ; CHECK-LABEL: throw_header_after_rec 42 ; CHECK: %x = load i64, i64* %xp 43 ; CHECK: %y = load i64, i64* %yp 44 ; CHECK: %div = udiv i64 %x, %y 45 ; CHECK-LABEL: loop 46 ; CHECK: call void @use(i64 %div) 47 entry: 48 br label %loop 49 50 loop: ; preds = %entry, %for.inc 51 %x = load i64, i64* %xp 52 %y = load i64, i64* %yp 53 %div = udiv i64 %x, %y 54 call void @use(i64 %div) readonly 55 br label %loop 56 } 57 58 ; Similiar to the above, but the hoistable instruction (%y in this case) 59 ; happens not to be the first instruction in the block. 60 define void @throw_header_after_nonfirst(i64* %xp, i64* %yp, i1* %cond) { 61 ; CHECK-LABEL: throw_header_after_nonfirst 62 ; CHECK: %y = load i64, i64* %yp 63 ; CHECK-LABEL: loop 64 ; CHECK: %x = load i64, i64* %gep 65 ; CHECK: %div = udiv i64 %x, %y 66 ; CHECK: call void @use(i64 %div) 67 entry: 68 br label %loop 69 70 loop: ; preds = %entry, %for.inc 71 %iv = phi i64 [0, %entry], [%div, %loop] 72 %gep = getelementptr i64, i64* %xp, i64 %iv 73 %x = load i64, i64* %gep 74 %y = load i64, i64* %yp 75 %div = udiv i64 %x, %y 76 call void @use(i64 %div) readonly 77 br label %loop 78 } 79 80 ; Negative test 81 define void @throw_header_before(i64 %x, i64 %y, i1* %cond) { 82 ; CHECK-LABEL: throw_header_before 83 ; CHECK-LABEL: loop 84 ; CHECK: %div = udiv i64 %x, %y 85 ; CHECK: call void @use(i64 %div) 86 entry: 87 br label %loop 88 89 loop: ; preds = %entry, %for.inc 90 call void @maythrow() 91 %div = udiv i64 %x, %y 92 call void @use(i64 %div) 93 br label %loop 94 } 95 96 ; The header is known no throw, but the loop is not. We can 97 ; still lift out of the header. 98 define void @nothrow_header(i64 %x, i64 %y, i1 %cond) { 99 ; CHECK-LABEL: nothrow_header 100 ; CHECK-LABEL: entry 101 ; CHECK: %div = udiv i64 %x, %y 102 ; CHECK-LABEL: loop 103 ; CHECK: call void @use(i64 %div) 104 entry: 105 br label %loop 106 loop: ; preds = %entry, %for.inc 107 %div = udiv i64 %x, %y 108 br i1 %cond, label %loop-if, label %exit 109 loop-if: 110 call void @use(i64 %div) 111 br label %loop 112 exit: 113 ret void 114 } 115 ; Negative test - can't move out of throwing block 116 define void @nothrow_header_neg(i64 %x, i64 %y, i1 %cond) { 117 ; CHECK-LABEL: nothrow_header_neg 118 ; CHECK-LABEL: entry 119 ; CHECK-LABEL: loop 120 ; CHECK: %div = udiv i64 %x, %y 121 ; CHECK: call void @use(i64 %div) 122 entry: 123 br label %loop 124 loop: ; preds = %entry, %for.inc 125 br label %loop-if 126 loop-if: 127 %div = udiv i64 %x, %y 128 call void @use(i64 %div) 129 br label %loop 130 } 131