Skip to content

Commit

Permalink
Add vasm dominator utility functions
Browse files Browse the repository at this point in the history
Summary:
Add vasm dominator utility functions. These are mainly copies of the
equivalent HHIR functions, but works on vasm.

Reviewed By: markw65

Differential Revision: D13285649

fbshipit-source-id: a41fef0e6e985b4055124a689d61f6209371aede
  • Loading branch information
ricklavoie authored and hhvm-bot committed Dec 2, 2018
1 parent 71dba2b commit bc68944
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 0 deletions.
65 changes: 65 additions & 0 deletions hphp/runtime/vm/jit/vasm-util.cpp
Expand Up @@ -18,6 +18,9 @@

#include "hphp/runtime/vm/jit/vasm-instr.h"
#include "hphp/runtime/vm/jit/vasm-unit.h"
#include "hphp/runtime/vm/jit/vasm-visit.h"

#include "hphp/util/dataflow-worklist.h"

namespace HPHP { namespace jit {

Expand Down Expand Up @@ -161,4 +164,66 @@ Vloc make_const(Vunit& unit, Type type) {

//////////////////////////////////////////////////////////////////////

bool dominates(Vlabel b1, Vlabel b2, const VIdomVector& idoms) {
assertx(b1.isValid() && b2.isValid());
for (auto b = b2; b.isValid(); b = idoms[b]) {
if (b == b1) return true;
}
return false;
}

VIdomVector findDominators(const Vunit& unit,
const jit::vector<Vlabel>& rpo) {
assertx(!rpo.empty() && rpo[0] == unit.entry);

auto const preds = computePreds(unit);
VIdomVector idom(unit.blocks.size());

jit::vector<size_t> rpoOrder(unit.blocks.size());
for (size_t i = 0; i < rpo.size(); ++i) rpoOrder[rpo[i]] = i;

dataflow_worklist<size_t> worklist(rpo.size());

idom[unit.entry] = unit.entry;
for (auto const succ : succs(unit.blocks[0])) {
worklist.push(rpoOrder[succ]);
}

while (!worklist.empty()) {
auto const block = rpo[worklist.pop()];
auto const& blockPreds = preds[block];

// Find the first already processed predecessor (there must be at least one
// because we shouldn't be on the worklist otherwise).
auto predIt = std::find_if(
blockPreds.begin(),
blockPreds.end(),
[&] (Vlabel p) { return idom[p].isValid(); }
);
assertx(predIt != blockPreds.end());
auto p1 = *predIt;

// For all other already processed predecessors
for (++predIt; predIt != blockPreds.end(); ++predIt) {
auto p2 = *predIt;
if (p2 == p1 || !idom[p2].isValid()) continue;
do {
// Find earliest common predecessor of p1 and p2
while (rpoOrder[p1] < rpoOrder[p2]) p2 = idom[p2];
while (rpoOrder[p2] < rpoOrder[p1]) p1 = idom[p1];
} while (p1 != p2);
}

if (!idom[block].isValid() || idom[block] != p1) {
idom[block] = p1;
for (auto const succ : succs(unit.blocks[block])) {
worklist.push(rpoOrder[succ]);
}
}
}

idom[unit.entry] = Vlabel{}; // entry has no dominator
return idom;
}

}}
16 changes: 16 additions & 0 deletions hphp/runtime/vm/jit/vasm-util.h
Expand Up @@ -39,6 +39,22 @@ bool is_trivial_nop(const Vinstr&);
*/
bool splitCriticalEdges(Vunit& unit);

///////////////////////////////////////////////////////////////////////////////

/*
* Compute a mapping of each (reachable) block in a Vunit to its immediate
* dominator, using the provided reverse post-order sort of the blocks.
*/
using VIdomVector = jit::vector<Vlabel>;
VIdomVector findDominators(const Vunit&, const jit::vector<Vlabel>& rpo);

/*
* Test if b1 dominates b2
*/
bool dominates(Vlabel b1, Vlabel b2, const VIdomVector&);

///////////////////////////////////////////////////////////////////////////////

/*
* Return a Vloc holding the constant value represented by the given Type.
*/
Expand Down

0 comments on commit bc68944

Please sign in to comment.