[qfcc] Fold int constants more aggressively

This code now reaches into one level of the expression tree and
rearranges the nodes to allow the constant folder to do its things, but
only for ints, and only when the folding is trivially correct (* and *,
+/- and +/-). There may be more opportunities, but these cover what I
needed for now and anything more will need code generation or smarter
tree manipulation as things are getting out of hand.
This commit is contained in:
Bill Currie 2022-01-29 15:38:39 +09:00
parent 284fcd312d
commit 54e079ab75
3 changed files with 153 additions and 0 deletions

View file

@ -80,6 +80,18 @@ cmp_result_expr (int result)
}
}
static int
is_addsub (int op)
{
return op == '+' || op == '-';
}
static int
inv_addsub (int op)
{
return op == '+' ? '-' : '+';
}
static expr_t *
do_op_string (int op, expr_t *e, expr_t *e1, expr_t *e2)
{
@ -819,6 +831,60 @@ do_op_int (int op, expr_t *e, expr_t *e1, expr_t *e2)
if (op == '-' && isval2 && val2 == 0)
return e1;
if (!isval1) {
if (e1->type == ex_expr) {
// at most one of the two sub-expressions is constant otherwise
// e1 would be a constant
if (is_constant (e1->e.expr.e1)) {
if ((op == '*' && e1->e.expr.op == '*')
|| (is_addsub (op) && is_addsub (e1->e.expr.op))) {
expr_t *c = binary_expr (op, e1->e.expr.e1, e2);
e = binary_expr (e1->e.expr.op, c, e1->e.expr.e2);
}
} else if (is_constant (e1->e.expr.e2)) {
if ((op == '*' && e1->e.expr.op == '*')
|| (is_addsub (op) && e1->e.expr.op == '+')) {
expr_t *c = binary_expr (op, e1->e.expr.e2, e2);
e = binary_expr (e1->e.expr.op, e1->e.expr.e1, c);
} else if (is_addsub (op) && e1->e.expr.op == '-') {
// must ivert op
expr_t *c = binary_expr (inv_addsub (op),
e1->e.expr.e2, e2);
e = binary_expr (e1->e.expr.op, e1->e.expr.e1, c);
}
}
}
return e;
} else if (!isval2) {
if (e2->type == ex_expr) {
// at most one of the two sub-expressions is constant otherwise
// e2 would be a constant
if (is_constant (e2->e.expr.e1)) {
if ((op == '*' && e2->e.expr.op == '*')
|| (op == '+' && is_addsub (e2->e.expr.op))) {
expr_t *c = binary_expr (op, e1, e2->e.expr.e1);
e = binary_expr (e2->e.expr.op, c, e2->e.expr.e2);
} else if (op == '-' && is_addsub (e2->e.expr.op)) {
expr_t *c = binary_expr (op, e1, e2->e.expr.e1);
c = fold_constants (c);
e = binary_expr (inv_addsub (e2->e.expr.op),
c, e2->e.expr.e2);
}
} else if (is_constant (e2->e.expr.e2)) {
if ((op == '*' && e2->e.expr.op == '*')
|| (op == '+' && is_addsub (e2->e.expr.op))) {
expr_t *c = binary_expr (e2->e.expr.op,
e1, e2->e.expr.e2);
e = binary_expr (op, c, e2->e.expr.e1);
} else if (op == '-' && is_addsub (e2->e.expr.op)) {
expr_t *c = binary_expr (inv_addsub (e2->e.expr.op),
e1, e2->e.expr.e2);
e = binary_expr (op, c, e2->e.expr.e1);
}
}
}
return e;
}
if (!isval1 || !isval2)
return e;

View file

@ -16,6 +16,7 @@ test_progs_dat=\
tools/qfcc/test/chewed-return.dat \
tools/qfcc/test/comma-expr.dat \
tools/qfcc/test/compound.dat \
tools/qfcc/test/const-fold-int.dat \
tools/qfcc/test/deadbool.dat \
tools/qfcc/test/dealloc-nowarn.dat \
tools/qfcc/test/dealloc-nowarn2.dat \
@ -195,6 +196,16 @@ tools/qfcc/test/compound.run: $(qfcc_test_run_deps)
include $(compound_dep) # am--include-marker
r_depfiles_remade += $(compound_dep)
tools_qfcc_test_const_fold_int_dat_SOURCES=tools/qfcc/test/const-fold-int.r
const_fold_int_obj=$(tools_qfcc_test_const_fold_int_dat_SOURCES:.r=.o)
const_fold_int_dep=$(call qcautodep,$(tools_qfcc_test_const_fold_int_dat_SOURCES))
tools/qfcc/test/const-fold-int.dat$(EXEEXT): $(const_fold_int_obj) $(QFCC_DEP)
$(V_QFCCLD)$(QLINK) -o $@ $(const_fold_int_obj)
tools/qfcc/test/const-fold-int.run: $(qfcc_test_run_deps)
@$(top_srcdir)/tools/qfcc/test/build-run $@
include $(const_fold_int_dep) # am--include-marker
r_depfiles_remade += $(const_fold_int_dep)
tools_qfcc_test_deadbool_dat_SOURCES=tools/qfcc/test/deadbool.r
deadbool_obj=$(tools_qfcc_test_deadbool_dat_SOURCES:.r=.o)
deadbool_dep=$(call qcautodep,$(tools_qfcc_test_deadbool_dat_SOURCES))

View file

@ -0,0 +1,76 @@
int mul_e_c_t_c (int x) { return x * 6 * 7; }
int mul_c_e_t_c (int x) { return 6 * x * 7; }
int mul_c_c_t_e (int x) { return 6 * 7 * x; }
int mul_e_t_c_c (int x) { return x * (6 * 7); }
int mul_c_t_e_c (int x) { return 6 * (x * 7); }
int mul_c_t_c_e (int x) { return 6 * (7 * x); }
int addadd_e_c_t_c (int x) { return x + 6 + 7; }
int addadd_c_e_t_c (int x) { return 6 + x + 7; }
int addadd_c_c_t_e (int x) { return 6 + 7 + x; }
int addadd_e_t_c_c (int x) { return x + (6 + 7); }
int addadd_c_t_e_c (int x) { return 6 + (x + 7); }
int addadd_c_t_c_e (int x) { return 6 + (7 + x); }
int addsub_e_c_t_c (int x) { return x + 6 - 7; }
int addsub_c_e_t_c (int x) { return 6 + x - 7; }
int addsub_c_c_t_e (int x) { return 6 + 7 - x; }
int addsub_e_t_c_c (int x) { return x + (6 - 7); }
int addsub_c_t_e_c (int x) { return 6 + (x - 7); }
int addsub_c_t_c_e (int x) { return 6 + (7 - x); }
int subadd_e_c_t_c (int x) { return x - 6 + 7; }
int subadd_c_e_t_c (int x) { return 6 - x + 7; }
int subadd_c_c_t_e (int x) { return 6 - 7 + x; }
int subadd_e_t_c_c (int x) { return x - (6 + 7); }
int subadd_c_t_e_c (int x) { return 6 - (x + 7); }
int subadd_c_t_c_e (int x) { return 6 - (7 + x); }
int subsub_e_c_t_c (int x) { return x - 6 - 7; }
int subsub_c_e_t_c (int x) { return 6 - x - 7; }
int subsub_c_c_t_e (int x) { return 6 - 7 - x; }
int subsub_e_t_c_c (int x) { return x - (6 - 7); }
int subsub_c_t_e_c (int x) { return 6 - (x - 7); }
int subsub_c_t_c_e (int x) { return 6 - (7 - x); }
int
main ()
{
int fail = 0;
fail |= mul_e_c_t_c (10) != 420;
fail |= mul_c_e_t_c (10) != 420;
fail |= mul_c_c_t_e (10) != 420;
fail |= mul_e_t_c_c (10) != 420;
fail |= mul_c_t_e_c (10) != 420;
fail |= mul_c_t_c_e (10) != 420;
fail |= addadd_e_c_t_c (29) != 42;
fail |= addadd_c_e_t_c (29) != 42;
fail |= addadd_c_c_t_e (29) != 42;
fail |= addadd_e_t_c_c (29) != 42;
fail |= addadd_c_t_e_c (29) != 42;
fail |= addadd_c_t_c_e (29) != 42;
fail |= addsub_e_c_t_c (43) != 42;
fail |= addsub_c_e_t_c (43) != 42;
fail |= addsub_c_c_t_e (-29) != 42;
fail |= addsub_e_t_c_c (43) != 42;
fail |= addsub_c_t_e_c (43) != 42;
fail |= addsub_c_t_c_e (-29) != 42;
fail |= subadd_e_c_t_c (41) != 42;
fail |= subadd_c_e_t_c (-29) != 42;
fail |= subadd_c_c_t_e (43) != 42;
fail |= subadd_e_t_c_c (55) != 42;
fail |= subadd_c_t_e_c (-43) != 42;
fail |= subadd_c_t_c_e (-43) != 42;
fail |= subsub_e_c_t_c (55) != 42;
fail |= subsub_c_e_t_c (-43) != 42;
fail |= subsub_c_c_t_e (-43) != 42;
fail |= subsub_e_t_c_c (41) != 42;
fail |= subsub_c_t_e_c (-29) != 42;
fail |= subsub_c_t_c_e (43) != 42;
return fail;
}