Skip to content

[feat] default enable inst combine pass to avoid ungrounded error #92

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 9, 2025
Merged
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
44 changes: 27 additions & 17 deletions example/java/CallChainWithSignature.gdl
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,17 @@ fn isChecked(signature: string) -> bool {

// You can view the signature, line number, and file location of each callable by outputting the following function:
fn signature_name(signature: string, line: int, fileName: string) -> bool {
let (db = default_java_db()){
for (callable in Callable(db)){
if (signature = callable.getSignature() && fileName = callable.getLocation().getFile().getName()
&& line = callable.getLocation().getStartLineNumber()) {
return true
}
for (callable in Callable(default_java_db())) {
if (signature = callable.getSignature() &&
fileName = callable.getLocation().getFile().getName() &&
line = callable.getLocation().getStartLineNumber()) {
return true
}
}
}

// Determine whether it is a callable corresponding to the function signature
fn checkCallable(c: Callable)-> bool {
fn checkCallable(c: Callable) -> bool {
if (isChecked(c.getSignature())) {
return true
}
Expand All @@ -35,39 +34,50 @@ fn checkCallable(c: Callable)-> bool {

// Do an upward search
fn getAncestorCallerEndWithLimit(c: Callable) -> *Callable {
// Get the calling function of the current functio
// Get the calling function of the current function
yield c.getCaller()
// The current node is multiple layers above, and recursive calls are required to obtain all calling functions
for (tmp in c.getCaller()) {
yield getAncestorCallerEndWithLimit(tmp)
}
}

fn getAllLimitedCallable(c:Callable)->*Callable{
fn getAllLimitedCallable(c: Callable) -> *Callable {
yield c
yield getAncestorCallerEndWithLimit(c)
}

// At the same time, output the class corresponding to callable
fn getCallGraph(callMethodName:string, callClassName: string,
calleeMethodName:string, calleeClassName: string) -> bool {
let (db = default_java_db()){
for (callable in Callable(db)){
fn getCallGraph(callMethodName: string,
callClassName: string,
calleeMethodName: string,
calleeClassName: string) -> bool {
let (db = default_java_db()) {
for (callable in Callable(db)) {
if (checkCallable(callable)) {
for (call in getAllLimitedCallable(callable), callee in getAllLimitedCallable(callable)){
for (call in getAllLimitedCallable(callable), callee in getAllLimitedCallable(callable)) {
if (call != callee && callee in call.getCallee()) {
// Get the method corresponding to the callable
// But be aware that the callable is mixed with method and constructor
// So this call graph may not contain constructor
for (callMethod in Method(db), calleeMethod in Method(db)) {
if (callMethod.key_eq(call) && calleeMethod.key_eq(callee)) {
if (callMethodName = callMethod.getName() && callClassName = callMethod.getBelongedClass().getQualifiedName() &&
calleeMethodName = callee.getName() && calleeClassName = calleeMethod.getBelongedClass().getQualifiedName()) {
if (callMethodName = callMethod.getName() &&
callClassName = callMethod.getBelongedClass().getQualifiedName() &&
calleeMethodName = callee.getName() &&
// Also, method's getBelongedClass will get Class,
// but some of methods are belonged to interface.
// So this call graph may not contain methods in interfaces.
// If you want to get methods in interfaces, you can use the following code:
// calleeClassName = calleeMethod.getParent().getQualifiedName()
calleeClassName = calleeMethod.getBelongedClass().getQualifiedName()) {
return true
}
}
}
}
}
}

}
}
}
Expand Down
4 changes: 2 additions & 2 deletions godel-script/godel-frontend/src/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,12 @@ std::ostream& help(std::ostream& out) {
<< reset << "Enable souffle code generator for statement optimizer.\n"
<< green << " -Ol, --opt-let "
<< reset << "Enable souffle code generator let statement optimizer(not suggested).\n"
<< green << " -Oim, --opt-ir-merge "
<< reset << "Enable souffle inst combine pass.\n"
<< green << " -Osc, --opt-self-constraint "
<< reset << "Enable self data constraint optimizer in souffle code generator.\n"
<< green << " -Ojr, --opt-join-reorder "
<< reset << "Enable join reorder optimizer(experimental).\n"
<< green << " --disable-inst-combine "
<< reset << "Disable instruction combine pass.\n"
<< green << " --disable-remove-unused "
<< reset << "Disable unused method deletion pass.\n"
<< green << " --disable-do-schema-opt "
Expand Down
9 changes: 3 additions & 6 deletions godel-script/godel-frontend/src/cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ enum class option {
/* optimization */
cli_enable_for_opt, // switch for optimization on
cli_enable_let_opt, // switch let optimization on
cli_enable_ir_merge, // switch ir merge on
cli_enable_self_constraint_opt, // switch self constraint optimization on
cli_enable_join_reorder, // switch join reorder optimization on
cli_disable_inst_combine, // switch inst combine off
cli_disable_remove_unused, // switch unused method deletion off
cli_disable_do_schema_opt, // switch do schema optimization off
cli_souffle_debug_dump, // switch souffle debug mode on
Expand Down Expand Up @@ -121,12 +121,11 @@ const std::unordered_map<std::string, option> options = {
{"-Of", option::cli_enable_for_opt},
{"--opt-let", option::cli_enable_let_opt},
{"-Ol", option::cli_enable_let_opt},
{"--opt-ir-merge", option::cli_enable_ir_merge},
{"-Oim", option::cli_enable_ir_merge},
{"--opt-self-constraint", option::cli_enable_self_constraint_opt},
{"-Osc", option::cli_enable_self_constraint_opt},
{"--opt-join-reorder", option::cli_enable_join_reorder},
{"-Ojr", option::cli_enable_join_reorder},
{"--disable-inst-combine", option::cli_disable_inst_combine},
{"--disable-remove-unused", option::cli_disable_remove_unused},
{"--disable-do-schema-opt", option::cli_disable_do_schema_opt},
{"--souffle-debug", option::cli_souffle_debug_dump},
Expand All @@ -142,11 +141,9 @@ const std::unordered_map<std::string, option> options = {
const std::unordered_map<std::string, std::vector<option>> multi_options = {
{"-O1", {option::cli_enable_for_opt}},
{"-O2", {option::cli_enable_for_opt,
option::cli_enable_self_constraint_opt,
option::cli_enable_ir_merge}},
option::cli_enable_self_constraint_opt}},
{"-O3", {option::cli_enable_for_opt,
option::cli_enable_self_constraint_opt,
option::cli_enable_ir_merge,
option::cli_enable_join_reorder}}
};

Expand Down
23 changes: 20 additions & 3 deletions godel-script/godel-frontend/src/ir/inst_combine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,18 +143,26 @@ void inst_combine_pass::scan(souffle_rule_impl* b) {
//
for(const auto& i : variable_reference_graph) {
const auto& name = i.first;
if (i.second.size()!=1) {
// if alias variables' count > 1, even if there's a circle, still skip it.
if (i.second.size() != 1) {
continue;
}
// alias variable's name
const auto& to = i.second.begin()->first;
if (!variable_reference_graph.count(to)) {
continue;
}
if (variable_reference_graph.at(to).size()!=1) {
// this variable's alias count should be 1
if (variable_reference_graph.at(to).size() != 1) {
continue;
}
// get `to`'s alias variable's name, this name should be equal to `name`
const auto& from = variable_reference_graph.at(to).begin()->first;
if (from==name && to.find("ssa_temp")==0 && from.find("ssa_temp")==0) {
// means there's a circle like this:
// `to` <--> `from`(aka `name`)
// after clear(), `to`'s alias count should be 0:
// `to` <--- `from`(aka `name`)
if (from == name && to.find("ssa_temp") == 0 && from.find("ssa_temp") == 0) {
variable_reference_graph.at(to).clear();
}
}
Expand Down Expand Up @@ -233,6 +241,15 @@ void combine_worker::visit_binary(lir::binary* node) {
}
}

void combine_worker::visit_aggregator(lir::aggregator* node) {
const auto& tgt = node->get_target();
if (is_single_ref_ssa_temp(tgt.content)) {
const auto& ref = get_single_ref(tgt.content);
node->get_mutable_target().content = ref.first;
ref.second->set_flag_eliminated(true);
}
}

void combine_worker::mark(souffle_rule_impl* b) {
b->get_block()->accept(this);
}
Expand Down
1 change: 1 addition & 0 deletions godel-script/godel-frontend/src/ir/inst_combine.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class combine_worker: public lir::inst_visitor {
void visit_record(lir::record*) override;
void visit_unary(lir::unary*) override;
void visit_binary(lir::binary*) override;
void visit_aggregator(lir::aggregator*) override;

public:
combine_worker(const inst_combine_pass::ref_graph& g): vg(g) {}
Expand Down
14 changes: 13 additions & 1 deletion godel-script/godel-frontend/src/ir/lir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,19 @@ void not_operand::dump(std::ostream& os, const std::string& indent) const {
// only one statement in the block
if (body->get_content().size()==1) {
os << indent << "!(";
body->get_content()[0]->dump(os, "");
switch(body->get_content()[0]->get_kind()) {
case inst_kind::inst_not:
case inst_kind::inst_and:
case inst_kind::inst_or:
case inst_kind::inst_aggr:
os << "\n";
body->get_content()[0]->dump(os, indent + " ");
os << "\n" << indent;
break;
default:
body->get_content()[0]->dump(os, "");
break;
}
os << ")";
return;
}
Expand Down
4 changes: 4 additions & 0 deletions godel-script/godel-frontend/src/ir/lir.h
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,10 @@ class aggregator: public inst {
void accept(inst_visitor* v) override {
v->visit_aggregator(this);
}

public:
const auto& get_target() const { return destination; }
auto& get_mutable_target() { return destination; }
};

}
Expand Down
2 changes: 1 addition & 1 deletion godel-script/godel-frontend/src/ir/pass_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void pass_manager::run(ir_context& ctx, const cli::configure& conf) {
ordered_pass_list.push_back(new unused_remove_pass(ctx));
ordered_pass_list.push_back(new unused_type_alias_remove_pass(ctx));
}
if (conf.count(cli::option::cli_enable_ir_merge)) {
if (!conf.count(cli::option::cli_disable_inst_combine)) {
ordered_pass_list.push_back(new inst_combine_pass(ctx));
}
ordered_pass_list.push_back(new flatten_nested_block(ctx));
Expand Down
Loading