From 2fe0af00e78d55edecd7ca7ee1808c4ea946b05f Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Thu, 16 Feb 2023 20:22:18 +0100 Subject: [PATCH] ir: more aggressively reuse const floats Signed-off-by: Wolfgang Bumiller Closes #202 --- gmqcc.h | 1 + ir.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++-- ir.h | 2 ++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/gmqcc.h b/gmqcc.h index 10b74f5..0294189 100644 --- a/gmqcc.h +++ b/gmqcc.h @@ -4,6 +4,7 @@ #include #include #include +#include using std::move; #include #include diff --git a/ir.cpp b/ir.cpp index 0f7989f..1031935 100644 --- a/ir.cpp +++ b/ir.cpp @@ -3300,6 +3300,41 @@ static void gen_vector_fields(code_t *code, prog_section_field_t fld, const char mem_d(component); } +// Check if the value can be reused from a previous value. If so, copy the +// `m_code` segment and return `true`. Othrewise return false and, if the value +// is eligable to be reused later, record it in `m_reusable_const_floats`. +bool ir_builder::generateMergedFloat(ir_value *global, bool register_only) +{ + if ((global->m_flags & IR_FLAG_INCLUDE_DEF) + || global->m_callparam || global->m_locked || global->m_unique_life + || global->m_memberof + || global->m_members[0] + || global->m_members[1] + || global->m_members[2] + || global->m_store != store_global + ) + { + return false; + } + + if (!global->m_writes.empty()) { + irerror(global->m_context, "writing to a global const"); + return false; + } + + auto old = m_reusable_const_floats.find(global->m_constval.vint); + if (old == m_reusable_const_floats.end()) { + auto iptr = (int32_t*)&global->m_constval.ivec[0]; + m_reusable_const_floats[*iptr] = global; + return false; + } else if (register_only) { + return false; + } else { + global->m_code = old->second->m_code; + return true; + } +} + bool ir_builder::generateGlobal(ir_value *global, bool islocal) { size_t i; @@ -3401,8 +3436,13 @@ bool ir_builder::generateGlobal(ir_value *global, bool islocal) { global->setCodeAddress(m_code->globals.size()); if (global->m_hasvalue) { - if (global->m_cvq == CV_CONST && global->m_reads.empty()) - return true; + if (global->m_cvq == CV_CONST) { + if (global->m_reads.empty()) + return true; + + if (!islocal && generateMergedFloat(global, pushdef)) + return global->m_code.globaladdr >= 0; + } iptr = (int32_t*)&global->m_constval.ivec[0]; m_code->globals.push_back(*iptr); } else { diff --git a/ir.h b/ir.h index c81d1a2..8ca8528 100644 --- a/ir.h +++ b/ir.h @@ -273,6 +273,7 @@ struct ir_builder { std::vector> m_fields; // for reusing them in vector-splits, TODO: sort this or use a radix-tree std::vector m_const_floats; + std::map m_reusable_const_floats; ht m_htfunctions; ht m_htglobals; @@ -313,6 +314,7 @@ private: bool generateGlobalFunction(ir_value*); bool generateGlobalFunctionCode(ir_value*); bool generateFunctionLocals(ir_value*); + bool generateMergedFloat(ir_value*, bool register_only); }; /* -- 2.39.2