[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

View file

@ -306,6 +306,14 @@ promote_scalar (type_t *dst_type, expr_t *scalar)
return 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 * static expr_t *
sum_expr (type_t *type, expr_t *a, expr_t *b) 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) { if (!b) {
return a; return a;
} }
expr_t *ext = 0; if (a->type != ex_extend && b->type == ex_extend) {
if (a->type == ex_extend && b->type == ex_extend) { // ensure always ext + something
if (a->e.extend.extend == b->e.extend.extend return sum_expr (type, b, a);
&& a->e.extend.reverse == b->e.extend.reverse }
&& a->e.extend.type == b->e.extend.type) { if (a->type == ex_extend) {
ext = a; // for copying extend info; if (b->type == ex_extend) {
a = a->e.extend.src; if (ext_compat (a, b)) {
b = b->e.extend.src; 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); auto sum = new_binary_expr ('+', a, b);
if (ext) { sum->e.expr.type = type;
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;
}
return sum; return sum;
} }