void RecursiveClauses::run(const AstTranslationUnit& translationUnit) { visitDepthFirst(*translationUnit.getProgram(), [&](const AstClause& clause) { if (computeIsRecursive(clause, translationUnit)) { recursiveClauses.insert(&clause); } }); }
void ResolveAliasesTransformer::resolveAliases(AstProgram &program) { // get all clauses std::vector<const AstClause*> clauses; visitDepthFirst(program, [&](const AstRelation& rel){ for(const auto& cur : rel.getClauses()) { clauses.push_back(cur); } }); // clean all clauses for(const AstClause* cur : clauses) { // -- Step 1 -- // get rid of aliases std::unique_ptr<AstClause> noAlias = resolveAliases(*cur); // clean up equalities std::unique_ptr<AstClause> cleaned = removeTrivialEquality(*noAlias); // -- Step 2 -- // restore simple terms in atoms removeComplexTermsInAtoms(*cleaned); // exchange rule program.removeClause(cur); program.appendClause(std::move(cleaned)); } }
bool AstClause::isFact() const { // there must be a head if (head == nullptr) { return false; } // there must not be any body clauses if (getBodySize() != 0) { return false; } // and there are no aggregates bool hasAggregates = false; visitDepthFirst(*head, [&](const AstAggregator& cur) { hasAggregates = true; }); return !hasAggregates; }
void ComponentLookup::run(const AstTranslationUnit& translationUnit) { const AstProgram *program = translationUnit.getProgram(); for (AstComponent *component : program->getComponents()) { globalScopeComponents.insert(component); enclosingComponent[component] = nullptr; } visitDepthFirst(*program, [&](const AstComponent& cur) { nestedComponents[&cur]; for (AstComponent *nestedComponent : cur.getComponents()) { nestedComponents[&cur].insert(nestedComponent); enclosingComponent[nestedComponent] = &cur; } }); }
IRStatistic IRStatistic::evaluate(const NodePtr& node) { IRStatistic res; // count number of shared nodes ... visitDepthFirstOnce(node, makeLambdaVisitor([&res](const NodePtr& ptr) { res.numSharedNodes++; res.nodeTypeInfo[ptr->getNodeType()].numShared++; }, true)); // ... and addressable nodes visitDepthFirst(node, makeLambdaVisitor([&res](const NodePtr& ptr) { res.numAddressableNodes++; res.nodeTypeInfo[ptr->getNodeType()].numAddressable++; }, true)); // ... and height (lightweight) res.height = evalHeight(node); // build result return res; }
bool AutoScheduleTransformer::autotune(AstTranslationUnit& translationUnit, std::ostream* report) { const QueryExecutionStrategy& strategy = ScheduledExecution; bool verbose = Global::config().has("verbose"); // start with status message if (verbose) { std::cout << "\n"; } if (verbose) { std::cout << "----------------- Auto-Scheduling Started -----------------\n"; } // step 1 - translate to RAM program if (verbose) { std::cout << "[ Converting to RAM Program ... ]\n"; } std::unique_ptr<RamStatement> stmt = RamTranslator().translateProgram(translationUnit); // check whether there is something to tune if (!stmt) { if (verbose) { std::cout << "[ No Rules in Program ]\n"; std::cout << "---------------- Auto-Scheduling Completed ----------------\n"; } return false; } if (verbose) { std::cout << "[ Done ]\n"; } // step 2 - run in interpreted mode, collect decisions if (verbose) { std::cout << "[ Profiling RAM Program ... ]\n"; } Profiler::Data data; Profiler profiler(strategy, data); // create a copy of the symbol table souffle::SymbolTable table = translationUnit.getSymbolTable(); // create interpreter instance RamGuidedInterpreter interpreter(profiler); if (report && verbose) { SplitStream splitStream(report, &std::cout); interpreter.setReportTarget(splitStream); } else if (report) { interpreter.setReportTarget(*report); } else if (verbose) { interpreter.setReportTarget(std::cout); } // run interpreter interpreter.execute(table, *stmt); if (verbose) { std::cout << "[ Done ]\n"; } if (verbose) { std::cout << "Data:\n"; for (const auto& cur : data) { std::cout << "Clause @ " << cur.first << "\n"; for (const ExecutionSummary& instance : cur.second) { std::cout << "\t" << instance.order << " in " << instance.time << "ms\n"; } } } // step 3 - process collected data .. if (verbose) { std::cout << "[ Selecting most significant schedules ... ]\n"; } std::map<AstSrcLocation, const AstClause*> clauses; visitDepthFirst(*translationUnit.getProgram(), [&](const AstClause& clause) { clauses[clause.getSrcLoc()] = &clause; }); std::map<const AstClause*, long> longestTime; std::map<const AstClause*, Order> bestOrders; // extract best order for each clause for (const auto& cur : data) { const AstClause* clause = clauses[cur.first]; assert(clause && "Unknown clause discovered!"); for (const ExecutionSummary& instance : cur.second) { if (longestTime[clause] < instance.time) { longestTime[clause] = instance.time; bestOrders[clause] = instance.order; } } } if (verbose) { for (const auto& cur : bestOrders) { std::cout << *cur.first << "\n Best Order: " << cur.second << "\n Time: " << longestTime[cur.first] << "\n\n"; } } if (verbose) { std::cout << "[ Done ]\n"; } // step 4 - apply transformations if (verbose) { std::cout << "[ Re-scheduling rules ... ]\n"; } bool changed = false; for (const auto& cur : bestOrders) { AstClause* clause = const_cast<AstClause*>(cur.first); bool orderChanged = false; const std::vector<unsigned>& newOrder = cur.second.getOrder(); // Check whether best order is different to the original order for (unsigned int i = 0; i < clause->getAtoms().size(); i++) { if (newOrder[i] != i) { orderChanged = true; break; } } if (orderChanged) { clause->reorderAtoms(newOrder); changed = true; } } if (verbose) { std::cout << "[ Done ]\n"; } // end with status message if (verbose) { std::cout << "---------------- Auto-Scheduling Completed -----------------\n"; } return changed; }