rose: allow ghosts to be aliased

This commit is contained in:
Justin Viiret 2016-06-20 10:17:38 +10:00 committed by Matthew Barr
parent e915ca21c5
commit 0749f7c06d

View File

@ -348,8 +348,45 @@ bool isAliasingCandidate(RoseVertex v, const RoseBuildImpl &tbi) {
} }
assert(*props.literals.begin() != MO_INVALID_IDX); assert(*props.literals.begin() != MO_INVALID_IDX);
return true;
}
// Any vertex involved in a "ghost" relationship has already been disallowed static
bool sameGhostProperties(const RoseBuildImpl &build, RoseVertex a,
RoseVertex b) {
// If these are ghost mapping keys, then they must map to the same vertex.
if (contains(build.ghost, a) || contains(build.ghost, b)) {
DEBUG_PRINTF("checking ghost key compat\n");
if (!contains(build.ghost, a) || !contains(build.ghost, b)) {
DEBUG_PRINTF("missing ghost mapping\n");
return false;
}
if (build.ghost.at(a) != build.ghost.at(b)) {
DEBUG_PRINTF("diff ghost mapping\n");
return false;
}
DEBUG_PRINTF("ghost mappings ok\n");
return true;
}
// If they are ghost vertices, then they must have the same literals.
// FIXME: get rid of linear scan
vector<RoseVertex> ghost_a, ghost_b;
for (const auto &e : build.ghost) {
if (e.second == a) {
ghost_a.push_back(e.first);
}
if (e.second == b) {
ghost_b.push_back(e.first);
}
}
if (!ghost_a.empty() || !ghost_a.empty()) {
DEBUG_PRINTF("ghost map targets\n");
if (build.g[a].literals != build.g[b].literals) {
DEBUG_PRINTF("diff literals\n");
return false;
}
}
return true; return true;
} }
@ -380,6 +417,10 @@ bool sameRoleProperties(const RoseBuildImpl &build, RoseVertex a, RoseVertex b)
return false; return false;
} }
if (!sameGhostProperties(build, a, b)) {
return false;
}
/* "roses are mergeable" check are handled elsewhere */ /* "roses are mergeable" check are handled elsewhere */
return true; return true;
@ -536,6 +577,28 @@ void mergeLiteralSets(RoseVertex a, RoseVertex b, RoseBuildImpl &tbi) {
insert(&g[b].literals, a_literals); insert(&g[b].literals, a_literals);
} }
static
void updateGhostMap(RoseBuildImpl &build, RoseVertex a, RoseVertex b) {
// Ghost keys.
if (contains(build.ghost, a)) {
auto it = build.ghost.find(a);
assert(it->second == build.ghost[b]);
build.ghost.erase(it);
}
// Ghost values. FIXME: this will be slow at scale.
vector<RoseVertex> ghost_refs;
for (const auto &e : build.ghost) {
if (e.second == a) {
ghost_refs.push_back(e.first);
}
}
for (const auto &v : ghost_refs) {
build.ghost.erase(v);
build.ghost.emplace(v, b);
}
}
// Merge role 'a' into 'b'. // Merge role 'a' into 'b'.
static static
void mergeVertices(RoseVertex a, RoseVertex b, RoseBuildImpl &tbi, void mergeVertices(RoseVertex a, RoseVertex b, RoseBuildImpl &tbi,
@ -566,6 +629,9 @@ void mergeVertices(RoseVertex a, RoseVertex b, RoseBuildImpl &tbi,
} }
mergeEdges(a, b, g); mergeEdges(a, b, g);
updateGhostMap(tbi, a, b);
removeVertexFromMaps(a, tbi, rrm); removeVertexFromMaps(a, tbi, rrm);
} }
@ -600,21 +666,7 @@ void mergeVerticesDiamond(RoseVertex a, RoseVertex b, RoseBuildImpl &tbi,
static never_inline static never_inline
void findCandidates(const RoseBuildImpl &tbi, CandidateSet *candidates) { void findCandidates(const RoseBuildImpl &tbi, CandidateSet *candidates) {
ue2::unordered_set<RoseVertex> disallowed;
// We currently deny candidature to any vertex involved in a "ghost"
// relationship.
for (const auto &m : tbi.ghost) {
disallowed.insert(m.first);
disallowed.insert(m.second);
}
for (auto v : vertices_range(tbi.g)) { for (auto v : vertices_range(tbi.g)) {
// Ignore ghost relationships.
if (contains(disallowed, v)) {
continue;
}
if (isAliasingCandidate(v, tbi)) { if (isAliasingCandidate(v, tbi)) {
DEBUG_PRINTF("candidate %zu\n", tbi.g[v].idx); DEBUG_PRINTF("candidate %zu\n", tbi.g[v].idx);
DEBUG_PRINTF("lits: %u\n", *tbi.g[v].literals.begin()); DEBUG_PRINTF("lits: %u\n", *tbi.g[v].literals.begin());