1
0
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:
Max Kazantsev 2018-07-30 07:07:32 +00:00
parent 06018234e8
commit 2a549dc9b1

View File

@ -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)