Skip to content

Commit 434a871

Browse files
authored
Merge pull request #92 from codefuse-ai/lhk_dev
[feat] default enable inst combine pass to avoid ungrounded error
2 parents 8fe1a45 + 8464560 commit 434a871

File tree

8 files changed

+71
-30
lines changed

8 files changed

+71
-30
lines changed

example/java/CallChainWithSignature.gdl

+27-17
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,17 @@ fn isChecked(signature: string) -> bool {
1515

1616
// You can view the signature, line number, and file location of each callable by outputting the following function:
1717
fn signature_name(signature: string, line: int, fileName: string) -> bool {
18-
let (db = default_java_db()){
19-
for (callable in Callable(db)){
20-
if (signature = callable.getSignature() && fileName = callable.getLocation().getFile().getName()
21-
&& line = callable.getLocation().getStartLineNumber()) {
22-
return true
23-
}
18+
for (callable in Callable(default_java_db())) {
19+
if (signature = callable.getSignature() &&
20+
fileName = callable.getLocation().getFile().getName() &&
21+
line = callable.getLocation().getStartLineNumber()) {
22+
return true
2423
}
2524
}
2625
}
2726

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

3635
// Do an upward search
3736
fn getAncestorCallerEndWithLimit(c: Callable) -> *Callable {
38-
// Get the calling function of the current functio
37+
// Get the calling function of the current function
3938
yield c.getCaller()
4039
// The current node is multiple layers above, and recursive calls are required to obtain all calling functions
4140
for (tmp in c.getCaller()) {
4241
yield getAncestorCallerEndWithLimit(tmp)
4342
}
4443
}
4544

46-
fn getAllLimitedCallable(c:Callable)->*Callable{
45+
fn getAllLimitedCallable(c: Callable) -> *Callable {
4746
yield c
4847
yield getAncestorCallerEndWithLimit(c)
4948
}
5049

5150
// At the same time, output the class corresponding to callable
52-
fn getCallGraph(callMethodName:string, callClassName: string,
53-
calleeMethodName:string, calleeClassName: string) -> bool {
54-
let (db = default_java_db()){
55-
for (callable in Callable(db)){
51+
fn getCallGraph(callMethodName: string,
52+
callClassName: string,
53+
calleeMethodName: string,
54+
calleeClassName: string) -> bool {
55+
let (db = default_java_db()) {
56+
for (callable in Callable(db)) {
5657
if (checkCallable(callable)) {
57-
for (call in getAllLimitedCallable(callable), callee in getAllLimitedCallable(callable)){
58+
for (call in getAllLimitedCallable(callable), callee in getAllLimitedCallable(callable)) {
5859
if (call != callee && callee in call.getCallee()) {
60+
// Get the method corresponding to the callable
61+
// But be aware that the callable is mixed with method and constructor
62+
// So this call graph may not contain constructor
5963
for (callMethod in Method(db), calleeMethod in Method(db)) {
6064
if (callMethod.key_eq(call) && calleeMethod.key_eq(callee)) {
61-
if (callMethodName = callMethod.getName() && callClassName = callMethod.getBelongedClass().getQualifiedName() &&
62-
calleeMethodName = callee.getName() && calleeClassName = calleeMethod.getBelongedClass().getQualifiedName()) {
65+
if (callMethodName = callMethod.getName() &&
66+
callClassName = callMethod.getBelongedClass().getQualifiedName() &&
67+
calleeMethodName = callee.getName() &&
68+
// Also, method's getBelongedClass will get Class,
69+
// but some of methods are belonged to interface.
70+
// So this call graph may not contain methods in interfaces.
71+
// If you want to get methods in interfaces, you can use the following code:
72+
// calleeClassName = calleeMethod.getParent().getQualifiedName()
73+
calleeClassName = calleeMethod.getBelongedClass().getQualifiedName()) {
6374
return true
6475
}
6576
}
6677
}
6778
}
6879
}
6980
}
70-
7181
}
7282
}
7383
}

godel-script/godel-frontend/src/cli.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,12 @@ std::ostream& help(std::ostream& out) {
110110
<< reset << "Enable souffle code generator for statement optimizer.\n"
111111
<< green << " -Ol, --opt-let "
112112
<< reset << "Enable souffle code generator let statement optimizer(not suggested).\n"
113-
<< green << " -Oim, --opt-ir-merge "
114-
<< reset << "Enable souffle inst combine pass.\n"
115113
<< green << " -Osc, --opt-self-constraint "
116114
<< reset << "Enable self data constraint optimizer in souffle code generator.\n"
117115
<< green << " -Ojr, --opt-join-reorder "
118116
<< reset << "Enable join reorder optimizer(experimental).\n"
117+
<< green << " --disable-inst-combine "
118+
<< reset << "Disable instruction combine pass.\n"
119119
<< green << " --disable-remove-unused "
120120
<< reset << "Disable unused method deletion pass.\n"
121121
<< green << " --disable-do-schema-opt "

godel-script/godel-frontend/src/cli.h

+3-6
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ enum class option {
4646
/* optimization */
4747
cli_enable_for_opt, // switch for optimization on
4848
cli_enable_let_opt, // switch let optimization on
49-
cli_enable_ir_merge, // switch ir merge on
5049
cli_enable_self_constraint_opt, // switch self constraint optimization on
5150
cli_enable_join_reorder, // switch join reorder optimization on
51+
cli_disable_inst_combine, // switch inst combine off
5252
cli_disable_remove_unused, // switch unused method deletion off
5353
cli_disable_do_schema_opt, // switch do schema optimization off
5454
cli_souffle_debug_dump, // switch souffle debug mode on
@@ -121,12 +121,11 @@ const std::unordered_map<std::string, option> options = {
121121
{"-Of", option::cli_enable_for_opt},
122122
{"--opt-let", option::cli_enable_let_opt},
123123
{"-Ol", option::cli_enable_let_opt},
124-
{"--opt-ir-merge", option::cli_enable_ir_merge},
125-
{"-Oim", option::cli_enable_ir_merge},
126124
{"--opt-self-constraint", option::cli_enable_self_constraint_opt},
127125
{"-Osc", option::cli_enable_self_constraint_opt},
128126
{"--opt-join-reorder", option::cli_enable_join_reorder},
129127
{"-Ojr", option::cli_enable_join_reorder},
128+
{"--disable-inst-combine", option::cli_disable_inst_combine},
130129
{"--disable-remove-unused", option::cli_disable_remove_unused},
131130
{"--disable-do-schema-opt", option::cli_disable_do_schema_opt},
132131
{"--souffle-debug", option::cli_souffle_debug_dump},
@@ -142,11 +141,9 @@ const std::unordered_map<std::string, option> options = {
142141
const std::unordered_map<std::string, std::vector<option>> multi_options = {
143142
{"-O1", {option::cli_enable_for_opt}},
144143
{"-O2", {option::cli_enable_for_opt,
145-
option::cli_enable_self_constraint_opt,
146-
option::cli_enable_ir_merge}},
144+
option::cli_enable_self_constraint_opt}},
147145
{"-O3", {option::cli_enable_for_opt,
148146
option::cli_enable_self_constraint_opt,
149-
option::cli_enable_ir_merge,
150147
option::cli_enable_join_reorder}}
151148
};
152149

godel-script/godel-frontend/src/ir/inst_combine.cpp

+20-3
Original file line numberDiff line numberDiff line change
@@ -143,18 +143,26 @@ void inst_combine_pass::scan(souffle_rule_impl* b) {
143143
//
144144
for(const auto& i : variable_reference_graph) {
145145
const auto& name = i.first;
146-
if (i.second.size()!=1) {
146+
// if alias variables' count > 1, even if there's a circle, still skip it.
147+
if (i.second.size() != 1) {
147148
continue;
148149
}
150+
// alias variable's name
149151
const auto& to = i.second.begin()->first;
150152
if (!variable_reference_graph.count(to)) {
151153
continue;
152154
}
153-
if (variable_reference_graph.at(to).size()!=1) {
155+
// this variable's alias count should be 1
156+
if (variable_reference_graph.at(to).size() != 1) {
154157
continue;
155158
}
159+
// get `to`'s alias variable's name, this name should be equal to `name`
156160
const auto& from = variable_reference_graph.at(to).begin()->first;
157-
if (from==name && to.find("ssa_temp")==0 && from.find("ssa_temp")==0) {
161+
// means there's a circle like this:
162+
// `to` <--> `from`(aka `name`)
163+
// after clear(), `to`'s alias count should be 0:
164+
// `to` <--- `from`(aka `name`)
165+
if (from == name && to.find("ssa_temp") == 0 && from.find("ssa_temp") == 0) {
158166
variable_reference_graph.at(to).clear();
159167
}
160168
}
@@ -233,6 +241,15 @@ void combine_worker::visit_binary(lir::binary* node) {
233241
}
234242
}
235243

244+
void combine_worker::visit_aggregator(lir::aggregator* node) {
245+
const auto& tgt = node->get_target();
246+
if (is_single_ref_ssa_temp(tgt.content)) {
247+
const auto& ref = get_single_ref(tgt.content);
248+
node->get_mutable_target().content = ref.first;
249+
ref.second->set_flag_eliminated(true);
250+
}
251+
}
252+
236253
void combine_worker::mark(souffle_rule_impl* b) {
237254
b->get_block()->accept(this);
238255
}

godel-script/godel-frontend/src/ir/inst_combine.h

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class combine_worker: public lir::inst_visitor {
5353
void visit_record(lir::record*) override;
5454
void visit_unary(lir::unary*) override;
5555
void visit_binary(lir::binary*) override;
56+
void visit_aggregator(lir::aggregator*) override;
5657

5758
public:
5859
combine_worker(const inst_combine_pass::ref_graph& g): vg(g) {}

godel-script/godel-frontend/src/ir/lir.cpp

+13-1
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,19 @@ void not_operand::dump(std::ostream& os, const std::string& indent) const {
359359
// only one statement in the block
360360
if (body->get_content().size()==1) {
361361
os << indent << "!(";
362-
body->get_content()[0]->dump(os, "");
362+
switch(body->get_content()[0]->get_kind()) {
363+
case inst_kind::inst_not:
364+
case inst_kind::inst_and:
365+
case inst_kind::inst_or:
366+
case inst_kind::inst_aggr:
367+
os << "\n";
368+
body->get_content()[0]->dump(os, indent + " ");
369+
os << "\n" << indent;
370+
break;
371+
default:
372+
body->get_content()[0]->dump(os, "");
373+
break;
374+
}
363375
os << ")";
364376
return;
365377
}

godel-script/godel-frontend/src/ir/lir.h

+4
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,10 @@ class aggregator: public inst {
666666
void accept(inst_visitor* v) override {
667667
v->visit_aggregator(this);
668668
}
669+
670+
public:
671+
const auto& get_target() const { return destination; }
672+
auto& get_mutable_target() { return destination; }
669673
};
670674

671675
}

godel-script/godel-frontend/src/ir/pass_manager.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ void pass_manager::run(ir_context& ctx, const cli::configure& conf) {
2828
ordered_pass_list.push_back(new unused_remove_pass(ctx));
2929
ordered_pass_list.push_back(new unused_type_alias_remove_pass(ctx));
3030
}
31-
if (conf.count(cli::option::cli_enable_ir_merge)) {
31+
if (!conf.count(cli::option::cli_disable_inst_combine)) {
3232
ordered_pass_list.push_back(new inst_combine_pass(ctx));
3333
}
3434
ordered_pass_list.push_back(new flatten_nested_block(ctx));

0 commit comments

Comments
 (0)