Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/coreclr/jit/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -1545,11 +1545,18 @@ struct BasicBlock : private LIR::Range
void* bbSparseProbeList; // Used early on by fgInstrument
};

void* bbSparseCountInfo; // Used early on by fgIncorporateEdgeCounts
union
{
void* bbSparseCountInfo; // Used early on by fgIncorporateEdgeCounts
BasicBlock* bbIPDom; // closest postdominator of block
};

unsigned bbPreorderNum; // the block's preorder number in the graph [0...postOrderCount)
unsigned bbPostorderNum; // the block's postorder number in the graph [0...postOrderCount)

unsigned bbReversePreorderNum; // the block's preorder number in the reverse graph [0...postOrderCount)
unsigned bbReversePostorderNum; // the block's postorder number in the reverse graph [0...postOrderCount)

IL_OFFSET bbCodeOffs; // IL offset of the beginning of the block
IL_OFFSET bbCodeOffsEnd; // IL offset past the end of the block. Thus, the [bbCodeOffs..bbCodeOffsEnd)
// range is not inclusive of the end offset. The count of IL bytes in the block
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5136,6 +5136,8 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
DoPhase(this, PHASE_OPTIMIZE_INDEX_CHECKS, &Compiler::rangeCheckPhase);
}

DoPhase(this, PHASE_AGGRESSIVE_SSA_DCE, &Compiler::fgSsaBasedDce);

if (doOptimizeIVs)
{
// Simplify and optimize induction variables used in natural loops
Expand Down
151 changes: 144 additions & 7 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -1969,6 +1969,69 @@ class FlowGraphDfsTree
bool IsAncestor(BasicBlock* ancestor, BasicBlock* descendant) const;
};

// Represents a depth-first search tree of the reversed flow graph.
class FlowGraphReverseDfsTree
{
Compiler* m_comp;

// Post-order that we saw reverse reachable basic blocks in. This order can be
// particularly useful to iterate in reverse, as reverse post-order ensures
// that all predecessors are visited before successors whenever possible.
BasicBlock** m_postOrder;
unsigned m_postOrderCount;

// Pseudo exit representing the block that post-dominates all blocks
BasicBlock* m_pseudoExit;

public:
FlowGraphReverseDfsTree(Compiler* comp, BasicBlock** postOrder, unsigned postOrderCount, BasicBlock* pseudoExit)
: m_comp(comp)
, m_postOrder(postOrder)
, m_postOrderCount(postOrderCount)
, m_pseudoExit(pseudoExit)
{
}

Compiler* GetCompiler() const
{
return m_comp;
}

BasicBlock** GetPostOrder() const
{
return m_postOrder;
}

unsigned GetPostOrderCount() const
{
return m_postOrderCount;
}

BasicBlock* GetPostOrder(unsigned index) const
{
assert(index < m_postOrderCount);
return m_postOrder[index];
}

BitVecTraits PostOrderTraits() const
{
return BitVecTraits(m_postOrderCount, m_comp);
}

BasicBlock* PseudoExit() const
{
return m_pseudoExit;
}

#ifdef DEBUG
void Dump() const;
#endif // DEBUG

bool Contains(BasicBlock* block) const;
bool IsAncestor(BasicBlock* ancestor, BasicBlock* descendant) const;
};


// Represents the result of induction variable analysis. See
// FlowGraphNaturalLoop::AnalyzeIteration.
struct NaturalLoopIterInfo
Expand Down Expand Up @@ -2338,7 +2401,7 @@ class FlowGraphNaturalLoops
// Represents the dominator tree of the flow graph.
class FlowGraphDominatorTree
{
template<typename TVisitor>
template<typename TVisitor, bool postDom>
friend class DomTreeVisitor;

const FlowGraphDfsTree* m_dfsTree;
Expand Down Expand Up @@ -2372,6 +2435,43 @@ class FlowGraphDominatorTree
static FlowGraphDominatorTree* Build(const FlowGraphDfsTree* dfsTree);
};

// Represents the postdominator tree of the flow graph.
class FlowGraphPostDominatorTree
{
template<typename TVisitor, bool postDom>
friend class DomTreeVisitor;

const FlowGraphReverseDfsTree* m_reverseDfsTree;
const DomTreeNode* m_domTree;
const unsigned* m_preorderNum;
const unsigned* m_postorderNum;

FlowGraphPostDominatorTree(const FlowGraphReverseDfsTree* reverseDfsTree, const DomTreeNode* domTree, const unsigned* preorderNum, const unsigned* postorderNum)
: m_reverseDfsTree(reverseDfsTree)
, m_domTree(domTree)
, m_preorderNum(preorderNum)
, m_postorderNum(postorderNum)
{
}

static BasicBlock* IntersectPostdom(BasicBlock* block1, BasicBlock* block2);

public:
const FlowGraphReverseDfsTree* GetReverseDfsTree()
{
return m_reverseDfsTree;
}

BasicBlock* Intersect(BasicBlock* block, BasicBlock* block2);
bool PostDominates(BasicBlock* dominator, BasicBlock* dominated);

#ifdef DEBUG
void Dump();
#endif

static FlowGraphPostDominatorTree* Build(const FlowGraphReverseDfsTree* dfsTree);
};

// Represents a reverse mapping from block back to its (most nested) containing loop.
class BlockToNaturalLoopMap
{
Expand Down Expand Up @@ -2417,6 +2517,23 @@ class BlockReachabilitySets

bool CanReach(BasicBlock* from, BasicBlock* to);

template <typename TFunc>
void VisitReachingBlocks(BasicBlock* block, TFunc func)
{
if (!m_dfsTree->Contains(block))
{
return;
}

BitVecTraits traits = m_dfsTree->PostOrderTraits();
BitVecOps::Iter iter(&traits, m_reachabilitySets[block->bbPostorderNum]);
unsigned poNum;
while (iter.NextElem(&poNum))
{
func(m_dfsTree->GetPostOrder(poNum));
}
}

#ifdef DEBUG
void Dump();
#endif
Expand Down Expand Up @@ -2520,6 +2637,8 @@ struct RelopImplicationInfo
bool reverseSense = false;
};

typedef JitHashTable<GenTree*, JitPtrKeyFuncs<GenTree>, bool> TreeSet;

/*
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Expand Down Expand Up @@ -5114,6 +5233,7 @@ class Compiler
BasicBlock** fgBBReversePostorder; // Blocks in reverse postorder

FlowGraphDfsTree* m_dfsTree;
FlowGraphReverseDfsTree* m_reverseDfsTree;
// The next members are annotations on the flow graph used during the
// optimization phases. They are invalidated once RBO runs and modifies the
// flow graph.
Expand All @@ -5125,6 +5245,10 @@ class Compiler
FlowGraphDominatorTree* m_domTree;
BlockReachabilitySets* m_reachabilitySets;

// Postdominator tree
FlowGraphPostDominatorTree* m_postDomTree;
BlkToBlkVectorMap* m_postDomFrontiers;

// Do we require loops to be in canonical form? The canonical form ensures that:
// 1. All loops have preheaders (single entry blocks that always enter the loop)
// 2. All loop exits where bbIsHandlerBeg(exit) is false have only loop predecessors.
Expand Down Expand Up @@ -5504,6 +5628,9 @@ class Compiler
void fgPerNodeLocalVarLiveness(GenTree* node);
void fgPerBlockLocalVarLiveness();

bool fgIsPreLive(GenTree* tree);
PhaseStatus fgSsaBasedDce();

#if defined(FEATURE_HW_INTRINSICS)
void fgPerNodeLocalVarLiveness(GenTreeHWIntrinsic* hwintrinsic);
#endif // FEATURE_HW_INTRINSICS
Expand Down Expand Up @@ -5900,6 +6027,8 @@ class Compiler
bool fgRemoveUnreachableBlocks(CanRemoveBlockBody canRemoveBlock);

PhaseStatus fgComputeDominators(); // Compute dominators
PhaseStatus fgComputePostDominators(); // Compute postdominators
void fgComputePostDominanceFrontiers();

bool fgRemoveDeadBlocks(); // Identify and remove dead blocks.

Expand Down Expand Up @@ -6164,6 +6293,12 @@ class Compiler
FlowGraphDfsTree* fgComputeDfs();
void fgInvalidateDfsTree();

template <typename VisitPreorder, typename VisitPostorder>
unsigned fgRunReverseDfs(VisitPreorder assignPreorder, VisitPostorder assignPostorder, BasicBlock* pseudoExit);

FlowGraphReverseDfsTree* fgComputeReverseDfs();
void fgInvalidateReverseDfsTree();

void fgRemoveReturnBlock(BasicBlock* block);

void fgConvertBBToThrowBB(BasicBlock* block);
Expand Down Expand Up @@ -11841,10 +11976,11 @@ class GenericTreeWalker final
};

// A dominator tree visitor implemented using the curiously-recurring-template pattern, similar to GenTreeVisitor.
template <typename TVisitor>
template <typename TVisitor, bool postDom>
class DomTreeVisitor
{
friend class FlowGraphDominatorTree;
friend class FlowGraphPostDominatorTree;

protected:
Compiler* m_compiler;
Expand Down Expand Up @@ -11879,27 +12015,28 @@ class DomTreeVisitor
{
static_cast<TVisitor*>(this)->PreOrderVisit(block);

next = tree[block->bbPostorderNum].firstChild;
next = tree[postDom ? block->bbReversePostorderNum : block->bbPostorderNum].firstChild;

if (next != nullptr)
{
assert(next->bbIDom == block);
assert((!postDom && (next->bbIDom == block)) || (postDom && (next->bbIPDom == block)));
continue;
}

do
{
static_cast<TVisitor*>(this)->PostOrderVisit(block);

next = tree[block->bbPostorderNum].nextSibling;
next = tree[postDom ? block->bbReversePostorderNum : block->bbPostorderNum].nextSibling;

if (next != nullptr)
{
assert(next->bbIDom == block->bbIDom);
assert((!postDom && (next->bbIDom == block->bbIDom)) ||
(postDom && (next->bbIPDom == block->bbIPDom)));
break;
}

block = block->bbIDom;
block = postDom ? block->bbIPDom : block->bbIDom;

} while (block != nullptr);
}
Expand Down
Loading