{SCF_OP_3AC_JB, "jb"},
{SCF_OP_3AC_JBE, "jbe"},
+ {SCF_OP_3AC_DUMP, "core_dump"},
{SCF_OP_3AC_NOP, "nop"},
{SCF_OP_3AC_END, "end"},
dn_src = src->dag_node;
- if (dn_src->parents && dn_src->parents->size > 0) {
+ if (dn_src->parents && dn_src->parents->size > 0 && !scf_variable_may_malloced(dn_src->var)) {
dn_parent = dn_src->parents->data[dn_src->parents->size - 1];
if (SCF_OP_ASSIGN == dn_parent->type) {
return ret;
}
} else if (SCF_OP_3AC_CMP == c->op->type
- || SCF_OP_3AC_TEQ == c->op->type) {
+ || SCF_OP_3AC_TEQ == c->op->type
+ || SCF_OP_3AC_DUMP == c->op->type) {
scf_dag_node_t* dn_cmp = scf_dag_node_alloc(c->op->type, NULL, NULL);
continue;
}
#endif
+ if (SCF_OP_3AC_DUMP == c->op->type) {
+ c->basic_block_start = 1;
+ continue;
+ }
if (SCF_OP_3AC_END == c->op->type) {
c->basic_block_start = 1;
continue;
}
+ if (SCF_OP_3AC_DUMP == c->op->type) {
+ bb->dump_flag = 1;
+ continue;
+ }
+
if (SCF_OP_3AC_END == c->op->type) {
bb->end_flag = 1;
continue;
uint32_t vla_flag :1;
uint32_t end_flag :1;
uint32_t varg_flag :1;
+ uint32_t dump_flag :1;
uint32_t jmp_dst_flag:1;
uint32_t dereference_flag:1;
SCF_OP_3AC_RELOAD, // reload a var from memory, only for 3ac & native
SCF_OP_3AC_RESAVE, // resave a var to memory, only for 3ac & native
+ SCF_OP_3AC_DUMP,
SCF_OP_3AC_NOP,
SCF_OP_3AC_END,
scf_list_add_tail(d->_3ac_list_head, &jmp->list);
- scf_vector_add(d->branch_ops->_breaks, jmp);
- return 0;
+ return scf_vector_add(d->branch_ops->_breaks, jmp);
}
static int _scf_op_continue(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data)
assert(4 == nb_nodes);
scf_handler_data_t* d = data;
+ scf_variable_t* v;
+ scf_type_t* t;
+ scf_node_t* parent = nodes[0]->parent;
+ scf_node_t* zero;
+
+ t = scf_block_find_type_type(ast->current_block, SCF_VAR_INT);
+ v = SCF_VAR_ALLOC_BY_TYPE(NULL, t, 1, 0, NULL);
+ if (!v)
+ return -ENOMEM;
+ v->data.u64 = 0;
+ v->const_literal_flag = 1;
+
+ zero = scf_node_alloc(NULL, v->type, v);
+ scf_variable_free(v);
+ v = NULL;
+ if (!zero)
+ return -ENOMEM;
+
+ int ret = scf_node_add_child(parent, zero);
+ if (ret < 0) {
+ scf_node_free(zero);
+ return ret;
+ }
+
+ scf_3ac_operand_t* dst;
+ scf_3ac_code_t* cmp;
+ scf_3ac_code_t* jgt;
+ scf_3ac_code_t* core;
+ scf_node_t* srcs[] = {nodes[1], zero};
+
+ cmp = scf_3ac_code_NN(SCF_OP_3AC_CMP, NULL, 0, srcs, 2);
+ if (!cmp)
+ return -ENOMEM;
+
+ jgt = scf_3ac_jmp_code(SCF_OP_3AC_JGT, NULL, NULL);
+ if (!jgt) {
+ scf_3ac_code_free(cmp);
+ return -ENOMEM;
+ }
+
+ core = scf_3ac_code_NN(SCF_OP_3AC_DUMP, NULL, 0, nodes + 1, 3);
+ if (!core) {
+ scf_3ac_code_free(jgt);
+ scf_3ac_code_free(cmp);
+ return -ENOMEM;
+ }
+
+ scf_list_add_tail(d->_3ac_list_head, &cmp->list);
+ scf_list_add_tail(d->_3ac_list_head, &jgt->list);
+ scf_list_add_tail(d->_3ac_list_head, &core->list);
+
+ dst = jgt->dsts->data[0];
+ dst->code = core;
+
+ ret = scf_vector_add(d->branch_ops->_breaks, jgt);
+ if (ret < 0)
+ return ret;
return _scf_3ac_code_N(d->_3ac_list_head, SCF_OP_VLA_ALLOC, nodes[0], nodes + 1, 3);
}
#include"scf_optimizer.h"
extern scf_optimizer_t scf_optimizer_inline;
+extern scf_optimizer_t scf_optimizer_split_call;
extern scf_optimizer_t scf_optimizer_dag;
static scf_optimizer_t* scf_optimizers[] =
{
&scf_optimizer_inline, // global optimizer
+ &scf_optimizer_split_call,
&scf_optimizer_dag,
}
}
+static void __optimize_dn_free(scf_dag_node_t* dn)
+{
+ scf_dag_node_t* dn2;
+ int i;
+
+ for (i = 0; i < dn->childs->size; ) {
+ dn2 = dn->childs->data[i];
+
+ assert(0 == scf_vector_del(dn ->childs, dn2));
+ assert(0 == scf_vector_del(dn2->parents, dn));
+
+ if (0 == dn2->parents->size) {
+ scf_vector_free(dn2->parents);
+ dn2->parents = NULL;
+ }
+ }
+
+ scf_list_del(&dn->list);
+ scf_dag_node_free(dn);
+ dn = NULL;
+}
+
static int _bb_dag_update(scf_basic_block_t* bb)
{
scf_dag_node_t* dn;
scf_dag_node_t* dn_bb;
- scf_dag_node_t* dn_bb2;
scf_dag_node_t* dn_func;
- scf_dag_node_t* parent;
+ scf_dag_node_t* base;
scf_list_t* l;
- int i;
-
while (1) {
int updated = 0;
if (SCF_OP_ADDRESS_OF == dn->type || SCF_OP_DEREFERENCE == dn->type) {
dn_func = dn->old;
-
} else {
assert(dn_bb->parents && dn_bb->parents->size > 0);
continue;
}
- for (i = 0; i < dn->childs->size; ) {
- dn_bb = dn->childs->data[i];
-
- assert(0 == scf_vector_del(dn->childs, dn_bb));
- assert(0 == scf_vector_del(dn_bb->parents, dn));
-
- if (0 == dn_bb->parents->size) {
- scf_vector_free(dn_bb->parents);
- dn_bb->parents = NULL;
- }
- }
-
- assert(0 == dn->childs->size);
- scf_list_del(&dn->list);
- scf_dag_node_free(dn);
- dn = NULL;
-
+ __optimize_dn_free(dn);
++updated;
} else if (SCF_OP_ADD == dn->type || SCF_OP_SUB == dn->type
|| scf_vector_find(bb->dn_resaves, dn_func))
continue;
- for (i = 0; i < dn->childs->size; i++) {
- dn_bb = dn->childs->data[i];
-
- assert(0 == scf_vector_del(dn_bb->parents, dn));
-
- if (0 == dn_bb->parents->size) {
- scf_vector_free(dn_bb->parents);
- dn_bb->parents = NULL;
- }
- }
-
- scf_list_del(&dn->list);
- scf_dag_node_free(dn);
- dn = NULL;
-
+ __optimize_dn_free(dn);
++updated;
}
}
if (bb->jmp_flag
|| bb->end_flag
|| bb->call_flag
+ || bb->dump_flag
|| bb->varg_flag) {
scf_logd("bb: %p, jmp:%d,ret:%d, end: %d, call:%d, varg:%d, dereference_flag: %d\n",
bb, bb->jmp_flag, bb->ret_flag, bb->end_flag, bb->call_flag, bb->dereference_flag,
return 0;
}
-static void _bb_update_dn_status(scf_vector_t* aliases, scf_list_t* start, scf_basic_block_t* bb)
-{
- scf_list_t* l;
- scf_3ac_code_t* c;
- scf_dn_status_t* status;
-
- for (l = start; l != scf_list_sentinel(&bb->code_list_head); l = scf_list_next(l)) {
-
- c = scf_list_data(l, scf_3ac_code_t, list);
-
- if (!c->active_vars)
- continue;
-
- int i;
- for (i = 0; i < c->active_vars->size; ) {
- status = c->active_vars->data[i];
-
- if (scf_vector_find_cmp(aliases, status->dag_node, scf_dn_status_cmp))
- assert(0 == scf_vector_del(c->active_vars, status));
- else
- ++i;
- }
- }
-}
-
static int __optimize_call_bb(scf_3ac_code_t* c, scf_basic_block_t* bb, scf_list_t* bb_list_head)
{
- scf_list_t* l;
- scf_vector_t* aliases;
- int ret;
-
- aliases = scf_vector_alloc();
+ scf_vector_t* aliases = scf_vector_alloc();
if (!aliases)
return -ENOMEM;
- ret = _alias_call(aliases, c, bb, bb_list_head);
+ int ret = _alias_call(aliases, c, bb, bb_list_head);
if (ret < 0) {
scf_loge("\n");
scf_vector_free(aliases);
scf_vector_free(aliases);
return ret;
}
-
- l = scf_list_head(&bb->code_list_head);
- l = scf_list_next(l);
- _bb_update_dn_status(aliases, l, bb);
}
scf_vector_free(aliases);
return 0;
}
-#define SCF_BB_SPLIT_MOV_CODE(start, bb0, bb1) \
- do { \
- bb1 = NULL; \
- ret = scf_basic_block_split(bb0, &bb1); \
- if (ret < 0) \
- return ret; \
- bb1->dereference_flag = bb0->dereference_flag; \
- bb1->ret_flag = bb0->ret_flag; \
- bb0->ret_flag = 0; \
- scf_list_add_front(&bb0->list, &bb1->list); \
- scf_basic_block_mov_code(bb1, start, bb0); \
- } while (0)
-
static int _optimize_call_bb(scf_basic_block_t* bb, scf_list_t* bb_list_head)
{
- scf_list_t* l;
- scf_list_t* start;
- scf_list_t* sentinel;
-
- int ret;
-
- while (1) {
- scf_3ac_code_t* c;
- scf_basic_block_t* bb_child;
-
- start = scf_list_head(&bb->code_list_head);
- sentinel = scf_list_sentinel(&bb->code_list_head);
-
- for (l = start; l != sentinel; l = scf_list_next(l)) {
- c = scf_list_data(l, scf_3ac_code_t, list);
-
- if (SCF_OP_CALL == c->op->type)
- break;
- }
- if (l == sentinel)
- break;
-
- if (l != start) {
- bb->call_flag = 0;
- SCF_BB_SPLIT_MOV_CODE(l, bb, bb_child);
- bb = bb_child;
- }
- bb->call_flag = 1;
-
- ret = __optimize_call_bb(c, bb, bb_list_head);
- if (ret < 0) {
- scf_loge("\n");
- return ret;
- }
+ scf_3ac_code_t* c;
+ scf_list_t* l;
- l = scf_list_head(&bb->code_list_head);
- l = scf_list_next(l);
- if (l == scf_list_sentinel(&bb->code_list_head))
- break;
+ l = scf_list_head(&bb->code_list_head);
+ c = scf_list_data(l, scf_3ac_code_t, list);
- SCF_BB_SPLIT_MOV_CODE(l, bb, bb_child);
- bb = bb_child;
+ assert(SCF_OP_CALL == c->op->type);
+ assert(scf_list_next(l) == scf_list_sentinel(&bb->code_list_head));
- ret = scf_basic_block_inited_vars(bb, bb_list_head);
- if (ret < 0)
- return ret;
- }
- return 0;
+ return __optimize_call_bb(c, bb, bb_list_head);
}
static int _optimize_call(scf_ast_t* ast, scf_function_t* f, scf_vector_t* functions)
return ret;
}
+// scf_basic_block_print_list(bb_list_head);
return 0;
}
if (bb->jmp_flag
|| bb->end_flag
|| bb->call_flag
+ || bb->dump_flag
|| bb->varg_flag) {
scf_logd("bb: %p, jmp:%d,ret:%d, end: %d, call:%d, varg:%d, dereference_flag: %d\n",
bb, bb->jmp_flag, bb->ret_flag, bb->end_flag, bb->call_flag, bb->dereference_flag,
return ret;
}
-// scf_basic_block_print_list(bb_list_head);
return 0;
}
if (!bb->call_flag)
continue;
- int call_flag = 0;
+ int n_calls = 0;
bb_cur = bb;
if (SCF_OP_CALL != c->op->type)
continue;
- call_flag = 1;
+ n_calls++;
src = c->srcs->data[0];
v = _scf_operand_get(src->node);
bb2 = bb_cur;
bb_cur->call_flag = 0;
+ n_calls--;
+
int ret = _do_inline(ast, c, &bb_cur, f, f2);
if (ret < 0)
return ret;
scf_3ac_code_free(c);
c = NULL;
- bb2->call_flag |= call_flag;
- call_flag = 0;
+ bb2->call_flag |= n_calls > 0;
if (bb2->ret_flag) {
bb2->ret_flag = 0;
#endif
}
- bb_cur->call_flag |= call_flag;
- call_flag = 0;
+ bb_cur->call_flag |= n_calls > 0;
}
#if 0
--- /dev/null
+#include"scf_optimizer.h"
+#include"scf_pointer_alias.h"
+
+#define SCF_BB_SPLIT(bb0, bb1) \
+ do { \
+ bb1 = NULL; \
+ int ret = scf_basic_block_split(bb0, &bb1); \
+ if (ret < 0) \
+ return ret; \
+ bb1->dereference_flag = bb0->dereference_flag; \
+ bb1->ret_flag = bb0->ret_flag; \
+ bb0->ret_flag = 0; \
+ scf_list_add_front(&bb0->list, &bb1->list); \
+ } while (0)
+
+static int _optimize_split_call_bb(scf_basic_block_t* bb, scf_list_t* bb_list_head)
+{
+ scf_basic_block_t* cur_bb = bb;
+ scf_basic_block_t* bb2;
+ scf_3ac_code_t* c;
+ scf_list_t* l;
+
+ int split_flag = 0;
+
+ for (l = scf_list_head(&bb->code_list_head); l != scf_list_sentinel(&bb->code_list_head); ) {
+
+ c = scf_list_data(l, scf_3ac_code_t, list);
+ l = scf_list_next(l);
+
+ if (split_flag) {
+ split_flag = 0;
+
+ SCF_BB_SPLIT(cur_bb, bb2);
+ cur_bb = bb2;
+ }
+
+ if (cur_bb != bb) {
+ scf_list_del(&c->list);
+ scf_list_add_tail(&cur_bb->code_list_head, &c->list);
+
+ c->basic_block = cur_bb;
+ }
+
+ if (SCF_OP_CALL == c->op->type) {
+ split_flag = 1;
+
+ if (scf_list_prev(&c->list) != scf_list_sentinel(&cur_bb->code_list_head)) {
+ SCF_BB_SPLIT(cur_bb, bb2);
+
+ cur_bb->call_flag = 0;
+
+ scf_list_del(&c->list);
+ scf_list_add_tail(&bb2->code_list_head, &c->list);
+
+ c->basic_block = bb2;
+
+ cur_bb = bb2;
+ }
+
+ cur_bb->call_flag = 1;
+ }
+ }
+
+ return 0;
+}
+
+static int _optimize_split_call(scf_ast_t* ast, scf_function_t* f, scf_vector_t* functions)
+{
+ if (!f)
+ return -EINVAL;
+
+ scf_list_t* bb_list_head = &f->basic_block_list_head;
+ scf_list_t* l;
+ scf_basic_block_t* bb;
+
+ if (scf_list_empty(bb_list_head))
+ return 0;
+
+ for (l = scf_list_head(bb_list_head); l != scf_list_sentinel(bb_list_head); ) {
+
+ bb = scf_list_data(l, scf_basic_block_t, list);
+ l = scf_list_next(l);
+
+ if (bb->jmp_flag || bb->end_flag || bb->cmp_flag)
+ continue;
+
+ if (!bb->call_flag)
+ continue;
+
+ int ret = _optimize_split_call_bb(bb, bb_list_head);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+scf_optimizer_t scf_optimizer_split_call =
+{
+ .name = "split_call",
+
+ .optimize = _optimize_split_call,
+
+ .flags = SCF_OPTIMIZER_LOCAL,
+};
--- /dev/null
+int printf(const char* fmt, ...);
+
+int f()
+{
+ int a[2];
+
+ int* p = a;
+
+ a[0] = 1;
+ a[1] = 2;
+
+ *p += 3;
+ int b = *p;
+ return b;
+}
+
+int main()
+{
+ int i = 1;
+ int a = 2;
+ int b = 3;
+
+ printf("%d\n", f());
+ return 0;
+}
--- /dev/null
+//第 7 ç« /inline.c
+
+int printf(const char* fmt, ...);
+
+inline int add(int i, int j)
+{
+ return i + j;
+}
+
+int main()
+{
+ int a = 1;
+ int b = 2;
+ int c = add(a, b);
+ printf("%d\n", c);
+ return 0;
+}
-
#include "../lib/scf_capi.c"
struct str
int __init(str* this)
{
- this->len = 0;
+ this->len = 0;
this->capacity = 16;
this->data = scf__auto_malloc(16);
}
};
-
int main()
{
str* p0;
str* p1;
- int i;
p0 = create str();
+ p1 = p0;
- printf("%s\n", p0->data);
+ printf("%s\n", p1->data);
return 0;
}
--- /dev/null
+int printf(const char* fmt, ...);
+
+int main(int argc, char* argv[])
+{
+ int i;
+ int j;
+
+ for (i = 1; i < 4; i++) {
+ char a[i];
+
+ for (j = 0; j < i; j++) {
+
+ a[j] = '1';
+
+ printf("i: %d, j: %d, a: %c, %lg\n", i, j, a[j], 3.14);
+ }
+ }
+
+ return 0;
+}
l = scf_list_tail(&bb->code_list_head);
end = scf_list_data(l, scf_3ac_code_t, list);
- int err = x64_pop_callee_regs(end, f);
- if (err < 0)
- return err;
+ if (f->bp_used_flag || f->vla_flag) {
- if (f->bp_used_flag) {
inst = x64_make_inst_G2E(mov, rsp, rbp);
X64_INST_ADD_CHECK(end->instructions, inst);
end->inst_bytes += inst->len;
X64_INST_ADD_CHECK(end->instructions, inst);
end->inst_bytes += inst->len;
bb ->code_bytes += inst->len;
+ }
+
+ int err = x64_pop_callee_regs(end, f);
+ if (err < 0)
+ return err;
+
+ f->init_code_bytes = 0;
+
+ err = x64_push_callee_regs(f->init_code, f);
+ if (err < 0)
+ return err;
+
+ uint32_t local = f->bp_used_flag ? f->local_vars_size : 0;
+
+ if (f->bp_used_flag || f->vla_flag) {
inst = x64_make_inst_G(push, rbp);
X64_INST_ADD_CHECK(f->init_code->instructions, inst);
- f->init_code_bytes = inst->len;
+ f->init_code_bytes += inst->len;
inst = x64_make_inst_G2E(mov, rbp, rsp);
X64_INST_ADD_CHECK(f->init_code->instructions, inst);
f->init_code_bytes += inst->len;
- uint32_t local = f->local_vars_size;
-
if (f->callee_saved_size & 0xf) {
if (!(local & 0xf))
local += 8;
int err = _x64_save_rabi(f);
if (err < 0)
return err;
- } else {
- if (f->vla_flag) {
- inst = x64_make_inst_G2E(mov, rsp, rbp);
- X64_INST_ADD_CHECK(end->instructions, inst);
- end->inst_bytes += inst->len;
- bb ->code_bytes += inst->len;
- }
-
- inst = x64_make_inst_G(pop, rbp);
- X64_INST_ADD_CHECK(end->instructions, inst);
- end->inst_bytes += inst->len;
- bb ->code_bytes += inst->len;
-
- inst = x64_make_inst_G(push, rbp);
- X64_INST_ADD_CHECK(f->init_code->instructions, inst);
- f->init_code_bytes = inst->len;
-
- if (f->vla_flag) {
- inst = x64_make_inst_G2E(mov, rbp, rsp);
- X64_INST_ADD_CHECK(f->init_code->instructions, inst);
- f->init_code_bytes += inst->len;
- }
}
- err = x64_push_callee_regs(f->init_code, f);
- if (err < 0)
- return err;
-
inst = x64_make_inst(ret, 8);
X64_INST_ADD_CHECK(end->instructions, inst);
end->inst_bytes += inst->len;
_x64_set_offsets(f);
_x64_set_offset_for_jmps( ctx, f);
-
return 0;
}
return _div_mod_assign(ctx, c, 1);
}
-static int _x64_inst_vla_alloc_handler(scf_native_t* ctx, scf_3ac_code_t* c)
+static int _x64_inst_dump_handler(scf_native_t* ctx, scf_3ac_code_t* c)
{
- if (!c->dsts || c->dsts->size != 1)
- return -EINVAL;
-
if (!c->srcs || c->srcs->size != 3)
return -EINVAL;
scf_x64_context_t* x64 = ctx->priv;
scf_function_t* f = x64->f;
-
- scf_3ac_operand_t* dst = c->dsts->data[0];
scf_3ac_operand_t* src = c->srcs->data[0];
scf_3ac_operand_t* logf = c->srcs->data[1];
scf_3ac_operand_t* msg = c->srcs->data[2];
- if (!dst || !dst->dag_node)
- return -EINVAL;
-
- if (!src || !src->dag_node)
- return -EINVAL;
-
if (!logf || !logf->dag_node)
return -EINVAL;
return -EINVAL;
scf_instruction_t* inst = NULL;
- scf_instruction_t* jcc = NULL;
scf_register_t* rs = NULL;
scf_register_t* rd = NULL;
- scf_register_t* rsp = x64_find_register("rsp");
scf_register_t* rdi = x64_find_register("rdi");
scf_register_t* rsi = x64_find_register("rsi");
scf_register_t* rax = x64_find_register("rax");
- scf_x64_OpCode_t* cmp = x64_find_OpCode(SCF_X64_CMP, 1, 4, SCF_X64_I2E);
- scf_x64_OpCode_t* jg = x64_find_OpCode(SCF_X64_JG , 1, 1, SCF_X64_I);
scf_x64_OpCode_t* lea = x64_find_OpCode(SCF_X64_LEA, 8, 8, SCF_X64_E2G);
scf_x64_OpCode_t* call = x64_find_OpCode(SCF_X64_CALL,4, 4, SCF_X64_I);
- scf_x64_OpCode_t* sub = x64_find_OpCode(SCF_X64_SUB, 8, 8, SCF_X64_E2G);
- scf_x64_OpCode_t* add = x64_find_OpCode(SCF_X64_ADD, 4, 8, SCF_X64_I2E);
- scf_x64_OpCode_t* and = x64_find_OpCode(SCF_X64_AND, 4, 8, SCF_X64_I2E);
- scf_x64_OpCode_t* mov = x64_find_OpCode(SCF_X64_MOV, 8, 8, SCF_X64_G2E);
scf_x64_OpCode_t* xor = x64_find_OpCode(SCF_X64_XOR, 8, 8, SCF_X64_G2E);
+ scf_x64_OpCode_t* mov = x64_find_OpCode(SCF_X64_MOV, 8, 8, SCF_X64_G2E);
if (!c->instructions) {
c->instructions = scf_vector_alloc();
}
X64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1);
- X64_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0);
- // if src > 0
- uint32_t imm = 0;
- inst = x64_make_inst_I2E(cmp, rs, (uint8_t*)&imm, 1);
+ inst = x64_make_inst_G2E(mov, rsi, rs);
X64_INST_ADD_CHECK(c->instructions, inst);
- jcc = x64_make_inst_I(jg, (uint8_t*)&imm, 1);
- X64_INST_ADD_CHECK(c->instructions, jcc);
-
- // process error when src <= 0
scf_rela_t* rela = NULL;
- int i = c->instructions->size;
-
- inst = x64_make_inst_G2E(mov, rsi, rs);
- X64_INST_ADD_CHECK(c->instructions, inst);
inst = x64_make_inst_M2G(&rela, lea, rdi, NULL, msg->dag_node->var);
X64_INST_ADD_CHECK(c->instructions, inst);
X64_INST_ADD_CHECK(c->instructions, inst);
// call printf() to show msg
+ uint32_t imm = 0;
inst = x64_make_inst_I(call, (uint8_t*)&imm, sizeof(imm));
X64_INST_ADD_CHECK(c->instructions, inst);
inst = x64_make_inst_G2P(mov, rax, 0, rax);
X64_INST_ADD_CHECK(c->instructions, inst);
+ return 0;
+}
+
+static int _x64_inst_vla_alloc_handler(scf_native_t* ctx, scf_3ac_code_t* c)
+{
+ if (!c->dsts || c->dsts->size != 1)
+ return -EINVAL;
+
+ if (!c->srcs || c->srcs->size != 3)
+ return -EINVAL;
- for ( ; i < c->instructions->size; i++) {
- inst = c->instructions->data[i];
- jcc->code[1] += inst->len;
+ scf_x64_context_t* x64 = ctx->priv;
+ scf_function_t* f = x64->f;
+ scf_3ac_operand_t* dst = c->dsts->data[0];
+ scf_3ac_operand_t* src = c->srcs->data[0];
+
+ if (!dst || !dst->dag_node)
+ return -EINVAL;
+
+ if (!src || !src->dag_node)
+ return -EINVAL;
+
+ scf_instruction_t* inst = NULL;
+ scf_register_t* rs = NULL;
+ scf_register_t* rd = NULL;
+ scf_register_t* rsp = x64_find_register("rsp");
+
+ scf_x64_OpCode_t* add = x64_find_OpCode(SCF_X64_ADD, 4, 8, SCF_X64_I2E);
+ scf_x64_OpCode_t* and = x64_find_OpCode(SCF_X64_AND, 4, 8, SCF_X64_I2E);
+ scf_x64_OpCode_t* sub = x64_find_OpCode(SCF_X64_SUB, 8, 8, SCF_X64_E2G);
+ scf_x64_OpCode_t* mov = x64_find_OpCode(SCF_X64_MOV, 8, 8, SCF_X64_G2E);
+
+ if (!c->instructions) {
+ c->instructions = scf_vector_alloc();
+ if (!c->instructions)
+ return -ENOMEM;
}
- // alloc VLA
- imm = 0xf;
+ X64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1);
+
+ uint32_t imm = 0xf;
inst = x64_make_inst_I2E(add, rs, (uint8_t*)&imm, sizeof(imm));
X64_INST_ADD_CHECK(c->instructions, inst);
inst = x64_make_inst_E2G(sub, rsp, rs);
X64_INST_ADD_CHECK(c->instructions, inst);
+ int ret = x64_save_var(src->dag_node, c, f);
+ if (ret < 0)
+ return ret;
+
+ X64_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0);
+
inst = x64_make_inst_G2E(mov, rd, rsp);
X64_INST_ADD_CHECK(c->instructions, inst);
-
- return x64_save_var(src->dag_node, c, f);
+ return 0;
}
static int _x64_inst_vla_free_handler(scf_native_t* ctx, scf_3ac_code_t* c)
[SCF_OP_RETURN ] = _x64_inst_return_handler,
[SCF_OP_GOTO ] = _x64_inst_goto_handler,
+ [SCF_OP_3AC_DUMP ] = _x64_inst_dump_handler,
+
[SCF_OP_3AC_JZ ] = _x64_inst_jz_handler,
[SCF_OP_3AC_JNZ ] = _x64_inst_jnz_handler,
[SCF_OP_3AC_JGT ] = _x64_inst_jgt_handler,
if (!c->srcs || c->srcs->size != 1)
return -EINVAL;
- scf_x64_context_t* x64 = ctx->priv;
- scf_function_t* f = x64->f;
- scf_3ac_operand_t* src = c->srcs->data[0];
- scf_variable_t* var = src->dag_node->var;
+ scf_x64_context_t* x64 = ctx->priv;
+ scf_function_t* f = x64->f;
+ scf_3ac_operand_t* src = c->srcs->data[0];
+ scf_variable_t* v = src->dag_node->var;
scf_x64_OpCode_t* test;
scf_instruction_t* inst;
if (!src || !src->dag_node)
return -EINVAL;
- if (!c->instructions) {
- c->instructions = scf_vector_alloc();
- if (!c->instructions)
- return -ENOMEM;
- }
-
if (0 == src->dag_node->color) {
scf_loge("src->dag_node->var: %p\n", src->dag_node->var);
return -1;
}
- if (src->dag_node->color > 0) {
- X64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 0);
- test = x64_find_OpCode(SCF_X64_TEST, var->size, var->size, SCF_X64_G2E);
- inst = x64_make_inst_G2E(test, rs, rs);
- X64_INST_ADD_CHECK(c->instructions, inst);
-
- } else {
- scf_rela_t* rela = NULL;
- int size = var->size > 4 ? 4 : var->size;
- uint32_t imm = 0xffffffff;
-
- test = x64_find_OpCode(SCF_X64_TEST, size, var->size, SCF_X64_I2E);
- inst = x64_make_inst_I2M(&rela, test, var, NULL, (uint8_t*)&imm, size);
- X64_INST_ADD_CHECK(c->instructions, inst);
- X64_RELA_ADD_CHECK(f->data_relas, rela, c, var, NULL);
+ if (!c->instructions) {
+ c->instructions = scf_vector_alloc();
+ if (!c->instructions)
+ return -ENOMEM;
}
+ X64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1);
+
+ test = x64_find_OpCode(SCF_X64_TEST, v->size, v->size, SCF_X64_G2E);
+ inst = x64_make_inst_G2E(test, rs, rs);
+ X64_INST_ADD_CHECK(c->instructions, inst);
return 0;
}
#include"scf_basic_block.h"
#include"scf_3ac.h"
-static int _x64_peephole_common(scf_vector_t* std_insts, scf_instruction_t* inst)
+static int _x64_peephole_mov(scf_vector_t* std_insts, scf_instruction_t* inst)
{
scf_3ac_code_t* c = inst->c;
scf_basic_block_t* bb = c->basic_block;
scf_instruction_print(inst);
printf("\n");
#endif
+ if (SCF_X64_LEA == std->OpCode->type) {
+
+ if (scf_inst_data_same(&std->dst, &inst->src)
+ && x64_inst_data_is_reg(&inst->dst)) {
+
+ if (std->src.index)
+ inst2 = x64_make_inst_SIB2G((scf_x64_OpCode_t*)std->OpCode,
+ inst->dst.base,
+ std->src.base, std->src.index, std->src.scale, std->src.disp);
+ else
+ inst2 = x64_make_inst_P2G((scf_x64_OpCode_t*)std->OpCode, inst->dst.base, std->src.base, std->src.disp);
+
+ if (!inst2)
+ return -ENOMEM;
+
+ memcpy(inst->code, inst2->code, inst2->len);
+ inst->len = inst2->len;
+
+ inst->OpCode = std->OpCode;
+ inst->src.base = std->src.base;
+ inst->src.index = std->src.index;
+ inst->src.scale = std->src.scale;
+ inst->src.disp = std->src.disp;
+ inst->src.flag = std->src.flag;
+
+ free(inst2);
+ inst2 = NULL;
+ }
+ break;
+ }
+
if (scf_inst_data_same(&std->dst, &inst->dst)) {
if (scf_inst_data_same(&std->src, &inst->src)) {
free(std);
std = NULL;
continue;
+
} else if (scf_inst_data_same(&std->src, &inst->src)) {
+
+ if (std->src.flag && std->dst.base->bytes == inst->dst.base->bytes) {
+
+ inst2 = x64_make_inst_E2G((scf_x64_OpCode_t*)inst->OpCode, inst->dst.base, std->dst.base);
+ if (!inst2)
+ return -ENOMEM;
+
+ memcpy(inst->code, inst2->code, inst2->len);
+ inst->len = inst2->len;
+
+ inst->src.base = std->dst.base;
+ inst->src.index = NULL;
+ inst->src.scale = 0;
+ inst->src.disp = 0;
+ inst->src.flag = 0;
+
+ free(inst2);
+ inst2 = NULL;
+ }
continue;
- } else if (scf_inst_data_same(&std->dst, &inst->src)) {
+ } else if (scf_inst_data_same(&std->dst, &inst->src)) {
std->nb_used++;
if (scf_inst_data_same(&std->src, &inst->dst)) {
for (j = std_insts->size - 1; j >= 0; j--) {
std = std_insts->data[j];
+ if (SCF_X64_LEA == std->OpCode->type)
+ break;
+
if (inst->src.flag) {
if (scf_inst_data_same(&inst->src, &std->src))
}
if (scf_inst_data_same(&inst->src, &std->dst)
- || scf_inst_data_same(&inst->dst, &std->dst)) {
-
- assert(0 == scf_vector_del(std_insts, std));
- }
+ || scf_inst_data_same(&inst->dst, &std->dst))
+ std->nb_used++;
}
return 0;
}
-static void _x64_peephole_function(scf_vector_t* tmp_insts, scf_function_t* f, int jmp_back_flag)
+static int _x64_peephole_movx(scf_vector_t* std_insts, scf_instruction_t* inst)
{
- scf_register_t* rax = x64_find_register("rax");
- scf_register_t* rsp = x64_find_register("rsp");
- scf_register_t* rbp = x64_find_register("rbp");
+ if (!x64_inst_data_is_reg(&inst->src) || !x64_inst_data_is_reg(&inst->dst)) {
+ scf_vector_clear(std_insts, NULL);
+ return 0;
+ }
+
+ scf_3ac_code_t* c = inst->c;
+ scf_basic_block_t* bb = c->basic_block;
+ scf_instruction_t* std;
+ scf_x64_OpCode_t* OpCode;
+ int j;
- scf_register_t* rdi = x64_find_register("rdi");
- scf_register_t* rsi = x64_find_register("rsi");
- scf_register_t* rdx = x64_find_register("rdx");
- scf_register_t* rcx = x64_find_register("rcx");
- scf_register_t* r8 = x64_find_register("r8");
- scf_register_t* r9 = x64_find_register("r9");
+ for (j = std_insts->size - 1; j >= 0; j--) {
+ std = std_insts->data[j];
- scf_instruction_t* inst;
- scf_instruction_t* inst2;
- scf_basic_block_t* bb;
- scf_3ac_code_t* c;
- scf_list_t* l;
+ if (scf_inst_data_same(&std->dst, &inst->src)) {
+ std->nb_used++;
- int i;
- int j;
- int k;
+ if (std->OpCode == inst->OpCode
+ && scf_inst_data_same(&std->src, &inst->src)
+ && scf_inst_data_same(&std->dst, &inst->dst)) {
- for (i = tmp_insts->size - 1; i >= 0; i--) {
- inst = tmp_insts->data[i];
+ assert(0 == scf_vector_del(inst->c->instructions, inst));
+
+ free(inst);
+ inst = NULL;
+ return X64_PEEPHOLE_DEL;
+ }
+ }
+ }
- scf_register_t* r0;
- scf_register_t* r1;
- scf_register_t* r2;
+ assert(0 == scf_vector_add_unique(std_insts, inst));
+ return 0;
+}
- if (!inst)
- continue;
+static int x64_inst_is_useful(scf_instruction_t* inst, scf_instruction_t* std)
+{
+ if (scf_inst_data_same(&inst->dst, &std->src))
+ return 1;
- if (SCF_X64_MOV != inst->OpCode->type)
- continue;
+ if (x64_inst_data_is_reg(&inst->dst)) {
- if (x64_inst_data_is_reg(&inst->dst)) {
+ scf_register_t* r0 = inst->dst.base;
+ scf_register_t* r1 = std->src.base;
- r0 = inst->dst.base;
+ if (SCF_X64_CALL == std->OpCode->type) {
- for (k = 0; k < X64_ABI_RET_NB; k++) {
- r2 = x64_find_register_type_id_bytes(0, x64_abi_ret_regs[k], 8);
+ if (X64_COLOR_CONFLICT(r0->color, x64_find_register("rdi")->color)
+ || X64_COLOR_CONFLICT(r0->color, x64_find_register("rsi")->color)
+ || X64_COLOR_CONFLICT(r0->color, x64_find_register("rdx")->color)
+ || X64_COLOR_CONFLICT(r0->color, x64_find_register("rcx")->color)
+ || X64_COLOR_CONFLICT(r0->color, x64_find_register("r8")->color)
+ || X64_COLOR_CONFLICT(r0->color, x64_find_register("r9")->color))
+ return 1;
- if (X64_COLOR_CONFLICT(r2->color, r0->color))
- break;
+ } else {
+ if (x64_inst_data_is_reg(&std->src)) {
+ if (X64_COLOR_CONFLICT(r0->color, r1->color))
+ return 1;
}
- if (k < X64_ABI_RET_NB)
- continue;
+ if (std->src.base == inst->dst.base
+ || std->src.index == inst->dst.base
+ || std->dst.index == inst->dst.base
+ || std->dst.base == inst->dst.base)
+ return 1;
+ }
- } else if (!x64_inst_data_is_local(&inst->dst))
- continue;
+ } else if (x64_inst_data_is_local(&inst->dst)) {
- if (jmp_back_flag)
- j = 0;
- else
- j = i + 1;
+ if (scf_inst_data_same(&inst->dst, &std->src))
+ return 1;
- for ( ; j < tmp_insts->size; j++) {
- inst2 = tmp_insts->data[j];
+ if (x64_find_register("rsp") == inst->dst.base)
+ return 1;
- if (!inst2 || inst == inst2)
- continue;
+ if (SCF_OP_VA_START == inst->c->op->type
+ || SCF_OP_VA_ARG == inst->c->op->type
+ || SCF_OP_VA_END == inst->c->op->type)
+ return 1;
+
+ if (x64_inst_data_is_pointer(&std->dst) || x64_inst_data_is_pointer(&std->src))
+ return 1;
- if (scf_inst_data_same(&inst->dst, &inst2->src))
+ switch (std->OpCode->type)
+ {
+ case SCF_X64_CMP:
+ case SCF_X64_TEST:
+ if (scf_inst_data_same(&inst->dst, &std->dst))
+ return 1;
break;
- if (x64_inst_data_is_reg(&inst->dst)) {
+ case SCF_X64_MOV:
+ case SCF_X64_LEA:
+ if (std->src.base == inst->dst.base) // maybe array member
+ return 1;
+ break;
+ default:
+ break;
+ };
+ }
+ return 0;
+}
- r0 = inst ->dst.base;
- r1 = inst2->src.base;
+static int x64_inst_useful_3ac(scf_instruction_t* inst, scf_3ac_code_t* c)
+{
+ scf_instruction_t* inst2;
+ int j = 0;
- if (SCF_X64_CALL == inst2->OpCode->type) {
+ if (inst->c == c) {
+ for ( ; j < c->instructions->size; j++) {
+ inst2 = c->instructions->data[j];
- if (X64_COLOR_CONFLICT(r0->color, rdi->color)
- || X64_COLOR_CONFLICT(r0->color, rsi->color)
- || X64_COLOR_CONFLICT(r0->color, rdx->color)
- || X64_COLOR_CONFLICT(r0->color, rcx->color)
- || X64_COLOR_CONFLICT(r0->color, r8->color)
- || X64_COLOR_CONFLICT(r0->color, r9->color))
- break;
+ if (inst2 == inst)
+ break;
+ }
- } else {
- if (x64_inst_data_is_reg(&inst2->src)) {
- if (X64_COLOR_CONFLICT(r0->color, r1->color))
- break;
- }
+ assert(j < c->instructions->size);
+ ++j;
+ }
- if (inst2->src.base == inst->dst.base
- || inst2->src.index == inst->dst.base
- || inst2->dst.index == inst->dst.base
- || inst2->dst.base == inst->dst.base)
- break;
- }
+ if (c->instructions) {
+ for ( ; j < c->instructions->size; j++) {
+ inst2 = c->instructions->data[j];
- } else if (x64_inst_data_is_local(&inst->dst)) {
+ if (x64_inst_is_useful(inst, inst2))
+ return 1;
+ }
+ }
+ return 0;
+}
- if (scf_inst_data_same(&inst->dst, &inst2->src))
- break;
- else if (rsp == inst->dst.base)
- break;
- else if (SCF_OP_VA_START == inst->c->op->type
- || SCF_OP_VA_ARG == inst->c->op->type
- || SCF_OP_VA_END == inst->c->op->type)
- break;
+static int x64_inst_useful_bb(scf_instruction_t* inst, scf_basic_block_t* bb)
+{
+ scf_3ac_code_t* c;
+ scf_list_t* l;
- else if (SCF_X64_CMP == inst2->OpCode->type
- || SCF_X64_TEST == inst2->OpCode->type) {
+ if (bb == inst->c->basic_block)
+ l = &inst->c->list;
+ else
+ l = scf_list_head(&bb->code_list_head);
- if (scf_inst_data_same(&inst->dst, &inst2->dst))
- break;
+ for ( ; l != scf_list_sentinel(&bb->code_list_head); l = scf_list_next(l)) {
+ c = scf_list_data(l, scf_3ac_code_t, list);
- } else if (SCF_X64_LEA == inst2->OpCode->type
- || SCF_X64_MOV == inst2->OpCode->type) {
+ if (x64_inst_useful_3ac(inst, c))
+ return 1;
+ }
- if (inst2->src.base == inst->dst.base
- && inst2->src.index) // maybe array member
- break;
- }
- }
- }
+ return 0;
+}
- if (j < tmp_insts->size)
+static int __x64_inst_useful_bb_next(scf_basic_block_t* bb, void* data, scf_vector_t* queue)
+{
+ scf_instruction_t* inst = data;
+ scf_basic_block_t* bb2;
+ int j;
+
+ if (x64_inst_useful_bb(inst, bb))
+ return 1;
+
+ for (j = 0; j < bb->nexts->size; j++) {
+ bb2 = bb->nexts->data[j];
+
+ int ret = scf_vector_add(queue, bb2);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int _x64_peephole_function(scf_vector_t* tmp_insts, scf_function_t* f)
+{
+ scf_instruction_t* inst;
+ scf_basic_block_t* bb;
+ scf_3ac_code_t* c;
+ int i;
+
+ for (i = tmp_insts->size - 1; i >= 0; i--) {
+ inst = tmp_insts->data[i];
+
+ if (SCF_X64_MOV != inst->OpCode->type)
+ continue;
+
+ if (x64_inst_data_is_reg(&inst->dst)) {
+
+ if (x64_reg_is_retval(inst->dst.base))
+ continue;
+
+ } else if (!x64_inst_data_is_local(&inst->dst))
continue;
c = inst->c;
+ bb = c->basic_block;
+
+ int ret = scf_basic_block_search_bfs(bb, __x64_inst_useful_bb_next, inst);
+ if (ret < 0)
+ return ret;
+
+ if (ret > 0)
+ continue;
assert(0 == scf_vector_del(c->instructions, inst));
assert(0 == scf_vector_del(tmp_insts, inst));
inst = NULL;
}
- int nb_locals = 0;
+ int n_locals = 0;
for (i = 0; i < tmp_insts->size; i++) {
inst = tmp_insts->data[i];
- if (!inst)
- continue;
-
- if (x64_inst_data_is_local(&inst->src)
- || x64_inst_data_is_local(&inst->dst))
- nb_locals++;
+ if (x64_inst_data_is_local(&inst->src) || x64_inst_data_is_local(&inst->dst))
+ n_locals++;
}
- if (nb_locals > 0)
+ if (n_locals > 0)
f->bp_used_flag = 1;
else
f->bp_used_flag = 0;
scf_logw("%s(), f->bp_used_flag: %d\n", f->node.w->text->data, f->bp_used_flag);
+ return 0;
}
int x64_optimize_peephole(scf_native_t* ctx, scf_function_t* f)
if (bb->jmp_flag) {
scf_vector_clear(std_insts, NULL);
- ret = scf_vector_add(tmp_insts, NULL);
- if (ret < 0)
- goto error;
-
l2 = scf_list_head(&bb->code_list_head);
c = scf_list_data(l2, scf_3ac_code_t, list);
if (bb->jmp_dst_flag) {
scf_vector_clear(std_insts, NULL);
-
- ret = scf_vector_add(tmp_insts, NULL);
- if (ret < 0)
- goto error;
}
for (l2 = scf_list_head(&bb->code_list_head); l2 != scf_list_sentinel(&bb->code_list_head);
inst->c = c;
// scf_instruction_print(inst);
- if (SCF_X64_CMP == inst->OpCode->type || SCF_X64_TEST == inst->OpCode->type) {
+ ret = 0;
+ switch (inst->OpCode->type) {
- ret = _x64_peephole_cmp(std_insts, inst);
- if (ret < 0)
- goto error;
+ case SCF_X64_CMP:
+ case SCF_X64_TEST:
+ ret = _x64_peephole_cmp(std_insts, inst);
+ break;
- } else if (SCF_X64_MOV == inst->OpCode->type) {
+ case SCF_X64_MOV:
+ ret = _x64_peephole_mov(std_insts, inst);
+ break;
- ret = _x64_peephole_common(std_insts, inst);
- if (ret < 0)
- goto error;
+ case SCF_X64_LEA:
+ ret = scf_vector_add_unique(std_insts, inst);
+ break;
- if (X64_PEEPHOLE_DEL == ret)
- continue;
+ case SCF_X64_MOVSS:
+ case SCF_X64_MOVSD:
+ break;
+ default:
+ scf_vector_clear(std_insts, NULL);
+ break;
+ };
- } else {
- scf_vector_clear(std_insts, NULL);
- }
+ if (ret < 0)
+ goto error;
+
+ if (X64_PEEPHOLE_DEL == ret)
+ continue;
ret = scf_vector_add(tmp_insts, inst);
if (ret < 0)
}
}
- _x64_peephole_function(tmp_insts, f, jmp_back_flag);
-#if 0
- for (i = 0; i < tmp_insts->size; i++) {
- inst = tmp_insts->data[i];
-
- if (!inst)
- continue;
-
- if (SCF_X64_MOV != inst->OpCode->type
- || !x64_inst_data_is_local(&inst->src))
- continue;
-
- scf_logw("\n");
- scf_instruction_print(inst);
-
- for (j = i - 1; j >= 0; j--) {
- std = tmp_insts->data[j];
-
- if (!std)
- break;
-
- if (scf_inst_data_same(&std->dst, &inst->src)
- || scf_inst_data_same(&std->dst, &inst->dst)) {
- printf("-------\n");
- scf_instruction_print(std);
- break;
- }
- }
- printf("\n");
- }
-#endif
- ret = 0;
+ ret = _x64_peephole_function(tmp_insts, f);
error:
scf_vector_free(tmp_insts);
scf_vector_free(std_insts);
return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL);
}
+static int _x64_rcg_dump_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g)
+{
+ int ret = _x64_rcg_make2(c, NULL, NULL, NULL);
+ if (ret < 0)
+ return ret;
+
+ return _x64_rcg_make(c, g, NULL, NULL, NULL);
+}
+
static int _x64_rcg_cmp_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g)
{
int ret = _x64_rcg_make2(c, NULL, NULL, NULL);
[SCF_OP_3AC_CMP ] = _x64_rcg_cmp_handler,
[SCF_OP_3AC_TEQ ] = _x64_rcg_teq_handler,
+ [SCF_OP_3AC_DUMP ] = _x64_rcg_dump_handler,
[SCF_OP_3AC_SETZ ] = _x64_rcg_setz_handler,
[SCF_OP_3AC_SETNZ ] = _x64_rcg_setnz_handler,
void x64_call_rabi(int* p_nints, int* p_nfloats, scf_3ac_code_t* c);
+static inline int x64_reg_is_retval(scf_register_t* r)
+{
+ scf_register_t* r2;
+ int k;
+
+ for (k = 0; k < X64_ABI_RET_NB; k++) {
+ r2 = x64_find_register_type_id_bytes(0, x64_abi_ret_regs[k], 8);
+
+ if (X64_COLOR_CONFLICT(r2->color, r->color))
+ return 1;
+ }
+
+ return 0;
+}
static inline int x64_inst_data_is_reg(scf_inst_data_t* id)
{
return 0;
}
+static inline int x64_inst_data_is_pointer(scf_inst_data_t* id)
+{
+ scf_register_t* rbp = x64_find_register("rbp");
+ scf_register_t* rsp = x64_find_register("rsp");
+
+ if (id->flag && id->base && id->base != rbp && id->base != rsp)
+ return 1;
+ return 0;
+}
+
#endif
CFILES += ../core/scf_optimizer.c
CFILES += ../core/scf_optimizer_dag.c
CFILES += ../core/scf_optimizer_inline.c
+CFILES += ../core/scf_optimizer_split_call.c
CFILES += ../core/scf_optimizer_call.c
CFILES += ../core/scf_optimizer_common_expr.c
CFILES += ../core/scf_optimizer_pointer_alias.c