[qfcc] Convert dot of scales to scaled dot

That is, dot(scale(A,a),scale(B,b)) -> (a*b)*dot(A,B). Does the right
thing when only one side is a scale. No change to the instruction count
in my fancy zero, but it does open more opportunities when I distribute
products.
This commit is contained in:
Bill Currie 2023-09-28 16:36:42 +09:00
parent 4bf6ce45d4
commit 2bf855657c

View file

@ -391,18 +391,17 @@ mvec_gather (const expr_t **components, algebra_t *algebra)
}
return mvec;
}
#if 0
static const expr_t *
extract_extended_neg (const expr_t *expr)
static bool __attribute__((pure))
is_scale (const expr_t *expr)
{
auto e = expr->extend;
return neg_expr (ext_expr (neg_expr (e.src), e.type, e.extend, e.reverse));
return expr && expr->type == ex_expr && expr->expr.op == SCALE;
}
#endif
static const expr_t * __attribute__((pure))
traverse_scale (const expr_t *expr)
{
while (expr && expr->type == ex_expr && expr->expr.op == SCALE) {
while (is_scale (expr)) {
expr = expr->expr.e1;
}
return expr;
@ -656,7 +655,7 @@ scale_expr (type_t *type, const expr_t *a, const expr_t *b)
b = neg_expr (b);
}
if (a->type == ex_expr && a->expr.op == SCALE) {
if (is_scale (a)) {
// covert scale (scale (X, y), z) to scale (X, y*z)
b = scale_expr (get_type (b), b, a->expr.e2);
a = a->expr.e1;
@ -739,8 +738,22 @@ dot_expr (type_t *type, const expr_t *a, const expr_t *b)
return 0;
}
const expr_t *prod = 0;
if (is_scale (a)) {
prod = a->expr.e2;
a = a->expr.e1;
}
if (is_scale (b)) {
auto s = b->expr.e2;
prod = prod ? scale_expr (get_type (prod), prod, s) : s;
b = b->expr.e1;
}
auto dot = typed_binary_expr (type, DOT, a, b);
dot = edag_add_expr (dot);
if (prod) {
dot = scale_expr (type, dot, prod);
}
if (neg) {
dot = neg_expr (dot);
dot = edag_add_expr (dot);