mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
[NFC] Prepare GuardWidening for widening of cond branches
llvm-svn: 338229
This commit is contained in:
parent
06018234e8
commit
2a549dc9b1
@ -75,21 +75,33 @@ class GuardWideningImpl {
|
|||||||
|
|
||||||
/// The set of guards whose conditions have been widened into dominating
|
/// The set of guards whose conditions have been widened into dominating
|
||||||
/// guards.
|
/// guards.
|
||||||
SmallVector<IntrinsicInst *, 16> EliminatedGuards;
|
SmallVector<Instruction *, 16> EliminatedGuards;
|
||||||
|
|
||||||
/// The set of guards which have been widened to include conditions to other
|
/// The set of guards which have been widened to include conditions to other
|
||||||
/// guards.
|
/// guards.
|
||||||
DenseSet<IntrinsicInst *> WidenedGuards;
|
DenseSet<Instruction *> WidenedGuards;
|
||||||
|
|
||||||
/// Try to eliminate guard \p Guard by widening it into an earlier dominating
|
/// Try to eliminate guard \p Guard by widening it into an earlier dominating
|
||||||
/// guard. \p DFSI is the DFS iterator on the dominator tree that is
|
/// guard. \p DFSI is the DFS iterator on the dominator tree that is
|
||||||
/// currently visiting the block containing \p Guard, and \p GuardsPerBlock
|
/// currently visiting the block containing \p Guard, and \p GuardsPerBlock
|
||||||
/// maps BasicBlocks to the set of guards seen in that block.
|
/// maps BasicBlocks to the set of guards seen in that block.
|
||||||
bool eliminateGuardViaWidening(
|
bool eliminateGuardViaWidening(
|
||||||
IntrinsicInst *Guard, const df_iterator<DomTreeNode *> &DFSI,
|
Instruction *Guard, const df_iterator<DomTreeNode *> &DFSI,
|
||||||
const DenseMap<BasicBlock *, SmallVector<IntrinsicInst *, 8>> &
|
const DenseMap<BasicBlock *, SmallVector<Instruction *, 8>> &
|
||||||
GuardsPerBlock);
|
GuardsPerBlock);
|
||||||
|
|
||||||
|
// Get the condition from \p GuardInst.
|
||||||
|
Value *getGuardCondition(Instruction *GuardInst);
|
||||||
|
|
||||||
|
// Set the condition for \p GuardInst.
|
||||||
|
void setGuardCondition(Instruction *GuardInst, Value *NewCond);
|
||||||
|
|
||||||
|
// Whether or not the particular instruction is a guard.
|
||||||
|
bool isGuard(const Instruction *I);
|
||||||
|
|
||||||
|
// Eliminates the guard instruction properly.
|
||||||
|
void eliminateGuard(Instruction *GuardInst);
|
||||||
|
|
||||||
/// Used to keep track of which widening potential is more effective.
|
/// Used to keep track of which widening potential is more effective.
|
||||||
enum WideningScore {
|
enum WideningScore {
|
||||||
/// Don't widen.
|
/// Don't widen.
|
||||||
@ -113,9 +125,9 @@ class GuardWideningImpl {
|
|||||||
/// Compute the score for widening the condition in \p DominatedGuard
|
/// Compute the score for widening the condition in \p DominatedGuard
|
||||||
/// (contained in \p DominatedGuardLoop) into \p DominatingGuard (contained in
|
/// (contained in \p DominatedGuardLoop) into \p DominatingGuard (contained in
|
||||||
/// \p DominatingGuardLoop).
|
/// \p DominatingGuardLoop).
|
||||||
WideningScore computeWideningScore(IntrinsicInst *DominatedGuard,
|
WideningScore computeWideningScore(Instruction *DominatedGuard,
|
||||||
Loop *DominatedGuardLoop,
|
Loop *DominatedGuardLoop,
|
||||||
IntrinsicInst *DominatingGuard,
|
Instruction *DominatingGuard,
|
||||||
Loop *DominatingGuardLoop);
|
Loop *DominatingGuardLoop);
|
||||||
|
|
||||||
/// Helper to check if \p V can be hoisted to \p InsertPos.
|
/// Helper to check if \p V can be hoisted to \p InsertPos.
|
||||||
@ -206,10 +218,10 @@ class GuardWideningImpl {
|
|||||||
|
|
||||||
/// Widen \p ToWiden to fail if \p NewCondition is false (in addition to
|
/// Widen \p ToWiden to fail if \p NewCondition is false (in addition to
|
||||||
/// whatever it is already checking).
|
/// whatever it is already checking).
|
||||||
void widenGuard(IntrinsicInst *ToWiden, Value *NewCondition) {
|
void widenGuard(Instruction *ToWiden, Value *NewCondition) {
|
||||||
Value *Result;
|
Value *Result;
|
||||||
widenCondCommon(ToWiden->getArgOperand(0), NewCondition, ToWiden, Result);
|
widenCondCommon(ToWiden->getOperand(0), NewCondition, ToWiden, Result);
|
||||||
ToWiden->setArgOperand(0, Result);
|
setGuardCondition(ToWiden, Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -225,9 +237,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool GuardWideningImpl::run() {
|
bool GuardWideningImpl::run() {
|
||||||
using namespace llvm::PatternMatch;
|
DenseMap<BasicBlock *, SmallVector<Instruction *, 8>> GuardsInBlock;
|
||||||
|
|
||||||
DenseMap<BasicBlock *, SmallVector<IntrinsicInst *, 8>> GuardsInBlock;
|
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
|
|
||||||
for (auto DFI = df_begin(Root), DFE = df_end(Root);
|
for (auto DFI = df_begin(Root), DFE = df_end(Root);
|
||||||
@ -239,8 +249,8 @@ bool GuardWideningImpl::run() {
|
|||||||
auto &CurrentList = GuardsInBlock[BB];
|
auto &CurrentList = GuardsInBlock[BB];
|
||||||
|
|
||||||
for (auto &I : *BB)
|
for (auto &I : *BB)
|
||||||
if (match(&I, m_Intrinsic<Intrinsic::experimental_guard>()))
|
if (isGuard(&I))
|
||||||
CurrentList.push_back(cast<IntrinsicInst>(&I));
|
CurrentList.push_back(cast<Instruction>(&I));
|
||||||
|
|
||||||
for (auto *II : CurrentList)
|
for (auto *II : CurrentList)
|
||||||
Changed |= eliminateGuardViaWidening(II, DFI, GuardsInBlock);
|
Changed |= eliminateGuardViaWidening(II, DFI, GuardsInBlock);
|
||||||
@ -249,16 +259,16 @@ bool GuardWideningImpl::run() {
|
|||||||
assert(EliminatedGuards.empty() || Changed);
|
assert(EliminatedGuards.empty() || Changed);
|
||||||
for (auto *II : EliminatedGuards)
|
for (auto *II : EliminatedGuards)
|
||||||
if (!WidenedGuards.count(II))
|
if (!WidenedGuards.count(II))
|
||||||
II->eraseFromParent();
|
eliminateGuard(II);
|
||||||
|
|
||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GuardWideningImpl::eliminateGuardViaWidening(
|
bool GuardWideningImpl::eliminateGuardViaWidening(
|
||||||
IntrinsicInst *GuardInst, const df_iterator<DomTreeNode *> &DFSI,
|
Instruction *GuardInst, const df_iterator<DomTreeNode *> &DFSI,
|
||||||
const DenseMap<BasicBlock *, SmallVector<IntrinsicInst *, 8>> &
|
const DenseMap<BasicBlock *, SmallVector<Instruction *, 8>> &
|
||||||
GuardsInBlock) {
|
GuardsInBlock) {
|
||||||
IntrinsicInst *BestSoFar = nullptr;
|
Instruction *BestSoFar = nullptr;
|
||||||
auto BestScoreSoFar = WS_IllegalOrNegative;
|
auto BestScoreSoFar = WS_IllegalOrNegative;
|
||||||
auto *GuardInstLoop = LI.getLoopFor(GuardInst->getParent());
|
auto *GuardInstLoop = LI.getLoopFor(GuardInst->getParent());
|
||||||
|
|
||||||
@ -302,8 +312,8 @@ bool GuardWideningImpl::eliminateGuardViaWidening(
|
|||||||
for (auto *Candidate : make_range(I, E)) {
|
for (auto *Candidate : make_range(I, E)) {
|
||||||
auto Score =
|
auto Score =
|
||||||
computeWideningScore(GuardInst, GuardInstLoop, Candidate, CurLoop);
|
computeWideningScore(GuardInst, GuardInstLoop, Candidate, CurLoop);
|
||||||
LLVM_DEBUG(dbgs() << "Score between " << *GuardInst->getArgOperand(0)
|
LLVM_DEBUG(dbgs() << "Score between " << *getGuardCondition(GuardInst)
|
||||||
<< " and " << *Candidate->getArgOperand(0) << " is "
|
<< " and " << *getGuardCondition(Candidate) << " is "
|
||||||
<< scoreTypeToString(Score) << "\n");
|
<< scoreTypeToString(Score) << "\n");
|
||||||
if (Score > BestScoreSoFar) {
|
if (Score > BestScoreSoFar) {
|
||||||
BestScoreSoFar = Score;
|
BestScoreSoFar = Score;
|
||||||
@ -323,16 +333,40 @@ bool GuardWideningImpl::eliminateGuardViaWidening(
|
|||||||
LLVM_DEBUG(dbgs() << "Widening " << *GuardInst << " into " << *BestSoFar
|
LLVM_DEBUG(dbgs() << "Widening " << *GuardInst << " into " << *BestSoFar
|
||||||
<< " with score " << scoreTypeToString(BestScoreSoFar)
|
<< " with score " << scoreTypeToString(BestScoreSoFar)
|
||||||
<< "\n");
|
<< "\n");
|
||||||
widenGuard(BestSoFar, GuardInst->getArgOperand(0));
|
widenGuard(BestSoFar, getGuardCondition(GuardInst));
|
||||||
GuardInst->setArgOperand(0, ConstantInt::getTrue(GuardInst->getContext()));
|
setGuardCondition(GuardInst, ConstantInt::getTrue(GuardInst->getContext()));
|
||||||
EliminatedGuards.push_back(GuardInst);
|
EliminatedGuards.push_back(GuardInst);
|
||||||
WidenedGuards.insert(BestSoFar);
|
WidenedGuards.insert(BestSoFar);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value *GuardWideningImpl::getGuardCondition(Instruction *GuardInst) {
|
||||||
|
IntrinsicInst *GI = cast<IntrinsicInst>(GuardInst);
|
||||||
|
assert(GI->getIntrinsicID() == Intrinsic::experimental_guard &&
|
||||||
|
"Bad guard intrinsic?");
|
||||||
|
return GI->getArgOperand(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuardWideningImpl::setGuardCondition(Instruction *GuardInst,
|
||||||
|
Value *NewCond) {
|
||||||
|
IntrinsicInst *GI = cast<IntrinsicInst>(GuardInst);
|
||||||
|
assert(GI->getIntrinsicID() == Intrinsic::experimental_guard &&
|
||||||
|
"Bad guard intrinsic?");
|
||||||
|
GI->setArgOperand(0, NewCond);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GuardWideningImpl::isGuard(const Instruction* I) {
|
||||||
|
using namespace llvm::PatternMatch;
|
||||||
|
return match(I, m_Intrinsic<Intrinsic::experimental_guard>());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuardWideningImpl::eliminateGuard(Instruction *GuardInst) {
|
||||||
|
GuardInst->eraseFromParent();
|
||||||
|
}
|
||||||
|
|
||||||
GuardWideningImpl::WideningScore GuardWideningImpl::computeWideningScore(
|
GuardWideningImpl::WideningScore GuardWideningImpl::computeWideningScore(
|
||||||
IntrinsicInst *DominatedGuard, Loop *DominatedGuardLoop,
|
Instruction *DominatedGuard, Loop *DominatedGuardLoop,
|
||||||
IntrinsicInst *DominatingGuard, Loop *DominatingGuardLoop) {
|
Instruction *DominatingGuard, Loop *DominatingGuardLoop) {
|
||||||
bool HoistingOutOfLoop = false;
|
bool HoistingOutOfLoop = false;
|
||||||
|
|
||||||
if (DominatingGuardLoop != DominatedGuardLoop) {
|
if (DominatingGuardLoop != DominatedGuardLoop) {
|
||||||
@ -345,7 +379,7 @@ GuardWideningImpl::WideningScore GuardWideningImpl::computeWideningScore(
|
|||||||
HoistingOutOfLoop = true;
|
HoistingOutOfLoop = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isAvailableAt(DominatedGuard->getArgOperand(0), DominatingGuard))
|
if (!isAvailableAt(getGuardCondition(DominatedGuard), DominatingGuard))
|
||||||
return WS_IllegalOrNegative;
|
return WS_IllegalOrNegative;
|
||||||
|
|
||||||
// If the guard was conditional executed, it may never be reached
|
// If the guard was conditional executed, it may never be reached
|
||||||
@ -356,8 +390,8 @@ GuardWideningImpl::WideningScore GuardWideningImpl::computeWideningScore(
|
|||||||
// here. TODO: evaluate cost model for spurious deopt
|
// here. TODO: evaluate cost model for spurious deopt
|
||||||
// NOTE: As written, this also lets us hoist right over another guard which
|
// NOTE: As written, this also lets us hoist right over another guard which
|
||||||
// is essentially just another spelling for control flow.
|
// is essentially just another spelling for control flow.
|
||||||
if (isWideningCondProfitable(DominatedGuard->getArgOperand(0),
|
if (isWideningCondProfitable(getGuardCondition(DominatedGuard),
|
||||||
DominatingGuard->getArgOperand(0)))
|
getGuardCondition(DominatingGuard)))
|
||||||
return HoistingOutOfLoop ? WS_VeryPositive : WS_Positive;
|
return HoistingOutOfLoop ? WS_VeryPositive : WS_Positive;
|
||||||
|
|
||||||
if (HoistingOutOfLoop)
|
if (HoistingOutOfLoop)
|
||||||
|
Loading…
Reference in New Issue
Block a user