]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
ir: more aggressively reuse const floats main xonotic-v0.8.6
authorWolfgang Bumiller <wry.git@bumiller.com>
Thu, 16 Feb 2023 19:22:18 +0000 (20:22 +0100)
committerWolfgang Bumiller <w.bumiller@proxmox.com>
Fri, 5 May 2023 06:42:03 +0000 (08:42 +0200)
Signed-off-by: Wolfgang Bumiller <wry.git@bumiller.com>
Closes #202

gmqcc.h
ir.cpp
ir.h

diff --git a/gmqcc.h b/gmqcc.h
index 10b74f5ab2741e92ff9421fc7a3d8bc2ac888244..0294189315591e66d87f3f4ce867c78dac81b474 100644 (file)
--- a/gmqcc.h
+++ b/gmqcc.h
@@ -4,6 +4,7 @@
 #include <string>
 #include <utility>
 #include <memory>
+#include <map>
 using std::move;
 #include <stdarg.h>
 #include <stddef.h>
diff --git a/ir.cpp b/ir.cpp
index 0f7989f328e2f8501f4158e73751cd28742548b7..1031935e5f242e718eda02521cf2a5bf0592551a 100644 (file)
--- 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 c81d1a24032454972fcfddbb5965992547cb6f4c..8ca85283aa6789d54fb322731ec788db6e2cbe39 100644 (file)
--- a/ir.h
+++ b/ir.h
@@ -273,6 +273,7 @@ struct ir_builder {
     std::vector<std::unique_ptr<ir_value>>    m_fields;
     // for reusing them in vector-splits, TODO: sort this or use a radix-tree
     std::vector<ir_value*>                    m_const_floats;
+    std::map<int32_t, ir_value*>              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);
 };
 
 /*