mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-29 14:40:25 +00:00
LICM may hoist an instruction with undefined behavior above a trap.
Scan the body of the loop and find instructions that may trap. Use this information when deciding if it is safe to hoist or sink instructions. Notice that we can optimize the search of instructions that may throw in the case of nested loops. rdar://11518836 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163132 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
68d92bdcc9
commit
7765492a7a
@ -108,6 +108,9 @@ namespace {
|
|||||||
BasicBlock *Preheader; // The preheader block of the current loop...
|
BasicBlock *Preheader; // The preheader block of the current loop...
|
||||||
Loop *CurLoop; // The current loop we are working on...
|
Loop *CurLoop; // The current loop we are working on...
|
||||||
AliasSetTracker *CurAST; // AliasSet information for the current loop...
|
AliasSetTracker *CurAST; // AliasSet information for the current loop...
|
||||||
|
bool MayThrow; // The current loop contains an instruction which
|
||||||
|
// may throw, thus preventing code motion of
|
||||||
|
// instructions with side effects.
|
||||||
DenseMap<Loop*, AliasSetTracker*> LoopToAliasSetMap;
|
DenseMap<Loop*, AliasSetTracker*> LoopToAliasSetMap;
|
||||||
|
|
||||||
/// cloneBasicBlockAnalysis - Simple Analysis hook. Clone alias set info.
|
/// cloneBasicBlockAnalysis - Simple Analysis hook. Clone alias set info.
|
||||||
@ -240,6 +243,15 @@ bool LICM::runOnLoop(Loop *L, LPPassManager &LPM) {
|
|||||||
CurAST->add(*BB); // Incorporate the specified basic block
|
CurAST->add(*BB); // Incorporate the specified basic block
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MayThrow = false;
|
||||||
|
// TODO: We've already searched for instructions which may throw in subloops.
|
||||||
|
// We may want to reuse this information.
|
||||||
|
for (Loop::block_iterator BB = L->block_begin(), BBE = L->block_end();
|
||||||
|
(BB != BBE) && !MayThrow ; ++BB)
|
||||||
|
for (BasicBlock::iterator I = (*BB)->begin(), E = (*BB)->end();
|
||||||
|
(I != E) && !MayThrow; ++I)
|
||||||
|
MayThrow |= I->mayThrow();
|
||||||
|
|
||||||
// We want to visit all of the instructions in this loop... that are not parts
|
// We want to visit all of the instructions in this loop... that are not parts
|
||||||
// of our subloops (they have already had their invariants hoisted out of
|
// of our subloops (they have already had their invariants hoisted out of
|
||||||
// their loop, into this loop, so there is no need to process the BODIES of
|
// their loop, into this loop, so there is no need to process the BODIES of
|
||||||
@ -418,17 +430,22 @@ bool LICM::canSinkOrHoistInst(Instruction &I) {
|
|||||||
if (!FoundMod) return true;
|
if (!FoundMod) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This should use mod/ref information to see if we can hoist or sink
|
// FIXME: This should use mod/ref information to see if we can hoist or
|
||||||
// the call.
|
// sink the call.
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise these instructions are hoistable/sinkable
|
// Only these instructions are hoistable/sinkable.
|
||||||
return isa<BinaryOperator>(I) || isa<CastInst>(I) ||
|
bool HoistableKind = (isa<BinaryOperator>(I) || isa<CastInst>(I) ||
|
||||||
isa<SelectInst>(I) || isa<GetElementPtrInst>(I) || isa<CmpInst>(I) ||
|
isa<SelectInst>(I) || isa<GetElementPtrInst>(I) ||
|
||||||
isa<InsertElementInst>(I) || isa<ExtractElementInst>(I) ||
|
isa<CmpInst>(I) || isa<InsertElementInst>(I) ||
|
||||||
isa<ShuffleVectorInst>(I);
|
isa<ExtractElementInst>(I) ||
|
||||||
|
isa<ShuffleVectorInst>(I));
|
||||||
|
if (!HoistableKind)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return isSafeToExecuteUnconditionally(I);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isNotUsedInLoop - Return true if the only users of this instruction are
|
/// isNotUsedInLoop - Return true if the only users of this instruction are
|
||||||
@ -604,6 +621,12 @@ bool LICM::isSafeToExecuteUnconditionally(Instruction &Inst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool LICM::isGuaranteedToExecute(Instruction &Inst) {
|
bool LICM::isGuaranteedToExecute(Instruction &Inst) {
|
||||||
|
|
||||||
|
// Somewhere in this loop there is an instruction which may throw and make us
|
||||||
|
// exit the loop.
|
||||||
|
if (MayThrow)
|
||||||
|
return false;
|
||||||
|
|
||||||
// Otherwise we have to check to make sure that the instruction dominates all
|
// Otherwise we have to check to make sure that the instruction dominates all
|
||||||
// of the exit blocks. If it doesn't, then there is a path out of the loop
|
// 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.
|
// which does not execute this instruction, so we can't hoist it.
|
||||||
|
@ -29,7 +29,7 @@ Out: ; preds = %LoopTail
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
declare void @foo2(i32)
|
declare void @foo2(i32) nounwind
|
||||||
|
|
||||||
|
|
||||||
;; It is ok and desirable to hoist this potentially trapping instruction.
|
;; It is ok and desirable to hoist this potentially trapping instruction.
|
||||||
@ -64,3 +64,29 @@ Out: ; preds = %Loop
|
|||||||
%C = sub i32 %A, %B ; <i32> [#uses=1]
|
%C = sub i32 %A, %B ; <i32> [#uses=1]
|
||||||
ret i32 %C
|
ret i32 %C
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; CHECK: @test4
|
||||||
|
; CHECK: call
|
||||||
|
; CHECK: sdiv
|
||||||
|
; CHECK: ret
|
||||||
|
define i32 @test4(i32 %x, i32 %y) nounwind uwtable ssp {
|
||||||
|
entry:
|
||||||
|
br label %for.body
|
||||||
|
|
||||||
|
for.body: ; preds = %entry, %for.body
|
||||||
|
%i.02 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
|
||||||
|
%n.01 = phi i32 [ 0, %entry ], [ %add, %for.body ]
|
||||||
|
call void @foo_may_call_exit(i32 0)
|
||||||
|
%div = sdiv i32 %x, %y
|
||||||
|
%add = add nsw i32 %n.01, %div
|
||||||
|
%inc = add nsw i32 %i.02, 1
|
||||||
|
%cmp = icmp slt i32 %inc, 10000
|
||||||
|
br i1 %cmp, label %for.body, label %for.end
|
||||||
|
|
||||||
|
for.end: ; preds = %for.body
|
||||||
|
%n.0.lcssa = phi i32 [ %add, %for.body ]
|
||||||
|
ret i32 %n.0.lcssa
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @foo_may_call_exit(i32)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user