Skip to content

Commit

Permalink
Merge pull request #92 from codefuse-ai/lhk_dev
Browse files Browse the repository at this point in the history
[feat] default enable inst combine pass to avoid ungrounded error
  • Loading branch information
ValKmjolnir authored Jan 9, 2025
2 parents 8fe1a45 + 8464560 commit 434a871
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 30 deletions.
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

0 comments on commit 434a871

Please sign in to comment.