Refine the notion of MayThrow in LICM to include a header specific version
In LICM, we have a check for an instruction which is guaranteed to execute and thus can't introduce any new faults if moved to the preheader. To handle a function which might unconditionally throw when first called, we check for any potentially throwing call in the loop and give up.
This is unfortunate when the potentially throwing condition is down a rare path. It prevents essentially all LICM of potentially faulting instructions where the faulting condition is checked outside the loop. It also greatly diminishes the utility of loop unswitching since control dependent instructions - which are now likely in the loops header block - will not be lifted by subsequent LICM runs.
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
}
The current patch really only helps with non-memory instructions (i.e. divs, etc..) since the maythrow call down the rare path will be considered to alias an otherwise hoistable load. The one exception is that it does kick in for loads which are known to be invariant without regard to other possible stores, i.e. those marked with either !invarant.load metadata of tbaa 'is constant memory' metadata.
Differential Revision: http://reviews.llvm.org/D6725
llvm-svn: 224965
2014-12-30 07:00:57 +08:00
|
|
|
; RUN: opt -S -licm < %s | FileCheck %s
|
|
|
|
|
|
|
|
declare void @use_nothrow(i64 %a) nounwind
|
|
|
|
declare void @use(i64 %a)
|
|
|
|
|
|
|
|
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
|
[LICM] Make isGuaranteedToExecute more accurate.
Summary:
Make isGuaranteedToExecute use the
isGuaranteedToTransferExecutionToSuccessor helper, and make that helper
a bit more accurate.
There's a potential performance impact here from assuming that arbitrary
calls might not return. This probably has little impact on loads and
stores to a pointer because most things alias analysis can reason about
are dereferenceable anyway. The other impacts, like less aggressive
hoisting of sdiv by a variable and less aggressive hoisting around
volatile memory operations, are unlikely to matter for real code.
This also impacts SCEV, which uses the same helper. It's a minor
improvement there because we can tell that, for example, memcpy always
returns normally. Strictly speaking, it's also introducing
a bug, but it's not any worse than everywhere else we assume readonly
functions terminate.
Fixes http://llvm.org/PR27857.
Reviewers: hfinkel, reames, chandlerc, sanjoy
Subscribers: broune, llvm-commits
Differential Revision: http://reviews.llvm.org/D21167
llvm-svn: 272489
2016-06-12 05:48:25 +08:00
|
|
|
br label %loop2
|
|
|
|
|
|
|
|
loop2:
|
Refine the notion of MayThrow in LICM to include a header specific version
In LICM, we have a check for an instruction which is guaranteed to execute and thus can't introduce any new faults if moved to the preheader. To handle a function which might unconditionally throw when first called, we check for any potentially throwing call in the loop and give up.
This is unfortunate when the potentially throwing condition is down a rare path. It prevents essentially all LICM of potentially faulting instructions where the faulting condition is checked outside the loop. It also greatly diminishes the utility of loop unswitching since control dependent instructions - which are now likely in the loops header block - will not be lifted by subsequent LICM runs.
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
}
The current patch really only helps with non-memory instructions (i.e. divs, etc..) since the maythrow call down the rare path will be considered to alias an otherwise hoistable load. The one exception is that it does kick in for loads which are known to be invariant without regard to other possible stores, i.e. those marked with either !invarant.load metadata of tbaa 'is constant memory' metadata.
Differential Revision: http://reviews.llvm.org/D6725
llvm-svn: 224965
2014-12-30 07:00:57 +08:00
|
|
|
call void @use_nothrow(i64 %div)
|
|
|
|
br label %loop
|
|
|
|
}
|
|
|
|
; Negative test
|
|
|
|
define void @throw_header(i64 %x, i64 %y, i1* %cond) {
|
|
|
|
; CHECK-LABEL: throw_header
|
|
|
|
; CHECK-LABEL: loop
|
|
|
|
; CHECK: %div = udiv i64 %x, %y
|
|
|
|
; 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
|
|
|
|
}
|
|
|
|
|
|
|
|
; 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
|
|
|
|
}
|
|
|
|
; 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: %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:
|
|
|
|
%div = udiv i64 %x, %y
|
|
|
|
call void @use(i64 %div)
|
|
|
|
br label %loop
|
|
|
|
}
|