From 6f749d61b1688752bb902efd635f55d584ad7087 Mon Sep 17 00:00:00 2001 From: Dale Weiler Date: Thu, 1 Aug 2013 07:07:59 +0000 Subject: [PATCH] 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). --- BSDmakefile | 21 +++++++++++---------- Makefile | 5 +++-- doc/gmqcc.1 | 4 ++++ fold.c | 44 +++++++++++++++++++++++++++++++------------- opts.def | 1 + 5 files changed, 50 insertions(+), 25 deletions(-) diff --git a/BSDmakefile b/BSDmakefile index a84493b..6aea46e 100644 --- a/BSDmakefile +++ b/BSDmakefile @@ -103,19 +103,20 @@ install-doc: # DO NOT DELETE -ast.o: gmqcc.h opts.def ast.h ir.h -code.o: gmqcc.h opts.def -conout.o: gmqcc.h opts.def -correct.o: gmqcc.h opts.def +util.o: gmqcc.h opts.def fs.o: gmqcc.h opts.def -ftepp.o: gmqcc.h opts.def lexer.h -ir.o: gmqcc.h opts.def ir.h -lexer.o: gmqcc.h opts.def lexer.h -main.o: gmqcc.h opts.def lexer.h +conout.o: gmqcc.h opts.def opts.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 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 -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 diff --git a/Makefile b/Makefile index 4444566..b2dc72d 100644 --- a/Makefile +++ b/Makefile @@ -150,10 +150,11 @@ stat.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: 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 -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 ftepp.o: gmqcc.h opts.def lexer.h utf8.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 diff --git a/doc/gmqcc.1 b/doc/gmqcc.1 index 22150a3..9220e24 100644 --- a/doc/gmqcc.1 +++ b/doc/gmqcc.1 @@ -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 anything other than 1, a float-multiplication will be added, which is 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 .Sh CONFIG The configuration file is similar to regular .ini files. Comments diff --git a/fold.c b/fold.c index c8996cf..d0802f4 100644 --- a/fold.c +++ b/fold.c @@ -123,15 +123,6 @@ static GMQCC_INLINE bool vec3_pbool(vec3_t a) { 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) { lex_ctx_t ctx; 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; } +/* 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_vector(E) ((E)->constval.vvec) #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 - * stage of the compiler, i.e eliminating branches for const expressions, - * which is the only supported thing so far. + * These are all the actual constant folding methods that happen in between + * the AST/IR stage of the compiler , i.e eliminating branches for const + * 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) { - 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; ir_block *elide; ir_value *dummy; diff --git a/opts.def b/opts.def index 61226ae..1f61ec5 100644 --- a/opts.def +++ b/opts.def @@ -105,6 +105,7 @@ GMQCC_DEFINE_FLAG(CALL_STORES, 3) GMQCC_DEFINE_FLAG(VOID_RETURN, 1) GMQCC_DEFINE_FLAG(VECTOR_COMPONENTS, 1) + GMQCC_DEFINE_FLAG(CONST_FOLD_DCE, 2) #endif #ifdef GMQCC_TYPE_OPTIONS -- 2.39.2