Skip to content

Commit d497119

Browse files
author
Andrew Kaylor
committed
Restrict the definition of loop preheader to avoid EH blocks
Differential Revision: https://reviews.llvm.org/D34487 llvm-svn: 306070
1 parent 08b2035 commit d497119

File tree

6 files changed

+73
-2
lines changed

6 files changed

+73
-2
lines changed

llvm/include/llvm/Analysis/LoopInfoImpl.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,9 @@ getExitEdges(SmallVectorImpl<Edge> &ExitEdges) const {
9191

9292
/// getLoopPreheader - If there is a preheader for this loop, return it. A
9393
/// loop has a preheader if there is only one edge to the header of the loop
94-
/// from outside of the loop. If this is the case, the block branching to the
95-
/// header of the loop is the preheader node.
94+
/// from outside of the loop and it is legal to hoist instructions into the
95+
/// predecessor. If this is the case, the block branching to the header of the
96+
/// loop is the preheader node.
9697
///
9798
/// This method returns null if there is no preheader for the loop.
9899
///
@@ -102,6 +103,10 @@ BlockT *LoopBase<BlockT, LoopT>::getLoopPreheader() const {
102103
BlockT *Out = getLoopPredecessor();
103104
if (!Out) return nullptr;
104105

106+
// Make sure we are allowed to hoist instructions into the predecessor.
107+
if (!Out->isLegalToHoistInto())
108+
return nullptr;
109+
105110
// Make sure there is only one exit out of the preheader.
106111
typedef GraphTraits<BlockT*> BlockTraits;
107112
typename BlockTraits::ChildIteratorType SI = BlockTraits::child_begin(Out);

llvm/include/llvm/CodeGen/MachineBasicBlock.h

+3
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,9 @@ class MachineBasicBlock
376376
/// Indicates if this is the entry block of a cleanup funclet.
377377
void setIsCleanupFuncletEntry(bool V = true) { IsCleanupFuncletEntry = V; }
378378

379+
/// Returns true if it is legal to hoist instructions into this block.
380+
bool isLegalToHoistInto() const;
381+
379382
// Code Layout methods.
380383

381384
/// Move 'this' block before or after the specified block. This only moves

llvm/include/llvm/IR/BasicBlock.h

+3
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,9 @@ class BasicBlock final : public Value, // Basic blocks are data objects also
395395
static_cast<const BasicBlock *>(this)->getLandingPadInst());
396396
}
397397

398+
/// \brief Return true if it is legal to hoist instructions into this block.
399+
bool isLegalToHoistInto() const;
400+
398401
private:
399402
/// \brief Increment the internal refcount of the number of BlockAddresses
400403
/// referencing this BasicBlock by \p Amt.

llvm/lib/CodeGen/MachineBasicBlock.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,12 @@ LLVM_DUMP_METHOD void MachineBasicBlock::dump() const {
228228
}
229229
#endif
230230

231+
bool MachineBasicBlock::isLegalToHoistInto() const {
232+
if (isReturnBlock() || hasEHPadSuccessor())
233+
return false;
234+
return true;
235+
}
236+
231237
StringRef MachineBasicBlock::getName() const {
232238
if (const BasicBlock *LBB = getBasicBlock())
233239
return LBB->getName();

llvm/lib/IR/BasicBlock.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,19 @@ bool BasicBlock::canSplitPredecessors() const {
355355
return true;
356356
}
357357

358+
bool BasicBlock::isLegalToHoistInto() const {
359+
auto *Term = getTerminator();
360+
// No terminator means the block is under construction.
361+
if (!Term)
362+
return true;
363+
364+
// If the block has no successors, there can be no instructions to hoist.
365+
assert(Term->getNumSuccessors() > 0);
366+
367+
// Instructions should not be hoisted across exception handling boundaries.
368+
return !Term->isExceptional();
369+
}
370+
358371
/// This splits a basic block into two at the specified
359372
/// instruction. Note that all instructions BEFORE the specified iterator stay
360373
/// as part of the original basic block, an unconditional branch is added to
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
; RUN: opt < %s -loop-rotate -S | FileCheck %s
2+
3+
target triple = "x86_64-pc-windows-msvc"
4+
5+
declare void @always_throws()
6+
7+
define i32 @test() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
8+
entry:
9+
invoke void @always_throws()
10+
to label %continue unwind label %catch.dispatch
11+
12+
continue:
13+
unreachable
14+
15+
catch.dispatch:
16+
%t0 = catchswitch within none [label %catch] unwind to caller
17+
18+
catch:
19+
%t1 = catchpad within %t0 [i8* null, i32 64, i8* null]
20+
catchret from %t1 to label %for.cond
21+
22+
for.cond:
23+
%sum = phi i32 [ %add, %for.body ], [ 0, %catch ]
24+
%i = phi i32 [ %inc, %for.body ], [ 0, %catch ]
25+
%cmp = icmp slt i32 %i, 1
26+
br i1 %cmp, label %for.body, label %return
27+
28+
for.body:
29+
%add = add nsw i32 1, %sum
30+
%inc = add nsw i32 %i, 1
31+
br label %for.cond
32+
33+
return:
34+
ret i32 0
35+
}
36+
37+
; CHECK: catch:
38+
; CHECK-NEXT: catchpad
39+
; CHECK-NEXT: catchret
40+
41+
declare i32 @__CxxFrameHandler3(...)

0 commit comments

Comments
 (0)