[llvm] r301214 - Revert "Compute safety information in a much finer granularity."
Evgeniy Stepanov via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 24 11:25:07 PDT 2017
Author: eugenis
Date: Mon Apr 24 13:25:07 2017
New Revision: 301214
URL: http://llvm.org/viewvc/llvm-project?rev=301214&view=rev
Log:
Revert "Compute safety information in a much finer granularity."
Use-after-free in llvm::isGuaranteedToExecute.
Removed:
llvm/trunk/test/Transforms/LICM/loop-early-exits.ll
Modified:
llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h
llvm/trunk/lib/Transforms/Scalar/LICM.cpp
llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp
llvm/trunk/test/Transforms/LICM/preheader-safe.ll
Modified: llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h?rev=301214&r1=301213&r2=301214&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h (original)
+++ llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h Mon Apr 24 13:25:07 2017
@@ -46,9 +46,9 @@ class TargetLibraryInfo;
/// \brief Captures loop safety information.
/// It keep information for loop & its header may throw exception.
struct LoopSafetyInfo {
- // The early exits in the loop, excluding loop exits.
- // These are calls that might throw, infinite loop, etc.
- SmallVector<Instruction *, 4> EarlyExits;
+ bool MayThrow = false; // The current loop contains an instruction which
+ // may throw.
+ bool HeaderMayThrow = false; // Same as previous, but specific to loop header
// Used to update funclet bundle operands.
DenseMap<BasicBlock *, ColorVector> BlockColors;
Modified: llvm/trunk/lib/Transforms/Scalar/LICM.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LICM.cpp?rev=301214&r1=301213&r2=301214&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LICM.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LICM.cpp Mon Apr 24 13:25:07 2017
@@ -478,17 +478,27 @@ bool llvm::hoistRegion(DomTreeNode *N, A
///
void llvm::computeLoopSafetyInfo(LoopSafetyInfo *SafetyInfo, Loop *CurLoop) {
assert(CurLoop != nullptr && "CurLoop cant be null");
- // Iterate over loop instructions and compute early exit points.
- for (Loop::block_iterator BB = CurLoop->block_begin(),
+ BasicBlock *Header = CurLoop->getHeader();
+ // Setting default safety values.
+ SafetyInfo->MayThrow = false;
+ SafetyInfo->HeaderMayThrow = false;
+ // Iterate over header and compute safety info.
+ for (BasicBlock::iterator I = Header->begin(), E = Header->end();
+ (I != E) && !SafetyInfo->HeaderMayThrow; ++I)
+ SafetyInfo->HeaderMayThrow |=
+ !isGuaranteedToTransferExecutionToSuccessor(&*I);
+
+ SafetyInfo->MayThrow = SafetyInfo->HeaderMayThrow;
+ // Iterate over loop instructions and compute safety info.
+ // Skip header as it has been computed and stored in HeaderMayThrow.
+ // The first block in loopinfo.Blocks is guaranteed to be the header.
+ assert(Header == *CurLoop->getBlocks().begin() && "First block must be header");
+ for (Loop::block_iterator BB = std::next(CurLoop->block_begin()),
BBE = CurLoop->block_end();
- BB != BBE; ++BB) {
- for (BasicBlock::iterator I = (*BB)->begin(), E = (*BB)->end(); I != E;
- ++I) {
- if (isGuaranteedToTransferExecutionToSuccessor(&*I))
- continue;
- SafetyInfo->EarlyExits.push_back(&*I);
- }
- }
+ (BB != BBE) && !SafetyInfo->MayThrow; ++BB)
+ for (BasicBlock::iterator I = (*BB)->begin(), E = (*BB)->end();
+ (I != E) && !SafetyInfo->MayThrow; ++I)
+ SafetyInfo->MayThrow |= !isGuaranteedToTransferExecutionToSuccessor(&*I);
// Compute funclet colors if we might sink/hoist in a function with a funclet
// personality routine.
@@ -1084,7 +1094,7 @@ bool llvm::promoteLoopAccessesToScalars(
// Do we know this object does not escape ?
bool IsKnownNonEscapingObject = false;
- if (!SafetyInfo->EarlyExits.empty()) {
+ if (SafetyInfo->MayThrow) {
// If a loop can throw, we have to insert a store along each unwind edge.
// That said, we can't actually make the unwind edge explicit. Therefore,
// we have to prove that the store is dead along the unwind edge.
Modified: llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp?rev=301214&r1=301213&r2=301214&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp Mon Apr 24 13:25:07 2017
@@ -272,7 +272,7 @@ bool LoopIdiomRecognize::runOnCountableL
// Give up if the loop has instructions may throw.
LoopSafetyInfo SafetyInfo;
computeLoopSafetyInfo(&SafetyInfo, CurLoop);
- if (!SafetyInfo.EarlyExits.empty())
+ if (SafetyInfo.MayThrow)
return MadeChange;
// Scan all the blocks in the loop that are not in subloops.
Modified: llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp?rev=301214&r1=301213&r2=301214&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp Mon Apr 24 13:25:07 2017
@@ -1044,11 +1044,21 @@ bool llvm::isGuaranteedToExecute(const I
const DominatorTree *DT, const Loop *CurLoop,
const LoopSafetyInfo *SafetyInfo) {
// We have to check to make sure that the instruction dominates all
- // of the exit points. If it doesn't, then there is a path out of the loop
- // which does not execute this instruction and its not guaranteed to execute.
- for (Instruction *ExitInst : SafetyInfo->EarlyExits)
- if (!DT->dominates(&Inst, ExitInst))
- return false;
+ // of the exit blocks. If it doesn't, then there is a path out of the loop
+ // which does not execute this instruction, so we can't hoist it.
+
+ // If the instruction is in the header block for the loop (which is very
+ // common), it is always guaranteed to dominate the exit blocks. Since this
+ // is a common case, and can save some work, check it now.
+ if (Inst.getParent() == CurLoop->getHeader())
+ // If there's a throw in the header block, we can't guarantee we'll reach
+ // Inst.
+ return !SafetyInfo->HeaderMayThrow;
+
+ // Somewhere in this loop there is an instruction which may throw and make us
+ // exit the loop.
+ if (SafetyInfo->MayThrow)
+ return false;
// Get the exit blocks for the current loop.
SmallVector<BasicBlock *, 8> ExitBlocks;
@@ -1061,9 +1071,7 @@ bool llvm::isGuaranteedToExecute(const I
// As a degenerate case, if the loop is statically infinite then we haven't
// proven anything since there are no exit blocks.
- // However, we also special case instruction from the header as the header
- // is always guaranteed to execute.
- if (ExitBlocks.empty() && Inst.getParent() != CurLoop->getHeader())
+ if (ExitBlocks.empty())
return false;
// FIXME: In general, we have to prove that the loop isn't an infinite loop.
Removed: llvm/trunk/test/Transforms/LICM/loop-early-exits.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LICM/loop-early-exits.ll?rev=301213&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/LICM/loop-early-exits.ll (original)
+++ llvm/trunk/test/Transforms/LICM/loop-early-exits.ll (removed)
@@ -1,82 +0,0 @@
-; RUN: opt -S -licm < %s | FileCheck %s
-
-declare void @use(i64 %a)
-declare void @use_nothrow(i64 %a) nounwind
-declare void @use_nothing()
-
-; We can move this udiv out of the loop as it comes before
-; the call instruction that may throw.
-define void @throw_header1(i64 %x, i64 %y, i1* %cond) {
-; CHECK-LABEL: throw_header1
-; 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
-}
-
-; We can not move this udiv out of the loop as it comes after
-; the call instruction that may throw.
-define void @throw_header2(i64 %x, i64 %y, i1* %cond) {
-; CHECK-LABEL: throw_header2
-; CHECK-LABEL: loop
-; CHECK: call void @use_nothing()
-; CHECK: %div = udiv i64 %x, %y
-entry:
- br label %loop
-
-loop: ; preds = %entry, %for.inc
- call void @use_nothing()
- %div = udiv i64 %x, %y
- call void @use_nothrow(i64 %div)
- br label %loop
-}
-
-; We can move this udiv out of the loop as it comes before
-; the call instruction that may throw.
-define void @throw_body1(i64 %x, i64 %y, i1* %cond) {
-; CHECK-LABEL: throw_body1
-; CHECK: %div = udiv i64 %x, %y
-; CHECK-LABEL: loop
-entry:
- br label %loop
-
-loop: ; preds = %entry, %for.inc
- br label %body
-
-body:
- %div = udiv i64 %x, %y
- call void @use(i64 %div)
- br i1 undef, label %loop, label %exit
-
-exit:
- ret void
-}
-
-; We can not move this udiv out of the loop as it comes after
-; the call instruction that may throw.
-define void @throw_body2(i64 %x, i64 %y, i1* %cond) {
-; CHECK-LABEL: throw_body2
-; CHECK-LABEL: loop
-; CHECK: call void @use_nothing()
-; CHECK: %div = udiv i64 %x, %y
-entry:
- br label %loop
-
-loop: ; preds = %entry, %for.inc
- br label %body
-
-body:
- call void @use_nothing()
- %div = udiv i64 %x, %y
- call void @use_nothrow(i64 %div)
- br i1 undef, label %loop, label %exit
-
-exit:
- ret void
-}
Modified: llvm/trunk/test/Transforms/LICM/preheader-safe.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LICM/preheader-safe.ll?rev=301214&r1=301213&r2=301214&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LICM/preheader-safe.ll (original)
+++ llvm/trunk/test/Transforms/LICM/preheader-safe.ll Mon Apr 24 13:25:07 2017
@@ -21,6 +21,20 @@ loop2:
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.
More information about the llvm-commits
mailing list