mirror of
https://github.com/SimonFJ20/bfjit
synced 2026-01-16 05:27:30 +01:00
223 lines
5.9 KiB
C
223 lines
5.9 KiB
C
#include "optimizer.h"
|
|
#include "expr.h"
|
|
|
|
/*
|
|
* fold adjecent
|
|
*
|
|
* A(N) :: { Incr(N) | Decr(N) | Right(N) | Left(N) }
|
|
*
|
|
* [A(N1) A(N2)] -> [A(N1 + N2)]
|
|
*
|
|
*/
|
|
|
|
ExprVec optimize_fold_adjecent(const ExprVec* vec)
|
|
{
|
|
ExprVec exprs;
|
|
expr_vec_construct(&exprs);
|
|
if (vec->length == 0) {
|
|
return exprs;
|
|
}
|
|
Expr a = expr_optimize_fold_adjecent(&vec->data[0]);
|
|
for (size_t i = 1; i < vec->length; ++i) {
|
|
Expr b = expr_optimize_fold_adjecent(&vec->data[i]);
|
|
switch (a.type) {
|
|
case ExprType_Incr:
|
|
case ExprType_Decr:
|
|
case ExprType_Left:
|
|
case ExprType_Right:
|
|
if (a.type != b.type) {
|
|
expr_vec_push(&exprs, a);
|
|
a = b;
|
|
} else {
|
|
a.value += b.value;
|
|
}
|
|
break;
|
|
default:
|
|
expr_vec_push(&exprs, a);
|
|
a = b;
|
|
}
|
|
}
|
|
expr_vec_push(&exprs, a);
|
|
return exprs;
|
|
}
|
|
|
|
Expr expr_optimize_fold_adjecent(const Expr* expr)
|
|
{
|
|
if (expr->type == ExprType_Loop) {
|
|
return (Expr) {
|
|
.type = ExprType_Loop,
|
|
.exprs = optimize_fold_adjecent(&expr->exprs),
|
|
};
|
|
} else {
|
|
return *expr;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* eliminate negation
|
|
*
|
|
* A(N), B(N) :: { Incr(N) | Decr(N) | Right(N) | Left(N) }
|
|
*
|
|
* [A(N) B(N)] = []
|
|
*
|
|
* [A(N1) B(N2)] ? N1 == N2 -> []
|
|
* [A(N1) B(N2)] ? N1 < N2 -> [B(N2 - N1)]
|
|
* [A(N1) B(N2)] ? N1 > N2 -> [A(N1 - N2)]
|
|
*
|
|
*/
|
|
|
|
ExprVec optimize_eliminate_negation(const ExprVec* vec)
|
|
{
|
|
ExprVec exprs;
|
|
expr_vec_construct(&exprs);
|
|
if (vec->length == 0) {
|
|
return exprs;
|
|
}
|
|
expr_vec_push(&exprs, expr_optimize_eliminate_negation(&vec->data[0]));
|
|
for (size_t i = 1; i < vec->length; ++i) {
|
|
expr_vec_push(&exprs, expr_optimize_eliminate_negation(&vec->data[i]));
|
|
Expr* a = &exprs.data[i - 1];
|
|
Expr* b = &exprs.data[i];
|
|
if (a->type == ExprType_Incr && b->type == ExprType_Decr) {
|
|
if (a->value > b->value) {
|
|
a->value -= b->value;
|
|
expr_vec_pop(&exprs);
|
|
} else if (a->value < b->value) {
|
|
*a = (Expr) { .type = ExprType_Decr,
|
|
.value = b->value - a->value };
|
|
expr_vec_pop(&exprs);
|
|
} else {
|
|
expr_vec_pop(&exprs);
|
|
expr_vec_pop(&exprs);
|
|
}
|
|
} else if (a->type == ExprType_Decr && b->type == ExprType_Incr) {
|
|
if (a->value > b->value) {
|
|
a->value -= b->value;
|
|
expr_vec_pop(&exprs);
|
|
} else if (a->value < b->value) {
|
|
*a = (Expr) { .type = ExprType_Incr,
|
|
.value = b->value - a->value };
|
|
expr_vec_pop(&exprs);
|
|
} else {
|
|
expr_vec_pop(&exprs);
|
|
expr_vec_pop(&exprs);
|
|
}
|
|
}
|
|
if (a->type == ExprType_Left && b->type == ExprType_Right) {
|
|
if (a->value > b->value) {
|
|
a->value -= b->value;
|
|
expr_vec_pop(&exprs);
|
|
} else if (a->value < b->value) {
|
|
*a = (Expr) { .type = ExprType_Right,
|
|
.value = b->value - a->value };
|
|
expr_vec_pop(&exprs);
|
|
} else {
|
|
expr_vec_pop(&exprs);
|
|
expr_vec_pop(&exprs);
|
|
}
|
|
} else if (a->type == ExprType_Right && b->type == ExprType_Left) {
|
|
if (a->value > b->value) {
|
|
a->value -= b->value;
|
|
expr_vec_pop(&exprs);
|
|
} else if (a->value < b->value) {
|
|
*a = (Expr) { .type = ExprType_Left,
|
|
.value = b->value - a->value };
|
|
expr_vec_pop(&exprs);
|
|
} else {
|
|
expr_vec_pop(&exprs);
|
|
expr_vec_pop(&exprs);
|
|
}
|
|
}
|
|
}
|
|
return exprs;
|
|
}
|
|
|
|
Expr expr_optimize_eliminate_negation(const Expr* expr)
|
|
{
|
|
if (expr->type == ExprType_Loop) {
|
|
return (Expr) {
|
|
.type = ExprType_Loop,
|
|
.exprs = optimize_eliminate_negation(&expr->exprs),
|
|
};
|
|
} else {
|
|
return *expr;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* eliminate overflow
|
|
*
|
|
* A(N) :: { Incr(N) | Decr(N) | Right(N) | Left(N) }
|
|
*
|
|
* N > 255
|
|
*
|
|
* A(N) -> A(N % 256)
|
|
*
|
|
*/
|
|
|
|
ExprVec optimize_eliminate_overflow(const ExprVec* vec)
|
|
{
|
|
ExprVec exprs;
|
|
expr_vec_construct(&exprs);
|
|
for (size_t i = 0; i < vec->length; ++i) {
|
|
expr_vec_push(&exprs, expr_optimize_eliminate_overflow(&vec->data[i]));
|
|
}
|
|
return exprs;
|
|
}
|
|
|
|
Expr expr_optimize_eliminate_overflow(const Expr* expr)
|
|
{
|
|
if (expr->type == ExprType_Loop) {
|
|
return (Expr) {
|
|
.type = ExprType_Loop,
|
|
.exprs = optimize_eliminate_overflow(&expr->exprs),
|
|
};
|
|
} else if (expr->value > 255) {
|
|
return (Expr) { .type = expr->type, .value = expr->value % 256 };
|
|
} else {
|
|
return *expr;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* replace zeroing loops
|
|
*
|
|
* A(N) :: { Incr(N) | Decr(N) }
|
|
*
|
|
* N % 2 == 1
|
|
*
|
|
* Loop[A(N)] -> Zero
|
|
*
|
|
*/
|
|
|
|
ExprVec optimize_replace_zeroing_loops(const ExprVec* vec)
|
|
{
|
|
ExprVec exprs;
|
|
expr_vec_construct(&exprs);
|
|
for (size_t i = 0; i < vec->length; ++i) {
|
|
expr_vec_push(
|
|
&exprs, expr_optimize_replace_zeroing_loops(&vec->data[i])
|
|
);
|
|
}
|
|
return exprs;
|
|
}
|
|
|
|
Expr expr_optimize_replace_zeroing_loops(const Expr* expr)
|
|
{
|
|
if (expr->type == ExprType_Loop) {
|
|
if (expr->exprs.length == 1
|
|
&& (expr->exprs.data[0].type == ExprType_Incr
|
|
|| expr->exprs.data[0].type == ExprType_Decr)
|
|
&& expr->exprs.data[0].value % 2 != 0) {
|
|
return (Expr) { .type = ExprType_Zero };
|
|
} else {
|
|
return (Expr) {
|
|
.type = ExprType_Loop,
|
|
.exprs = optimize_replace_zeroing_loops(&expr->exprs),
|
|
};
|
|
}
|
|
} else {
|
|
return *expr;
|
|
}
|
|
}
|