mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2024-11-30 15:41:12 +00:00
Added -Oconst-fold-dce (dead code elimination optimization for when constant expressions form the basis of the dead code, i.e if else with constant expression). Fixed deps and added documentation. Cleaned up folds for ir_value (can now use the same macros as the ast_value ones).
This commit is contained in:
parent
24fc2e5146
commit
6f749d61b1
5 changed files with 50 additions and 25 deletions
21
BSDmakefile
21
BSDmakefile
|
@ -103,19 +103,20 @@ install-doc:
|
||||||
|
|
||||||
# DO NOT DELETE
|
# DO NOT DELETE
|
||||||
|
|
||||||
ast.o: gmqcc.h opts.def ast.h ir.h
|
util.o: gmqcc.h opts.def
|
||||||
code.o: gmqcc.h opts.def
|
|
||||||
conout.o: gmqcc.h opts.def
|
|
||||||
correct.o: gmqcc.h opts.def
|
|
||||||
fs.o: gmqcc.h opts.def
|
fs.o: gmqcc.h opts.def
|
||||||
ftepp.o: gmqcc.h opts.def lexer.h
|
conout.o: gmqcc.h opts.def
|
||||||
ir.o: gmqcc.h opts.def ir.h
|
|
||||||
lexer.o: gmqcc.h opts.def lexer.h
|
|
||||||
main.o: gmqcc.h opts.def lexer.h
|
|
||||||
opts.o: gmqcc.h opts.def
|
opts.o: gmqcc.h opts.def
|
||||||
pak.o: gmqcc.h opts.def
|
pak.o: gmqcc.h opts.def
|
||||||
parser.o: gmqcc.h opts.def lexer.h ast.h ir.h intrin.h
|
|
||||||
stat.o: gmqcc.h opts.def
|
stat.o: gmqcc.h opts.def
|
||||||
test.o: gmqcc.h opts.def
|
test.o: gmqcc.h opts.def
|
||||||
|
main.o: gmqcc.h opts.def lexer.h
|
||||||
|
lexer.o: gmqcc.h opts.def lexer.h
|
||||||
|
parser.o: parser.h gmqcc.h opts.def lexer.h ast.h ir.h intrin.h
|
||||||
|
code.o: gmqcc.h opts.def
|
||||||
|
ast.o: gmqcc.h opts.def ast.h ir.h parser.h lexer.h
|
||||||
|
ir.o: gmqcc.h opts.def ir.h
|
||||||
|
ftepp.o: gmqcc.h opts.def lexer.h
|
||||||
utf8.o: gmqcc.h opts.def
|
utf8.o: gmqcc.h opts.def
|
||||||
util.o: gmqcc.h opts.def
|
correct.o: gmqcc.h opts.def
|
||||||
|
fold.o: ast.h ir.h gmqcc.h opts.def parser.h lexer.h
|
||||||
|
|
5
Makefile
5
Makefile
|
@ -150,10 +150,11 @@ stat.o: gmqcc.h opts.def
|
||||||
test.o: gmqcc.h opts.def
|
test.o: gmqcc.h opts.def
|
||||||
main.o: gmqcc.h opts.def lexer.h
|
main.o: gmqcc.h opts.def lexer.h
|
||||||
lexer.o: gmqcc.h opts.def lexer.h
|
lexer.o: gmqcc.h opts.def lexer.h
|
||||||
parser.o: gmqcc.h opts.def lexer.h ast.h ir.h intrin.h
|
parser.o: parser.h gmqcc.h opts.def lexer.h ast.h ir.h intrin.h
|
||||||
code.o: gmqcc.h opts.def
|
code.o: gmqcc.h opts.def
|
||||||
ast.o: gmqcc.h opts.def ast.h ir.h
|
ast.o: gmqcc.h opts.def ast.h ir.h parser.h lexer.h
|
||||||
ir.o: gmqcc.h opts.def ir.h
|
ir.o: gmqcc.h opts.def ir.h
|
||||||
ftepp.o: gmqcc.h opts.def lexer.h
|
ftepp.o: gmqcc.h opts.def lexer.h
|
||||||
utf8.o: gmqcc.h opts.def
|
utf8.o: gmqcc.h opts.def
|
||||||
correct.o: gmqcc.h opts.def
|
correct.o: gmqcc.h opts.def
|
||||||
|
fold.o: ast.h ir.h gmqcc.h opts.def parser.h lexer.h
|
||||||
|
|
|
@ -606,6 +606,10 @@ in this case, the y component of a vector. This optimization will turn
|
||||||
such a multiplication into a direct component access. If the factor is
|
such a multiplication into a direct component access. If the factor is
|
||||||
anything other than 1, a float-multiplication will be added, which is
|
anything other than 1, a float-multiplication will be added, which is
|
||||||
still faster than a vector multiplication.
|
still faster than a vector multiplication.
|
||||||
|
.It Fl O Ns Cm const-fold-dce
|
||||||
|
For constant expressions that result in dead code (such as a branch whos
|
||||||
|
condition can be evaluated at compile-time), this will eliminate the branch
|
||||||
|
and else body (if present) to produce more optimal code.
|
||||||
.El
|
.El
|
||||||
.Sh CONFIG
|
.Sh CONFIG
|
||||||
The configuration file is similar to regular .ini files. Comments
|
The configuration file is similar to regular .ini files. Comments
|
||||||
|
|
44
fold.c
44
fold.c
|
@ -123,15 +123,6 @@ static GMQCC_INLINE bool vec3_pbool(vec3_t a) {
|
||||||
return (a.x && a.y && a.z);
|
return (a.x && a.y && a.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GMQCC_INLINE bool fold_can_1(const ast_value *val) {
|
|
||||||
return (ast_istype(((ast_expression*)(val)), ast_value) && val->hasvalue && (val->cvq == CV_CONST) &&
|
|
||||||
((ast_expression*)(val))->vtype != TYPE_FUNCTION);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GMQCC_INLINE bool fold_can_2(const ast_value *v1, const ast_value *v2) {
|
|
||||||
return fold_can_1(v1) && fold_can_1(v2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static lex_ctx_t fold_ctx(fold_t *fold) {
|
static lex_ctx_t fold_ctx(fold_t *fold) {
|
||||||
lex_ctx_t ctx;
|
lex_ctx_t ctx;
|
||||||
if (fold->parser->lex)
|
if (fold->parser->lex)
|
||||||
|
@ -164,6 +155,13 @@ static GMQCC_INLINE bool fold_immediate_true(fold_t *fold, ast_value *v) {
|
||||||
return !!v->constval.vfunc;
|
return !!v->constval.vfunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handy macros to determine if an ast_value can be constant folded. */
|
||||||
|
#define fold_can_1(X) \
|
||||||
|
(ast_istype(((ast_expression*)(X)), ast_value) && (X)->hasvalue && ((X)->cvq == CV_CONST) && \
|
||||||
|
((ast_expression*)(X))->vtype != TYPE_FUNCTION)
|
||||||
|
|
||||||
|
#define fold_can_2(X, Y) (fold_can_1(X) && fold_can_1(Y))
|
||||||
|
|
||||||
#define fold_immvalue_float(E) ((E)->constval.vfloat)
|
#define fold_immvalue_float(E) ((E)->constval.vfloat)
|
||||||
#define fold_immvalue_vector(E) ((E)->constval.vvec)
|
#define fold_immvalue_vector(E) ((E)->constval.vvec)
|
||||||
#define fold_immvalue_string(E) ((E)->constval.vstring)
|
#define fold_immvalue_string(E) ((E)->constval.vstring)
|
||||||
|
@ -590,12 +588,32 @@ ast_expression *fold_op(fold_t *fold, const oper_info *info, ast_expression **op
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are all the actual constant folding methods that happen in the AST
|
* These are all the actual constant folding methods that happen in between
|
||||||
* stage of the compiler, i.e eliminating branches for const expressions,
|
* the AST/IR stage of the compiler , i.e eliminating branches for const
|
||||||
* which is the only supported thing so far.
|
* expressions, which is the only supported thing so far. We undefine the
|
||||||
|
* testing macros here because an ir_value is differant than an ast_value.
|
||||||
*/
|
*/
|
||||||
|
#undef isfloat
|
||||||
|
#undef isstring
|
||||||
|
#undef isvector
|
||||||
|
#undef fold_immvalue_float
|
||||||
|
#undef fold_immvalue_string
|
||||||
|
#undef fold_immvalue_vector
|
||||||
|
#undef fold_can_1
|
||||||
|
#undef fold_can_2
|
||||||
|
|
||||||
|
#define isfloat(X) ((X)->vtype == TYPE_FLOAT)
|
||||||
|
#define isstring(X) ((X)->vtype == TYPE_STRING)
|
||||||
|
#define isvector(X) ((X)->vtype == TYPE_VECTOR)
|
||||||
|
#define fold_immvalue_float(X) ((X)->constval.vfloat)
|
||||||
|
#define fold_immvalue_vector(X) ((X)->constval.vvec)
|
||||||
|
#define fold_immvalue_string(X) ((X)->constval.vstring)
|
||||||
|
#define fold_can_1(X) ((X)->hasvalue && (X)->cvq == CV_CONST)
|
||||||
|
#define fold_can_2(X,Y) (fold_can_1(X) && fold_can_1(Y))
|
||||||
|
|
||||||
|
|
||||||
int fold_cond(ir_value *condval, ast_function *func, ast_ifthen *branch) {
|
int fold_cond(ir_value *condval, ast_function *func, ast_ifthen *branch) {
|
||||||
if (condval->vtype == TYPE_FLOAT && condval->hasvalue && condval->cvq == CV_CONST) {
|
if (isfloat(condval) && fold_can_1(condval) && OPTS_OPTIMIZATION(OPTIM_CONST_FOLD_DCE)) {
|
||||||
ast_expression_codegen *cgen;
|
ast_expression_codegen *cgen;
|
||||||
ir_block *elide;
|
ir_block *elide;
|
||||||
ir_value *dummy;
|
ir_value *dummy;
|
||||||
|
|
1
opts.def
1
opts.def
|
@ -105,6 +105,7 @@
|
||||||
GMQCC_DEFINE_FLAG(CALL_STORES, 3)
|
GMQCC_DEFINE_FLAG(CALL_STORES, 3)
|
||||||
GMQCC_DEFINE_FLAG(VOID_RETURN, 1)
|
GMQCC_DEFINE_FLAG(VOID_RETURN, 1)
|
||||||
GMQCC_DEFINE_FLAG(VECTOR_COMPONENTS, 1)
|
GMQCC_DEFINE_FLAG(VECTOR_COMPONENTS, 1)
|
||||||
|
GMQCC_DEFINE_FLAG(CONST_FOLD_DCE, 2)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef GMQCC_TYPE_OPTIONS
|
#ifdef GMQCC_TYPE_OPTIONS
|
||||||
|
|
Loading…
Reference in a new issue