/** * test the difference methods */ void ScopeSetTest::testDifference() { ScopeSet scopes1("one,two,three"); ScopeSet scopes2("two,three"); ScopeSet scopes3("one,four"); ScopeSet scopes4("four,five,six"); ScopeSet difference = scopes1.Difference(scopes2); OLA_ASSERT_EQ(1u, difference.size()); OLA_ASSERT_EQ(string("one"), difference.ToString()); difference = scopes2.Difference(scopes1); OLA_ASSERT_TRUE(difference.empty()); OLA_ASSERT_EQ(0u, difference.size()); OLA_ASSERT_EQ(string(""), difference.ToString()); // difference update ScopeSet removed = scopes4.DifferenceUpdate(scopes3); OLA_ASSERT_FALSE(removed.empty()); OLA_ASSERT_EQ(1u, removed.size()); OLA_ASSERT_EQ(string("four"), removed.ToString()); OLA_ASSERT_FALSE(scopes4.empty()); OLA_ASSERT_EQ(2u, scopes4.size()); OLA_ASSERT_EQ(string("five,six"), scopes4.ToString()); }
/** * Test that the intersection methods works */ void ScopeSetTest::testIntersection() { ScopeSet scopes1("one,two"); ScopeSet scopes2("two,three"); ScopeSet scopes3("three,four"); // test Intersects OLA_ASSERT_TRUE(scopes1.Intersects(scopes2)); OLA_ASSERT_TRUE(scopes2.Intersects(scopes3)); OLA_ASSERT_FALSE(scopes1.Intersects(scopes3)); // test Intersection ScopeSet intersection = scopes1.Intersection(scopes2); OLA_ASSERT_EQ(1u, intersection.size()); OLA_ASSERT_EQ(string("two"), intersection.ToString()); intersection = scopes2.Intersection(scopes3); OLA_ASSERT_EQ(1u, intersection.size()); OLA_ASSERT_EQ(string("three"), intersection.ToString()); intersection = scopes1.Intersection(scopes3); OLA_ASSERT_TRUE(intersection.empty()); // test IntersectionCount OLA_ASSERT_EQ(1u, scopes1.IntersectionCount(scopes2)); OLA_ASSERT_EQ(1u, scopes2.IntersectionCount(scopes3)); OLA_ASSERT_EQ(0u, scopes1.IntersectionCount(scopes3)); }
inline bool findScopeUsages(Statement * stmt, ScopeSet & scopeSet, const PabloBlock * const block, const PabloBlock * const blocker) { for (PabloAST * use : stmt->users()) { assert (isa<Statement>(use)); PabloBlock * const parent = cast<Statement>(use)->getParent(); if (LLVM_LIKELY(parent == block)) { return false; } if (parent != blocker) { scopeSet.insert(parent); } } return true; }
/** ------------------------------------------------------------------------------------------------------------- * * @brief sink ** ------------------------------------------------------------------------------------------------------------- */ inline void CodeMotionPass::sink(PabloBlock * const block) { ScopeSet scopes; Statement * stmt = block->back(); // note: reverse AST traversal while (stmt) { Statement * prevNode = stmt->getPrevNode(); if (isAcceptableTarget(stmt, scopes, block)) { assert (scopes.size() > 0); while (scopes.size() > 1) { // Find the LCA of both scopes then add the LCA back to the list of scopes. PabloBlock * scope1 = scopes.back(); scopes.pop_back(); unsigned depth1 = depthTo(scope1, block); PabloBlock * scope2 = scopes.back(); scopes.pop_back(); unsigned depth2 = depthTo(scope2, block); // If one of these scopes is nested deeper than the other, scan upwards through // the scope tree until both scopes are at the same depth. while (depth1 > depth2) { scope1 = scope1->getParent(); --depth1; } while (depth1 < depth2) { scope2 = scope2->getParent(); --depth2; } // Then iteratively step backwards until we find a matching set of scopes; this // must be the LCA of our original scopes. while (scope1 != scope2) { assert (scope1 && scope2); scope1 = scope1->getParent(); scope2 = scope2->getParent(); } assert (scope1); // But if the LCA is the current block, we can't sink the statement. if (scope1 == block) { goto abort; } scopes.push_back(scope1); } assert (scopes.size() == 1); assert (isa<If>(stmt) ? (cast<If>(stmt)->getBody() != scopes.front()) : true); assert (isa<While>(stmt) ? (cast<While>(stmt)->getBody() != scopes.front()) : true); stmt->insertBefore(scopes.front()->front()); } abort: scopes.clear(); stmt = prevNode; } }