]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ir.c
'likely' hint for IFs
[xonotic/gmqcc.git] / ir.c
diff --git a/ir.c b/ir.c
index 9907b3585284a5770961786259003a608ecc9e73..bf0a7459120cb9ed2582832217ff8ec17b21d59c 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -654,6 +654,8 @@ ir_instr* ir_instr_new(ir_block* owner, int op)
     self->params = NULL;
 
     self->eid = 0;
+
+    self->likely = true;
     return self;
 }
 
@@ -1133,7 +1135,12 @@ bool ir_values_overlap(const ir_value *a, const ir_value *b)
 
 bool ir_block_create_store_op(ir_block *self, int op, ir_value *target, ir_value *what)
 {
-    ir_instr *in = ir_instr_new(self, op);
+    ir_instr *in;
+    if (self->final) {
+        irerror(self->context, "unreachable statement (%s)", self->label);
+        return false;
+    }
+    in = ir_instr_new(self, op);
     if (!in)
         return false;
 
@@ -1206,7 +1213,7 @@ bool ir_block_create_return(ir_block *self, ir_value *v)
 {
     ir_instr *in;
     if (self->final) {
-        irerror(self->context, "block already ended (%s)", self->label);
+        irerror(self->context, "unreachable statement (%s)", self->label);
         return false;
     }
     self->final = true;
@@ -1227,7 +1234,7 @@ bool ir_block_create_if(ir_block *self, ir_value *v,
 {
     ir_instr *in;
     if (self->final) {
-        irerror(self->context, "block already ended (%s)", self->label);
+        irerror(self->context, "unreachable statement (%s)", self->label);
         return false;
     }
     self->final = true;
@@ -1257,7 +1264,7 @@ bool ir_block_create_jump(ir_block *self, ir_block *to)
 {
     ir_instr *in;
     if (self->final) {
-        irerror(self->context, "block already ended (%s)", self->label);
+        irerror(self->context, "unreachable statement (%s)", self->label);
         return false;
     }
     self->final = true;
@@ -1277,7 +1284,7 @@ bool ir_block_create_goto(ir_block *self, ir_block *to)
 {
     ir_instr *in;
     if (self->final) {
-        irerror(self->context, "block already ended (%s)", self->label);
+        irerror(self->context, "unreachable statement (%s)", self->label);
         return false;
     }
     self->final = true;
@@ -1763,6 +1770,7 @@ bool ir_function_naive_phi(ir_function *self)
     return true;
 }
 
+#if 0
 static bool ir_naive_phi_emit_store(ir_block *block, size_t iid, ir_value *old, ir_value *what)
 {
     ir_instr *instr;
@@ -1780,10 +1788,11 @@ static bool ir_naive_phi_emit_store(ir_block *block, size_t iid, ir_value *old,
 
     return true;
 }
+#endif
 
 static bool ir_block_naive_phi(ir_block *self)
 {
-    size_t i, p, w;
+    size_t i, p; /*, w;*/
     /* FIXME: optionally, create_phi can add the phis
      * to a list so we don't need to loop through blocks
      * - anyway: "don't optimize YET"
@@ -1799,6 +1808,32 @@ static bool ir_block_naive_phi(ir_block *self)
 
         for (p = 0; p < vec_size(instr->phi); ++p)
         {
+            ir_value *v = instr->phi[p].value;
+            ir_block *b = instr->phi[p].from;
+
+            if (v->store == store_value &&
+                vec_size(v->reads) == 1 &&
+                vec_size(v->writes) == 1)
+            {
+                /* replace the value */
+                if (!ir_instr_op(v->writes[0], 0, instr->_ops[0], true))
+                    return false;
+            }
+            else
+            {
+                /* force a move instruction */
+                ir_instr *prevjump = vec_last(b->instr);
+                vec_pop(b->instr);
+                b->final = false;
+                instr->_ops[0]->store = store_global;
+                if (!ir_block_create_store(b, instr->_ops[0], v))
+                    return false;
+                instr->_ops[0]->store = store_value;
+                vec_push(b->instr, prevjump);
+                b->final = true;
+            }
+
+#if 0
             ir_value *v = instr->phi[p].value;
             for (w = 0; w < vec_size(v->writes); ++w) {
                 ir_value *old;
@@ -1848,6 +1883,7 @@ static bool ir_block_naive_phi(ir_block *self)
                     }
                 }
             }
+#endif
         }
         ir_instr_delete(instr);
     }
@@ -2467,6 +2503,13 @@ tailcall:
             }
             /* neither ontrue nor onfalse exist */
             stmt.opcode = INSTR_IFNOT;
+            if (!instr->likely) {
+                /* Honor the likelyhood hint */
+                ir_block *tmp = onfalse;
+                stmt.opcode = INSTR_IF;
+                onfalse = ontrue;
+                ontrue = tmp;
+            }
             stidx = vec_size(code_statements);
             vec_push(code_statements, stmt);
             /* on false we jump, so add ontrue-path */
@@ -2478,6 +2521,7 @@ tailcall:
             if (onfalse->generated) {
                 /* fixup the jump address */
                 code_statements[stidx].o2.s1 = (onfalse->code_start) - (stidx);
+                stmt.opcode = vec_last(code_statements).opcode;
                 /* may have been generated in the previous recursive call */
                 stmt.opcode = INSTR_GOTO;
                 stmt.o1.s1 = (onfalse->code_start) - vec_size(code_statements);