From fe6ef90c44d3b892061eb78ec727952c46c8bd9c Mon Sep 17 00:00:00 2001 From: Shpoike Date: Tue, 5 Nov 2024 01:19:27 +0000 Subject: [PATCH] Better gmqcc compat. --- engine/qclib/qcc.h | 1 + engine/qclib/qcc_pr_comp.c | 24 ++++++++++++++++++++++++ engine/qclib/qccmain.c | 2 ++ 3 files changed, 27 insertions(+) diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index 78f907f68..a619a5c6a 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -688,6 +688,7 @@ extern pbool flag_qcfuncs; extern pbool flag_embedsrc; extern pbool flag_nopragmafileline; extern pbool flag_utf8strings; +extern pbool flag_reciprocalmaths; extern pbool opt_overlaptemps; extern pbool opt_shortenifnots; diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 32746a143..b12a320b5 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -156,6 +156,7 @@ pbool flag_allowuninit; //ignore uninitialised locals, avoiding all private loc pbool flag_embedsrc; //embed all source files inside the .dat (can be opened with any zip program) pbool flag_nopragmafileline;//ignore #pragma file and #pragma line, so that I can actually read+debug xonotic's code. pbool flag_utf8strings; //strings default to u8"" string rules. +pbool flag_reciprocalmaths; //unsafe maths optimisations pbool opt_overlaptemps; //reduce numpr_globals by reuse of temps. When they are not needed they are freed for reuse. The way this is implemented is better than frikqcc's. (This is the single most important optimisation) pbool opt_assignments; //STORE_F isn't used if an operation wrote to a temp. @@ -3572,10 +3573,33 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_ return var_a; } break; + case OP_DIV_VF: + if (!eval_b->_float) + QCC_PR_ParseWarning(WARN_DIVISIONBY0, "Division by 0\n"); + else if (flag_reciprocalmaths) + { + QCC_FreeTemp(var_b); + var_b = QCC_MakeFloatConst(1 / eval_b->_float); + return QCC_PR_StatementFlags(&pr_opcodes[OP_MUL_VF], var_a, var_b, outstatement, 0); + } + if (eval_b->_float == 1) + { + optres_constantarithmatic++; + QCC_FreeTemp(var_b); + return var_a; + } + break; + case OP_DIV_F: case OP_DIV_IF: if (!eval_b->_float) QCC_PR_ParseWarning(WARN_DIVISIONBY0, "Division by 0\n"); + else if (flag_reciprocalmaths) + { + QCC_FreeTemp(var_b); + var_b = QCC_MakeFloatConst(1 / eval_b->_float); + return QCC_PR_StatementFlags((op == &pr_opcodes[OP_ADD_FP])?&pr_opcodes[OP_MUL_F]:&pr_opcodes[OP_MUL_IF], var_a, var_b, outstatement, 0); + } //fallthrough case OP_MUL_F: case OP_MUL_IF: diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 079f89344..4243f2574 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -425,6 +425,7 @@ compiler_flag_t compiler_flag[] = { {&flag_nopragmafileline,FLAG_MIDCOMPILE,"nofileline", "Ignore #pragma file", "Ignores #pragma file(foo) and #pragma line(foo), so that errors and symbols reflect the actual lines, instead of the original source."}, // {&flag_lno, hidedefaultflag,"lno", "Gen Debugging Info", "Writes debugging info."}, {&flag_utf8strings, FLAG_MIDCOMPILE,"utf8", "Unicode", "String immediates will use utf-8 encoding, instead of quake's encoding."}, + {&flag_reciprocalmaths, FLAG_MIDCOMPILE,"reciprocal-math","Reciprocal Maths", "Optimise x/const as x*(1/const)."}, {&flag_embedsrc, FLAG_MIDCOMPILE,"embedsrc", "Embed Sources", "Write the sourcecode into the output file. The resulting .dat can be opened as a standard zip archive (or by fteqccgui).\nGood for GPL compliance!"}, // {&flag_noreflection, FLAG_MIDCOMPILE,"omitinternals","Omit Reflection Info", "Keeps internal symbols private (equivelent to unix's hidden visibility). This has the effect of reducing filesize, thwarting debuggers, and breaking saved games. This allows you to use arrays without massively bloating the size of your progs.\nWARNING: The bit about breaking saved games was NOT a joke, but does not apply to menuqc or csqc. It also interferes with FTE_MULTIPROGS."}, @@ -4743,6 +4744,7 @@ static void QCC_PR_CommandLinePrecompilerOptions (void) flag_dblstarexp = flag_attributes = flag_assumevar = pr_subscopedlocals = flag_cpriority = flag_allowuninit = true; flag_boundchecks = false; //gmqcc doesn't support dynamic bound checks, so xonotic is buggy shite. we don't want to generate code that will crash. flag_macroinstrings = false; + flag_reciprocalmaths = true; //optimise x/y to x*(1/y) in constants. opt_logicops = true; //we have to disable some of these warnings, because xonotic insists on using -Werror. use -Wextra to override.