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