mirror of
https://github.com/SimonFJ20/bfjit
synced 2026-01-16 13:37:29 +01:00
optimize simple copying loop
This commit is contained in:
parent
f4e1f65e85
commit
69713c8a95
72
emitter.c
72
emitter.c
@ -11,6 +11,7 @@ Emitter emitter_create(uint8_t* code_address)
|
|||||||
.pos = 0,
|
.pos = 0,
|
||||||
.loop_counter = 0,
|
.loop_counter = 0,
|
||||||
.cmp_flags_set = false,
|
.cmp_flags_set = false,
|
||||||
|
.rax_contains_copy = false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,6 +53,9 @@ void emitter_push_u64(Emitter* emitter, uint64_t value)
|
|||||||
emitter->pos += 1;
|
emitter->pos += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool is_8(int value) { return value >= -128 && value <= 127; }
|
||||||
|
inline bool is_16(int value) { return value >= -32768 && value <= 32767; }
|
||||||
|
|
||||||
void emitter_emit_expr(Emitter* emitter, Expr* expr)
|
void emitter_emit_expr(Emitter* emitter, Expr* expr)
|
||||||
{
|
{
|
||||||
emitter->cmp_flags_set = false;
|
emitter->cmp_flags_set = false;
|
||||||
@ -61,32 +65,48 @@ void emitter_emit_expr(Emitter* emitter, Expr* expr)
|
|||||||
exit(1);
|
exit(1);
|
||||||
break;
|
break;
|
||||||
case ExprType_Incr:
|
case ExprType_Incr:
|
||||||
// add BYTE [rbx], 1
|
// add BYTE [rbx], <value, rel8>
|
||||||
emitter_push_u8(emitter, 0x80);
|
emitter_push_u8(emitter, 0x80);
|
||||||
emitter_push_u8(emitter, 0x03);
|
emitter_push_u8(emitter, 0x03);
|
||||||
emitter_push_u8(emitter, expr->value);
|
emitter_push_u8(emitter, (uint8_t)expr->value);
|
||||||
emitter->cmp_flags_set = true;
|
emitter->cmp_flags_set = true;
|
||||||
break;
|
break;
|
||||||
case ExprType_Decr:
|
case ExprType_Decr:
|
||||||
// sub BYTE [rbx], 1
|
// sub BYTE [rbx], <value: rel8>
|
||||||
emitter_push_u8(emitter, 0x80);
|
emitter_push_u8(emitter, 0x80);
|
||||||
emitter_push_u8(emitter, 0x2b);
|
emitter_push_u8(emitter, 0x2b);
|
||||||
emitter_push_u8(emitter, expr->value);
|
emitter_push_u8(emitter, (uint8_t)expr->value);
|
||||||
emitter->cmp_flags_set = true;
|
emitter->cmp_flags_set = true;
|
||||||
break;
|
break;
|
||||||
case ExprType_Left:
|
case ExprType_Left:
|
||||||
// sub rbx, 1
|
if (is_8(expr->value)) {
|
||||||
emitter_push_u8(emitter, 0x48);
|
// sub rbx, <value: rel8>
|
||||||
emitter_push_u8(emitter, 0x83);
|
emitter_push_u8(emitter, 0x48);
|
||||||
emitter_push_u8(emitter, 0xeb);
|
emitter_push_u8(emitter, 0x83);
|
||||||
emitter_push_u8(emitter, expr->value);
|
emitter_push_u8(emitter, 0xeb);
|
||||||
|
emitter_push_u8(emitter, (uint8_t)expr->value);
|
||||||
|
} else {
|
||||||
|
// sub rbx, <value: rel32>
|
||||||
|
emitter_push_u8(emitter, 0x48);
|
||||||
|
emitter_push_u8(emitter, 0x81);
|
||||||
|
emitter_push_u8(emitter, 0xeb);
|
||||||
|
emitter_push_u32(emitter, expr->value);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ExprType_Right:
|
case ExprType_Right:
|
||||||
// add rbx, 1
|
if (is_8(expr->value)) {
|
||||||
emitter_push_u8(emitter, 0x48);
|
// add rbx, <value: rel8>
|
||||||
emitter_push_u8(emitter, 0x83);
|
emitter_push_u8(emitter, 0x48);
|
||||||
emitter_push_u8(emitter, 0xc3);
|
emitter_push_u8(emitter, 0x83);
|
||||||
emitter_push_u8(emitter, expr->value);
|
emitter_push_u8(emitter, 0xc3);
|
||||||
|
emitter_push_u8(emitter, (uint8_t)expr->value);
|
||||||
|
} else {
|
||||||
|
// add rbx, <value: rel32>
|
||||||
|
emitter_push_u8(emitter, 0x48);
|
||||||
|
emitter_push_u8(emitter, 0x81);
|
||||||
|
emitter_push_u8(emitter, 0xc3);
|
||||||
|
emitter_push_u32(emitter, expr->value);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ExprType_Output:
|
case ExprType_Output:
|
||||||
// movzx edi, BYTE [rbx]
|
// movzx edi, BYTE [rbx]
|
||||||
@ -124,6 +144,30 @@ void emitter_emit_expr(Emitter* emitter, Expr* expr)
|
|||||||
emitter_push_u8(emitter, 0x00);
|
emitter_push_u8(emitter, 0x00);
|
||||||
emitter->cmp_flags_set = true;
|
emitter->cmp_flags_set = true;
|
||||||
break;
|
break;
|
||||||
|
case ExprType_Add:
|
||||||
|
if (!emitter->rax_contains_copy) {
|
||||||
|
// movzx rax, BYTE [rbx]
|
||||||
|
emitter_push_u8(emitter, 0x48);
|
||||||
|
emitter_push_u8(emitter, 0x0f);
|
||||||
|
emitter_push_u8(emitter, 0xb6);
|
||||||
|
emitter_push_u8(emitter, 0x03);
|
||||||
|
emitter->rax_contains_copy = true;
|
||||||
|
}
|
||||||
|
if (is_8(expr->value)) {
|
||||||
|
// add BYTE [rbx + <value: rel8>], al
|
||||||
|
emitter_push_u8(emitter, 0x00);
|
||||||
|
emitter_push_u8(emitter, 0x43);
|
||||||
|
emitter_push_u8(emitter, (uint8_t)expr->value);
|
||||||
|
} else {
|
||||||
|
// add BYTE [rbx + <value: rel32>], al
|
||||||
|
emitter_push_u8(emitter, 0x00);
|
||||||
|
emitter_push_u8(emitter, 0x83);
|
||||||
|
emitter_push_u32(emitter, expr->value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (expr->type != ExprType_Add) {
|
||||||
|
emitter->rax_contains_copy = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,7 @@ typedef struct {
|
|||||||
size_t pos;
|
size_t pos;
|
||||||
int loop_counter;
|
int loop_counter;
|
||||||
bool cmp_flags_set;
|
bool cmp_flags_set;
|
||||||
|
bool rax_contains_copy;
|
||||||
} Emitter;
|
} Emitter;
|
||||||
|
|
||||||
Emitter emitter_create(uint8_t* code_address);
|
Emitter emitter_create(uint8_t* code_address);
|
||||||
|
|||||||
64
expr.c
64
expr.c
@ -40,6 +40,24 @@ Expr expr_vec_pop(ExprVec* vec)
|
|||||||
return vec->data[vec->length];
|
return vec->data[vec->length];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void expr_vec_stringify(ExprVec* vec, char* acc, int depth)
|
||||||
|
{
|
||||||
|
strcat(acc, color_bold);
|
||||||
|
strcat(acc, expr_bracket_color(depth));
|
||||||
|
strcat(acc, "[");
|
||||||
|
strcat(acc, color_reset);
|
||||||
|
for (size_t i = 0; i < vec->length; ++i) {
|
||||||
|
if (i != 0) {
|
||||||
|
strcat(acc, " ");
|
||||||
|
}
|
||||||
|
expr_stringify(&vec->data[i], acc, depth + 1);
|
||||||
|
}
|
||||||
|
strcat(acc, color_bold);
|
||||||
|
strcat(acc, expr_bracket_color(depth));
|
||||||
|
strcat(acc, "]");
|
||||||
|
strcat(acc, color_reset);
|
||||||
|
}
|
||||||
|
|
||||||
bool expr_vec_equal(const ExprVec* self, const ExprVec* other)
|
bool expr_vec_equal(const ExprVec* self, const ExprVec* other)
|
||||||
{
|
{
|
||||||
if (self->length != other->length) {
|
if (self->length != other->length) {
|
||||||
@ -53,6 +71,16 @@ bool expr_vec_equal(const ExprVec* self, const ExprVec* other)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExprVec expr_vec_clone(const ExprVec* original)
|
||||||
|
{
|
||||||
|
ExprVec vec;
|
||||||
|
expr_vec_construct(&vec);
|
||||||
|
for (size_t i = 0; i < original->length; ++i) {
|
||||||
|
expr_vec_push(&vec, expr_clone(&original->data[i]));
|
||||||
|
}
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
void expr_free(Expr* expr)
|
void expr_free(Expr* expr)
|
||||||
{
|
{
|
||||||
switch (expr->type) {
|
switch (expr->type) {
|
||||||
@ -92,24 +120,6 @@ void expr_stringify_concat_value(Expr* expr, char* acc, int depth)
|
|||||||
strcat(acc, color_reset);
|
strcat(acc, color_reset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void expr_vec_stringify(ExprVec* vec, char* acc, int depth)
|
|
||||||
{
|
|
||||||
strcat(acc, color_bold);
|
|
||||||
strcat(acc, expr_bracket_color(depth));
|
|
||||||
strcat(acc, "[");
|
|
||||||
strcat(acc, color_reset);
|
|
||||||
for (size_t i = 0; i < vec->length; ++i) {
|
|
||||||
if (i != 0) {
|
|
||||||
strcat(acc, " ");
|
|
||||||
}
|
|
||||||
expr_stringify(&vec->data[i], acc, depth + 1);
|
|
||||||
}
|
|
||||||
strcat(acc, color_bold);
|
|
||||||
strcat(acc, expr_bracket_color(depth));
|
|
||||||
strcat(acc, "]");
|
|
||||||
strcat(acc, color_reset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void expr_stringify(Expr* expr, char* acc, int depth)
|
void expr_stringify(Expr* expr, char* acc, int depth)
|
||||||
{
|
{
|
||||||
switch (expr->type) {
|
switch (expr->type) {
|
||||||
@ -163,6 +173,12 @@ void expr_stringify(Expr* expr, char* acc, int depth)
|
|||||||
strcat(acc, "Zero");
|
strcat(acc, "Zero");
|
||||||
strcat(acc, color_reset);
|
strcat(acc, color_reset);
|
||||||
break;
|
break;
|
||||||
|
case ExprType_Add:
|
||||||
|
strcat(acc, color_cyan);
|
||||||
|
strcat(acc, "Add");
|
||||||
|
strcat(acc, color_reset);
|
||||||
|
expr_stringify_concat_value(expr, acc, depth);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,3 +206,15 @@ bool expr_equal(const Expr* self, const Expr* other)
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expr expr_clone(const Expr* expr)
|
||||||
|
{
|
||||||
|
if (expr->type == ExprType_Loop) {
|
||||||
|
return (Expr) {
|
||||||
|
.type = ExprType_Loop,
|
||||||
|
.exprs = expr_vec_clone(&expr->exprs),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return *expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
6
expr.h
6
expr.h
@ -14,6 +14,7 @@ typedef enum {
|
|||||||
ExprType_Input,
|
ExprType_Input,
|
||||||
ExprType_Loop,
|
ExprType_Loop,
|
||||||
ExprType_Zero,
|
ExprType_Zero,
|
||||||
|
ExprType_Add,
|
||||||
} ExprType;
|
} ExprType;
|
||||||
|
|
||||||
typedef struct Expr Expr;
|
typedef struct Expr Expr;
|
||||||
@ -29,7 +30,9 @@ void expr_vec_destroy(ExprVec* vec);
|
|||||||
void expr_vec_free(ExprVec* vec);
|
void expr_vec_free(ExprVec* vec);
|
||||||
void expr_vec_push(ExprVec* vec, Expr expr);
|
void expr_vec_push(ExprVec* vec, Expr expr);
|
||||||
Expr expr_vec_pop(ExprVec* vec);
|
Expr expr_vec_pop(ExprVec* vec);
|
||||||
|
void expr_vec_stringify(ExprVec* vec, char* acc, int depth);
|
||||||
bool expr_vec_equal(const ExprVec* self, const ExprVec* other);
|
bool expr_vec_equal(const ExprVec* self, const ExprVec* other);
|
||||||
|
ExprVec expr_vec_clone(const ExprVec* original);
|
||||||
|
|
||||||
struct Expr {
|
struct Expr {
|
||||||
ExprType type;
|
ExprType type;
|
||||||
@ -42,8 +45,9 @@ struct Expr {
|
|||||||
void expr_free(Expr* expr);
|
void expr_free(Expr* expr);
|
||||||
const char* expr_bracket_color(int depth);
|
const char* expr_bracket_color(int depth);
|
||||||
void expr_stringify_concat_value(Expr* expr, char* acc, int depth);
|
void expr_stringify_concat_value(Expr* expr, char* acc, int depth);
|
||||||
void expr_vec_stringify(ExprVec* vec, char* acc, int depth);
|
void expr_stringify_concat_pair(Expr* expr, char* acc, int depth);
|
||||||
void expr_stringify(Expr* expr, char* acc, int depth);
|
void expr_stringify(Expr* expr, char* acc, int depth);
|
||||||
bool expr_equal(const Expr* self, const Expr* other);
|
bool expr_equal(const Expr* self, const Expr* other);
|
||||||
|
Expr expr_clone(const Expr* expr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
74
main.c
74
main.c
@ -10,13 +10,27 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
#define ADD_OPTIMIZATION_WO_FREE_AST(NAME) \
|
||||||
|
previous_ast = ast; \
|
||||||
|
ast = optimize_##NAME(&ast); \
|
||||||
|
printf("%s" #NAME ":%s\n", color_bold, color_reset); \
|
||||||
|
if (!expr_vec_equal(&ast, &previous_ast)) { \
|
||||||
|
ast_string[0] = '\0'; \
|
||||||
|
expr_vec_stringify(&ast, ast_string, 0); \
|
||||||
|
puts(ast_string); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ADD_OPTIMIZATION(NAME) \
|
||||||
|
expr_vec_free(&previous_ast); \
|
||||||
|
ADD_OPTIMIZATION_WO_FREE_AST(NAME)
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
const char* text = "++++++++++[>+<-]";
|
// const char* text = "++++++++++[>+<-]";
|
||||||
printf("\ntext:%s\n\"%s\"%s\n", color_bright_green, text, color_reset);
|
// printf("\ntext:%s\n\"%s\"%s\n", color_bright_green, text, color_reset);
|
||||||
Parser parser = parser_create(lexer_from_string(text, strlen(text)));
|
// Parser parser = parser_create(lexer_from_string(text, strlen(text)));
|
||||||
|
|
||||||
// Parser parser = parser_create(lexer_from_args_or_stdin(argc, argv));
|
Parser parser = parser_create(lexer_from_args_or_stdin(argc, argv));
|
||||||
|
|
||||||
char* ast_string = malloc(sizeof(char) * 33768);
|
char* ast_string = malloc(sizeof(char) * 33768);
|
||||||
ast_string[0] = '\0';
|
ast_string[0] = '\0';
|
||||||
@ -42,44 +56,11 @@ int main(int argc, char** argv)
|
|||||||
if (!first) {
|
if (!first) {
|
||||||
expr_vec_free(&previous_ast);
|
expr_vec_free(&previous_ast);
|
||||||
}
|
}
|
||||||
previous_ast = ast;
|
ADD_OPTIMIZATION_WO_FREE_AST(fold_adjecent);
|
||||||
ast = optimize_fold_adjecent(&ast);
|
ADD_OPTIMIZATION(eliminate_negation);
|
||||||
printf("%sfold_adjecent:%s\n", color_bold, color_reset);
|
ADD_OPTIMIZATION(eliminate_overflow);
|
||||||
if (!expr_vec_equal(&ast, &previous_ast)) {
|
ADD_OPTIMIZATION(replace_zeroing_loops);
|
||||||
ast_string[0] = '\0';
|
ADD_OPTIMIZATION(replace_copying_loops);
|
||||||
expr_vec_stringify(&ast, ast_string, 0);
|
|
||||||
puts(ast_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
expr_vec_free(&previous_ast);
|
|
||||||
previous_ast = ast;
|
|
||||||
ast = optimize_eliminate_negation(&ast);
|
|
||||||
printf("%seliminate_negation:%s\n", color_bold, color_reset);
|
|
||||||
if (!expr_vec_equal(&ast, &previous_ast)) {
|
|
||||||
ast_string[0] = '\0';
|
|
||||||
expr_vec_stringify(&ast, ast_string, 0);
|
|
||||||
puts(ast_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
expr_vec_free(&previous_ast);
|
|
||||||
previous_ast = ast;
|
|
||||||
ast = optimize_eliminate_overflow(&ast);
|
|
||||||
printf("%seliminate_overflow:%s\n", color_bold, color_reset);
|
|
||||||
if (!expr_vec_equal(&ast, &previous_ast)) {
|
|
||||||
ast_string[0] = '\0';
|
|
||||||
expr_vec_stringify(&ast, ast_string, 0);
|
|
||||||
puts(ast_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
expr_vec_free(&previous_ast);
|
|
||||||
previous_ast = ast;
|
|
||||||
ast = optimize_replace_zeroing_loops(&ast);
|
|
||||||
printf("%sreplace_zeroing_loops:%s\n", color_bold, color_reset);
|
|
||||||
if (!expr_vec_equal(&ast, &previous_ast)) {
|
|
||||||
ast_string[0] = '\0';
|
|
||||||
expr_vec_stringify(&ast, ast_string, 0);
|
|
||||||
puts(ast_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (first) {
|
if (first) {
|
||||||
first = false;
|
first = false;
|
||||||
@ -112,12 +93,15 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
printf("\n%scode:%s\n", color_bold, color_reset);
|
printf("\n%scode:%s\n", color_bold, color_reset);
|
||||||
|
|
||||||
for (size_t y = 0; y < 8; ++y) {
|
for (size_t y = 0; y < 40; ++y) {
|
||||||
for (size_t x = 0; x < 8; ++x) {
|
for (size_t x = 0; x < 16; ++x) {
|
||||||
uint8_t v = ((uint8_t*)code)[y * 8 + x];
|
uint8_t v = ((uint8_t*)code)[y * 8 + x];
|
||||||
if (v == 0) {
|
if (v == 0) {
|
||||||
fputs(color_gray, stdout);
|
fputs(color_gray, stdout);
|
||||||
}
|
}
|
||||||
|
if (x == 8) {
|
||||||
|
fputc(' ', stdout);
|
||||||
|
}
|
||||||
printf("%02x ", v);
|
printf("%02x ", v);
|
||||||
fputs(color_reset, stdout);
|
fputs(color_reset, stdout);
|
||||||
}
|
}
|
||||||
@ -135,7 +119,7 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
printf("\n%smemory:%s\n", color_bold, color_reset);
|
printf("\n%smemory:%s\n", color_bold, color_reset);
|
||||||
|
|
||||||
for (size_t y = 0; y < 8; ++y) {
|
for (size_t y = 0; y < 4; ++y) {
|
||||||
for (size_t x = 0; x < 8; ++x) {
|
for (size_t x = 0; x < 8; ++x) {
|
||||||
uint8_t v = memory[y * 8 + x];
|
uint8_t v = memory[y * 8 + x];
|
||||||
if (v == 0) {
|
if (v == 0) {
|
||||||
|
|||||||
95
optimizer.c
95
optimizer.c
@ -4,9 +4,9 @@
|
|||||||
/*
|
/*
|
||||||
* fold adjecent
|
* fold adjecent
|
||||||
*
|
*
|
||||||
* A(N) :: { Incr(N) | Decr(N) | Right(N) | Left(N) }
|
* A(n) :: { Incr(n) | Decr(n) | Right(n) | Left(n) }
|
||||||
*
|
*
|
||||||
* [A(N1) A(N2)] -> [A(N1 + N2)]
|
* [A(n1) A(n2)] -> [A(n1 + n2)]
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -49,20 +49,20 @@ Expr expr_optimize_fold_adjecent(const Expr* expr)
|
|||||||
.exprs = optimize_fold_adjecent(&expr->exprs),
|
.exprs = optimize_fold_adjecent(&expr->exprs),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return *expr;
|
return expr_clone(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* eliminate negation
|
* eliminate negation
|
||||||
*
|
*
|
||||||
* A(N), B(N) :: { Incr(N) | Decr(N) | Right(N) | Left(N) }
|
* A(n), B(n) :: { Incr(n) | Decr(n) | Right(n) | Left(n) }
|
||||||
*
|
*
|
||||||
* [A(N) B(N)] = []
|
* [A(n) B(n)] = []
|
||||||
*
|
*
|
||||||
* [A(N1) B(N2)] ? N1 == N2 -> []
|
* [A(n1) B(n2)] ? n1 == n2 -> []
|
||||||
* [A(N1) B(N2)] ? N1 < N2 -> [B(N2 - N1)]
|
* [A(n1) B(n2)] ? n1 < n2 -> [B(n2 - n1)]
|
||||||
* [A(N1) B(N2)] ? N1 > N2 -> [A(N1 - N2)]
|
* [A(n1) B(n2)] ? n1 > n2 -> [A(n1 - n2)]
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -140,18 +140,18 @@ Expr expr_optimize_eliminate_negation(const Expr* expr)
|
|||||||
.exprs = optimize_eliminate_negation(&expr->exprs),
|
.exprs = optimize_eliminate_negation(&expr->exprs),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return *expr;
|
return expr_clone(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* eliminate overflow
|
* eliminate overflow
|
||||||
*
|
*
|
||||||
* A(N) :: { Incr(N) | Decr(N) | Right(N) | Left(N) }
|
* A(n) :: { Incr(n) | Decr(n) | Right(n) | Left(n) }
|
||||||
*
|
*
|
||||||
* N > 255
|
* n > 255
|
||||||
*
|
*
|
||||||
* A(N) -> A(N % 256)
|
* A(n) -> A(n % 256)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -175,18 +175,18 @@ Expr expr_optimize_eliminate_overflow(const Expr* expr)
|
|||||||
} else if (expr->value > 255) {
|
} else if (expr->value > 255) {
|
||||||
return (Expr) { .type = expr->type, .value = expr->value % 256 };
|
return (Expr) { .type = expr->type, .value = expr->value % 256 };
|
||||||
} else {
|
} else {
|
||||||
return *expr;
|
return expr_clone(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* replace zeroing loops
|
* replace zeroing loops
|
||||||
*
|
*
|
||||||
* A(N) :: { Incr(N) | Decr(N) }
|
* A(n) :: { Incr(n) | Decr(n) }
|
||||||
*
|
*
|
||||||
* N % 2 == 1
|
* n % 2 == 1
|
||||||
*
|
*
|
||||||
* Loop[A(N)] -> Zero
|
* Loop[A(n)] -> Zero
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -217,6 +217,67 @@ Expr expr_optimize_replace_zeroing_loops(const Expr* expr)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return *expr;
|
return expr_clone(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* replace copying loops
|
||||||
|
*
|
||||||
|
* O(n), I(n) :: { Left(n) | Right(n) }
|
||||||
|
*
|
||||||
|
* O != I
|
||||||
|
*
|
||||||
|
* [Loop[O(n) Incr(1) I(n) Decr(1)]] -> [Copy(n) Zero]
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
ExprVec optimize_replace_copying_loops(const ExprVec* original)
|
||||||
|
{
|
||||||
|
ExprVec result;
|
||||||
|
expr_vec_construct(&result);
|
||||||
|
for (size_t i = 0; i < original->length; ++i) {
|
||||||
|
const Expr* expr = &original->data[i];
|
||||||
|
if (expr->type == ExprType_Loop) {
|
||||||
|
const ExprVec* loop = &expr->exprs;
|
||||||
|
if (loop->length == 4
|
||||||
|
&& ((loop->data[0].type == ExprType_Left
|
||||||
|
&& loop->data[2].type == ExprType_Right)
|
||||||
|
|| (loop->data[0].type == ExprType_Right
|
||||||
|
&& loop->data[2].type == ExprType_Left))
|
||||||
|
&& loop->data[1].type == ExprType_Incr
|
||||||
|
&& loop->data[3].type == ExprType_Decr
|
||||||
|
&& loop->data[1].value == loop->data[3].value) {
|
||||||
|
if (loop->data[0].type == ExprType_Right) {
|
||||||
|
expr_vec_push(
|
||||||
|
&result,
|
||||||
|
(Expr) {
|
||||||
|
.type = ExprType_Add,
|
||||||
|
.value = loop->data[0].value,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
expr_vec_push(
|
||||||
|
&result,
|
||||||
|
(Expr) {
|
||||||
|
.type = ExprType_Add,
|
||||||
|
.value = -loop->data[0].value,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expr_vec_push(&result, (Expr) { .type = ExprType_Zero });
|
||||||
|
} else {
|
||||||
|
expr_vec_push(
|
||||||
|
&result,
|
||||||
|
(Expr) {
|
||||||
|
.type = ExprType_Loop,
|
||||||
|
.exprs = optimize_replace_copying_loops(&expr->exprs),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
expr_vec_push(&result, expr_clone(expr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@ -15,4 +15,6 @@ Expr expr_optimize_eliminate_overflow(const Expr* expr);
|
|||||||
ExprVec optimize_replace_zeroing_loops(const ExprVec* vec);
|
ExprVec optimize_replace_zeroing_loops(const ExprVec* vec);
|
||||||
Expr expr_optimize_replace_zeroing_loops(const Expr* expr);
|
Expr expr_optimize_replace_zeroing_loops(const Expr* expr);
|
||||||
|
|
||||||
|
ExprVec optimize_replace_copying_loops(const ExprVec* vec);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user