[qfcc] Merge extend expressions through sums

This takes care of chained sums of extend expressions. Now `l p ~l` has
only four extend instructions which is expected for the code not
detecting the cross product that always produces 0.
This commit is contained in:
Bill Currie 2023-09-02 18:46:14 +09:00
parent 924c13f925
commit c2472e99fa
1 changed files with 45 additions and 15 deletions

View File

@ -306,6 +306,14 @@ promote_scalar (type_t *dst_type, expr_t *scalar)
return scalar;
}
static bool __attribute__((const))
ext_compat (const expr_t *a, const expr_t *b)
{
return (a->e.extend.extend == b->e.extend.extend
&& a->e.extend.reverse == b->e.extend.reverse
&& a->e.extend.type == b->e.extend.type);
}
static expr_t *
sum_expr (type_t *type, expr_t *a, expr_t *b)
{
@ -315,24 +323,46 @@ sum_expr (type_t *type, expr_t *a, expr_t *b)
if (!b) {
return a;
}
expr_t *ext = 0;
if (a->type == ex_extend && b->type == ex_extend) {
if (a->e.extend.extend == b->e.extend.extend
&& a->e.extend.reverse == b->e.extend.reverse
&& a->e.extend.type == b->e.extend.type) {
ext = a; // for copying extend info;
a = a->e.extend.src;
b = b->e.extend.src;
if (a->type != ex_extend && b->type == ex_extend) {
// ensure always ext + something
return sum_expr (type, b, a);
}
if (a->type == ex_extend) {
if (b->type == ex_extend) {
if (ext_compat (a, b)) {
auto ext = a->e.extend;
a = a->e.extend.src;
b = b->e.extend.src;
auto sum = sum_expr (get_type (a), a, b);
return ext_expr (sum, type, ext.extend, ext.reverse);
}
} else if (b->type == ex_expr && b->e.expr.op == '+') {
auto c = b->e.expr.e1;
auto d = b->e.expr.e2;
if (ext_compat (a, c)) {
// d should not be compatible with a because it should have
// already been merged
auto ext = a->e.extend;
a = a->e.extend.src;
c = c->e.extend.src;
auto sum = sum_expr (get_type (a), a, c);
sum = ext_expr (sum, type, ext.extend, ext.reverse);
return sum_expr (type, sum, d);
}
if (ext_compat (a, d)) {
// c should not be compatible with a because it should have
// already been merged
auto ext = a->e.extend;
a = a->e.extend.src;
d = d->e.extend.src;
auto sum = sum_expr (get_type (a), a, d);
sum = ext_expr (sum, type, ext.extend, ext.reverse);
return sum_expr (type, sum, c);
}
}
}
auto sum = new_binary_expr ('+', a, b);
if (ext) {
sum->e.expr.type = get_type (a);
auto extend = ext->e.extend;
sum = ext_expr (sum, type, extend.extend, extend.reverse);
} else {
sum->e.expr.type = type;
}
sum->e.expr.type = type;
return sum;
}