mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-23 11:49:50 +00:00
Restrict the definition of loop preheader to avoid EH blocks
Differential Revision: https://reviews.llvm.org/D34487 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306070 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e4b1890fda
commit
c539eea7c6
@ -91,8 +91,9 @@ getExitEdges(SmallVectorImpl<Edge> &ExitEdges) const {
|
||||
|
||||
/// getLoopPreheader - If there is a preheader for this loop, return it. A
|
||||
/// loop has a preheader if there is only one edge to the header of the loop
|
||||
/// from outside of the loop. If this is the case, the block branching to the
|
||||
/// header of the loop is the preheader node.
|
||||
/// from outside of the loop and it is legal to hoist instructions into the
|
||||
/// predecessor. If this is the case, the block branching to the header of the
|
||||
/// loop is the preheader node.
|
||||
///
|
||||
/// This method returns null if there is no preheader for the loop.
|
||||
///
|
||||
@ -102,6 +103,10 @@ BlockT *LoopBase<BlockT, LoopT>::getLoopPreheader() const {
|
||||
BlockT *Out = getLoopPredecessor();
|
||||
if (!Out) return nullptr;
|
||||
|
||||
// Make sure we are allowed to hoist instructions into the predecessor.
|
||||
if (!Out->isLegalToHoistInto())
|
||||
return nullptr;
|
||||
|
||||
// Make sure there is only one exit out of the preheader.
|
||||
typedef GraphTraits<BlockT*> BlockTraits;
|
||||
typename BlockTraits::ChildIteratorType SI = BlockTraits::child_begin(Out);
|
||||
|
@ -376,6 +376,9 @@ public:
|
||||
/// Indicates if this is the entry block of a cleanup funclet.
|
||||
void setIsCleanupFuncletEntry(bool V = true) { IsCleanupFuncletEntry = V; }
|
||||
|
||||
/// Returns true if it is legal to hoist instructions into this block.
|
||||
bool isLegalToHoistInto() const;
|
||||
|
||||
// Code Layout methods.
|
||||
|
||||
/// Move 'this' block before or after the specified block. This only moves
|
||||
|
@ -395,6 +395,9 @@ public:
|
||||
static_cast<const BasicBlock *>(this)->getLandingPadInst());
|
||||
}
|
||||
|
||||
/// \brief Return true if it is legal to hoist instructions into this block.
|
||||
bool isLegalToHoistInto() const;
|
||||
|
||||
private:
|
||||
/// \brief Increment the internal refcount of the number of BlockAddresses
|
||||
/// referencing this BasicBlock by \p Amt.
|
||||
|
@ -228,6 +228,12 @@ LLVM_DUMP_METHOD void MachineBasicBlock::dump() const {
|
||||
}
|
||||
#endif
|
||||
|
||||
bool MachineBasicBlock::isLegalToHoistInto() const {
|
||||
if (isReturnBlock() || hasEHPadSuccessor())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
StringRef MachineBasicBlock::getName() const {
|
||||
if (const BasicBlock *LBB = getBasicBlock())
|
||||
return LBB->getName();
|
||||
|
@ -355,6 +355,19 @@ bool BasicBlock::canSplitPredecessors() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BasicBlock::isLegalToHoistInto() const {
|
||||
auto *Term = getTerminator();
|
||||
// No terminator means the block is under construction.
|
||||
if (!Term)
|
||||
return true;
|
||||
|
||||
// If the block has no successors, there can be no instructions to hoist.
|
||||
assert(Term->getNumSuccessors() > 0);
|
||||
|
||||
// Instructions should not be hoisted across exception handling boundaries.
|
||||
return !Term->isExceptional();
|
||||
}
|
||||
|
||||
/// This splits a basic block into two at the specified
|
||||
/// instruction. Note that all instructions BEFORE the specified iterator stay
|
||||
/// as part of the original basic block, an unconditional branch is added to
|
||||
|
41
test/Transforms/LoopRotate/catchret.ll
Executable file
41
test/Transforms/LoopRotate/catchret.ll
Executable file
@ -0,0 +1,41 @@
|
||||
; RUN: opt < %s -loop-rotate -S | FileCheck %s
|
||||
|
||||
target triple = "x86_64-pc-windows-msvc"
|
||||
|
||||
declare void @always_throws()
|
||||
|
||||
define i32 @test() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
|
||||
entry:
|
||||
invoke void @always_throws()
|
||||
to label %continue unwind label %catch.dispatch
|
||||
|
||||
continue:
|
||||
unreachable
|
||||
|
||||
catch.dispatch:
|
||||
%t0 = catchswitch within none [label %catch] unwind to caller
|
||||
|
||||
catch:
|
||||
%t1 = catchpad within %t0 [i8* null, i32 64, i8* null]
|
||||
catchret from %t1 to label %for.cond
|
||||
|
||||
for.cond:
|
||||
%sum = phi i32 [ %add, %for.body ], [ 0, %catch ]
|
||||
%i = phi i32 [ %inc, %for.body ], [ 0, %catch ]
|
||||
%cmp = icmp slt i32 %i, 1
|
||||
br i1 %cmp, label %for.body, label %return
|
||||
|
||||
for.body:
|
||||
%add = add nsw i32 1, %sum
|
||||
%inc = add nsw i32 %i, 1
|
||||
br label %for.cond
|
||||
|
||||
return:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
; CHECK: catch:
|
||||
; CHECK-NEXT: catchpad
|
||||
; CHECK-NEXT: catchret
|
||||
|
||||
declare i32 @__CxxFrameHandler3(...)
|
Loading…
Reference in New Issue
Block a user