mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-02-20 18:32:01 +00:00
Move const-branch-elision into fold.c
This commit is contained in:
parent
3e24b5a74b
commit
10b75fd8b9
4 changed files with 43 additions and 29 deletions
35
ast.c
35
ast.c
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "gmqcc.h"
|
||||
#include "ast.h"
|
||||
#include "parser.h"
|
||||
|
||||
#define ast_instantiate(T, ctx, destroyfn) \
|
||||
T* self = (T*)mem_a(sizeof(T)); \
|
||||
|
@ -1221,7 +1222,7 @@ void ast_function_delete(ast_function *self)
|
|||
mem_d(self);
|
||||
}
|
||||
|
||||
static const char* ast_function_label(ast_function *self, const char *prefix)
|
||||
const char* ast_function_label(ast_function *self, const char *prefix)
|
||||
{
|
||||
size_t id;
|
||||
size_t len;
|
||||
|
@ -2513,6 +2514,7 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va
|
|||
ir_block *ontrue_endblock = NULL;
|
||||
ir_block *onfalse_endblock = NULL;
|
||||
ir_block *merge = NULL;
|
||||
int fold = 0;
|
||||
|
||||
/* We don't output any value, thus also don't care about r/lvalue */
|
||||
(void)out;
|
||||
|
@ -2531,33 +2533,10 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va
|
|||
/* update the block which will get the jump - because short-logic or ternaries may have changed this */
|
||||
cond = func->curblock;
|
||||
|
||||
/* eliminate branches if value is constant */
|
||||
if (condval->vtype == TYPE_FLOAT && condval->hasvalue && condval->cvq == CV_CONST) {
|
||||
/* don't generate if statements */
|
||||
if (condval->constval.vfloat == 1.0f && self->on_true) {
|
||||
if (!(ontrue = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "ontrue"))))
|
||||
return false;
|
||||
/* generate */
|
||||
if (!(*(cgen = self->on_true->codegen))((ast_expression*)(self->on_true), func, false, &dummy))
|
||||
return false;
|
||||
if (!ir_block_create_jump(func->curblock, ast_ctx(self), ontrue))
|
||||
return false;
|
||||
func->curblock = ontrue;
|
||||
return true;
|
||||
} else if (condval->constval.vfloat == 0.0f && self->on_false) {
|
||||
if (!(onfalse = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "onfalse"))))
|
||||
return false;
|
||||
/* generate */
|
||||
if (!(*(cgen = self->on_false->codegen))((ast_expression*)(self->on_false), func, false, &dummy))
|
||||
return false;
|
||||
if (!ir_block_create_jump(func->curblock, ast_ctx(self), onfalse))
|
||||
return false;
|
||||
func->curblock = onfalse;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/* on-true path */
|
||||
|
||||
/* try constant folding away the if */
|
||||
if ((fold = fold_cond((ast_value*)condval, func, self)) != -1)
|
||||
return fold;
|
||||
|
||||
if (self->on_true) {
|
||||
/* create on-true block */
|
||||
ontrue = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "ontrue"));
|
||||
|
|
2
ast.h
2
ast.h
|
@ -642,7 +642,7 @@ void ast_function_delete(ast_function*);
|
|||
/* For "optimized" builds this can just keep returning "foo"...
|
||||
* or whatever...
|
||||
*/
|
||||
/*const char* ast_function_label(ast_function*, const char *prefix);*/
|
||||
const char* ast_function_label(ast_function*, const char *prefix);
|
||||
|
||||
bool ast_function_codegen(ast_function *self, ir_builder *builder);
|
||||
bool ast_generate_accessors(ast_value *asvalue, ir_builder *ir);
|
||||
|
|
32
fold.c
32
fold.c
|
@ -588,3 +588,35 @@ ast_expression *fold_op(fold_t *fold, const oper_info *info, ast_expression **op
|
|||
compile_error(fold_ctx(fold), "internal error: attempted to constant for unsupported operator");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* These are all the actual constant folding methods that happen in the AST
|
||||
* stage of the compiler, i.e eliminating branches for const expressions,
|
||||
* which is the only supported thing so far.
|
||||
*/
|
||||
int fold_cond(ir_value *condval, ast_function *func, ast_ifthen *branch) {
|
||||
if (condval->vtype == TYPE_FLOAT && condval->hasvalue && condval->cvq == CV_CONST) {
|
||||
ast_expression_codegen *cgen;
|
||||
ir_block *elide;
|
||||
ir_value *dummy;
|
||||
bool istrue = (fold_immvalue_float(condval) == 1.0f && branch->on_true);
|
||||
bool isfalse = (fold_immvalue_float(condval) == 0.0f && branch->on_false);
|
||||
ast_expression *path = (istrue) ? branch->on_true :
|
||||
(isfalse) ? branch->on_false : NULL;
|
||||
if (!path)
|
||||
return false;
|
||||
if (!(elide = ir_function_create_block(ast_ctx(branch), func->ir_func, ast_function_label(func, ((istrue) ? "ontrue" : "onfalse")))))
|
||||
return false;
|
||||
if (!(*(cgen = path->codegen))((ast_expression*)path, func, false, &dummy))
|
||||
return false;
|
||||
if (!ir_block_create_jump(func->curblock, ast_ctx(branch), elide))
|
||||
return false;
|
||||
/*
|
||||
* now the branch has been eliminates, and the correct block for the constant evaluation
|
||||
* is expanded into the current block for the function.
|
||||
*/
|
||||
func->curblock = elide;
|
||||
return true;
|
||||
}
|
||||
return -1; /* nothing done */
|
||||
}
|
||||
|
|
3
parser.h
3
parser.h
|
@ -112,4 +112,7 @@ ast_expression *fold_constgen_vector(fold_t *, vec3_t);
|
|||
ast_expression *fold_constgen_string(fold_t *, const char *, bool);
|
||||
bool fold_generate (fold_t *, ir_builder *);
|
||||
ast_expression *fold_op (fold_t *, const oper_info *, ast_expression**);
|
||||
|
||||
int fold_cond (ir_value *, ast_function *, ast_ifthen *);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue