mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-25 13:51:36 +00:00
[qfcc] Apply algebraic rules to products of negatives
Any geometric algebra product of two negatives cancels out the negative, and if the result is negative (because only one operand was negative), the negation is migrated to above the operation. This resulted in removing 2 instructions from one if my mini-tests (went from 74 to 78 with the addition/subtraction change, but this takes it back to 76 instructions).
This commit is contained in:
parent
74e9b6b7dd
commit
4135849903
1 changed files with 77 additions and 7 deletions
|
@ -295,6 +295,24 @@ sum_expr (type_t *type, expr_t *a, expr_t *b)
|
|||
return sum;
|
||||
}
|
||||
|
||||
static bool __attribute__((const))
|
||||
is_neg (const expr_t *e)
|
||||
{
|
||||
return e->type == ex_uexpr && e->e.expr.op == '-';
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
neg_expr (expr_t *e)
|
||||
{
|
||||
if (is_neg (e)) {
|
||||
return e->e.expr.e1;
|
||||
}
|
||||
auto type = get_type (e);
|
||||
e = new_unary_expr ('-', e);
|
||||
e->e.expr.type = type;
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
scale_expr (type_t *type, expr_t *a, expr_t *b)
|
||||
{
|
||||
|
@ -306,28 +324,66 @@ scale_expr (type_t *type, expr_t *a, expr_t *b)
|
|||
}
|
||||
int op = is_scalar (get_type (a)) ? '*' : SCALE;
|
||||
|
||||
bool neg = false;
|
||||
if (is_neg (a)) {
|
||||
neg = !neg;
|
||||
a = neg_expr (a);
|
||||
}
|
||||
if (is_neg (b)) {
|
||||
neg = !neg;
|
||||
b = neg_expr (b);
|
||||
}
|
||||
|
||||
auto scale = new_binary_expr (op, a, b);
|
||||
scale->e.expr.type = type;
|
||||
return fold_constants (scale);
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
neg_expr (expr_t *e)
|
||||
{
|
||||
return unary_expr ('-', e);
|
||||
scale = fold_constants (scale);
|
||||
if (neg) {
|
||||
scale = neg_expr (scale);
|
||||
scale->e.expr.type = type;
|
||||
scale = fold_constants (scale);
|
||||
}
|
||||
return scale;
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
dot_expr (type_t *type, expr_t *a, expr_t *b)
|
||||
{
|
||||
bool neg = false;
|
||||
if (is_neg (a)) {
|
||||
neg = !neg;
|
||||
a = neg_expr (a);
|
||||
}
|
||||
if (is_neg (b)) {
|
||||
neg = !neg;
|
||||
b = neg_expr (b);
|
||||
}
|
||||
|
||||
auto dot = new_binary_expr (DOT, a, b);
|
||||
dot->e.expr.type = type;
|
||||
if (neg) {
|
||||
dot = neg_expr (dot);
|
||||
dot->e.expr.type = type;
|
||||
}
|
||||
return dot;
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
cross_expr (type_t *type, expr_t *a, expr_t *b)
|
||||
{
|
||||
bool neg = false;
|
||||
if (is_neg (a)) {
|
||||
neg = !neg;
|
||||
a = neg_expr (a);
|
||||
}
|
||||
if (is_neg (b)) {
|
||||
neg = !neg;
|
||||
b = neg_expr (b);
|
||||
}
|
||||
if (neg) {
|
||||
auto t = a;
|
||||
a = b;
|
||||
b = t;
|
||||
}
|
||||
auto cross = new_binary_expr (CROSS, a, b);
|
||||
cross->e.expr.type = type;
|
||||
return cross;
|
||||
|
@ -336,6 +392,20 @@ cross_expr (type_t *type, expr_t *a, expr_t *b)
|
|||
static expr_t *
|
||||
wedge_expr (type_t *type, expr_t *a, expr_t *b)
|
||||
{
|
||||
bool neg = false;
|
||||
if (is_neg (a)) {
|
||||
neg = !neg;
|
||||
a = neg_expr (a);
|
||||
}
|
||||
if (is_neg (b)) {
|
||||
neg = !neg;
|
||||
b = neg_expr (b);
|
||||
}
|
||||
if (neg) {
|
||||
auto t = a;
|
||||
a = b;
|
||||
b = t;
|
||||
}
|
||||
auto cross = new_binary_expr (WEDGE, a, b);
|
||||
cross->e.expr.type = type;
|
||||
return cross;
|
||||
|
|
Loading…
Reference in a new issue