]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ir.c
Constant fold intrinsics if their arguments are constant. TODO: reference count intri...
[xonotic/gmqcc.git] / ir.c
diff --git a/ir.c b/ir.c
index d77f0110e62a87a6f6d152f3309e1b2cb2be5390..7a04e3b9ef89127fa067ac1c8122f5450d736b3b 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -642,7 +642,7 @@ static bool ir_function_pass_peephole(ir_function *self)
                 if (!instr_is_operation(oper->opcode))
                     continue;
 
-                /* Old engine's mul for vector+float cannot deal with aliased inputs. */
+                /* Don't change semantics of MUL_VF in engines where these may not alias. */
                 if (OPTS_FLAG(LEGACY_VECTOR_MATHS)) {
                     if (oper->opcode == INSTR_MUL_VF && oper->_ops[2]->memberof == oper->_ops[1])
                         continue;
@@ -650,18 +650,6 @@ static bool ir_function_pass_peephole(ir_function *self)
                         continue;
                 }
 
-                /* Emulated bitxor cannot deal with aliased inputs. */
-                if (oper->opcode == VINSTR_BITXOR && oper->_ops[2]->memberof == oper->_ops[1])
-                    continue;
-
-                /* Emulated bitand/bitor for vector+float cannot deal with aliased inputs. */
-                if (oper->opcode == VINSTR_BITAND_VF && oper->_ops[2]->memberof == oper->_ops[1])
-                    continue;
-                if (oper->opcode == VINSTR_BITOR_VF && oper->_ops[2]->memberof == oper->_ops[1])
-                    continue;
-                if (oper->opcode == VINSTR_BITXOR_VF && oper->_ops[2]->memberof == oper->_ops[1])
-                    continue;
-
                 value = oper->_ops[0];
 
                 /* only do it for SSA values */
@@ -2526,9 +2514,9 @@ static bool ir_block_life_propagate(ir_block *self, bool *changed)
          * same source and destination operand otherwise, as the engine may
          * read the source multiple times. */
         if (instr->opcode == INSTR_MUL_VF ||
-            instr->opcode == VINSTR_BITXOR ||
             instr->opcode == VINSTR_BITAND_VF ||
             instr->opcode == VINSTR_BITOR_VF ||
+            instr->opcode == VINSTR_BITXOR ||
             instr->opcode == VINSTR_BITXOR_VF ||
             instr->opcode == VINSTR_BITXOR_V)
         {
@@ -2539,7 +2527,12 @@ static bool ir_block_life_propagate(ir_block *self, bool *changed)
             if (value->memberof && ir_value_life_merge(value->memberof, instr->eid+1))
                 *changed = true;
         }
-        else if (instr->opcode == INSTR_MUL_FV || instr->opcode == INSTR_LOAD_V)
+
+        if (instr->opcode == INSTR_MUL_FV ||
+            instr->opcode == INSTR_LOAD_V ||
+            instr->opcode == VINSTR_BITXOR ||
+            instr->opcode == VINSTR_BITXOR_VF ||
+            instr->opcode == VINSTR_BITXOR_V)
         {
             value = instr->_ops[1];
             /* the float source will get an additional lifetime */
@@ -2822,7 +2815,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc
             stmt.o2.s1 = 0;
             stmt.o3.s1 = 0;
             if (stmt.o1.s1 != 1)
-                code_push_statement(code, &stmt, instr->context.line);
+                code_push_statement(code, &stmt, instr->context);
 
             /* no further instructions can be in this block */
             return true;
@@ -2833,17 +2826,17 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc
             stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]);
             stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]);
             stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]);
-            code_push_statement(code, &stmt, instr->context.line);
+            code_push_statement(code, &stmt, instr->context);
             stmt.opcode = INSTR_BITAND;
             stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]);
             stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]);
             stmt.o3.s1 = ir_value_code_addr(func->owner->vinstr_temp[0]);
-            code_push_statement(code, &stmt, instr->context.line);
+            code_push_statement(code, &stmt, instr->context);
             stmt.opcode = INSTR_SUB_F;
             stmt.o1.s1 = ir_value_code_addr(instr->_ops[0]);
             stmt.o2.s1 = ir_value_code_addr(func->owner->vinstr_temp[0]);
             stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]);
-            code_push_statement(code, &stmt, instr->context.line);
+            code_push_statement(code, &stmt, instr->context);
 
             /* instruction generated */
             continue;
@@ -2854,15 +2847,15 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc
             stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]);
             stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]);
             stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]);
-            code_push_statement(code, &stmt, instr->context.line);
+            code_push_statement(code, &stmt, instr->context);
             ++stmt.o1.s1;
             ++stmt.o2.s1;
             ++stmt.o3.s1;
-            code_push_statement(code, &stmt, instr->context.line);
+            code_push_statement(code, &stmt, instr->context);
             ++stmt.o1.s1;
             ++stmt.o2.s1;
             ++stmt.o3.s1;
-            code_push_statement(code, &stmt, instr->context.line);
+            code_push_statement(code, &stmt, instr->context);
 
             /* instruction generated */
             continue;
@@ -2873,15 +2866,15 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc
             stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]);
             stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]);
             stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]);
-            code_push_statement(code, &stmt, instr->context.line);
+            code_push_statement(code, &stmt, instr->context);
             ++stmt.o1.s1;
             ++stmt.o2.s1;
             ++stmt.o3.s1;
-            code_push_statement(code, &stmt, instr->context.line);
+            code_push_statement(code, &stmt, instr->context);
             ++stmt.o1.s1;
             ++stmt.o2.s1;
             ++stmt.o3.s1;
-            code_push_statement(code, &stmt, instr->context.line);
+            code_push_statement(code, &stmt, instr->context);
 
             /* instruction generated */
             continue;
@@ -2893,18 +2886,18 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc
                 stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]) + j;
                 stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]) + j;
                 stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]) + j;
-                code_push_statement(code, &stmt, instr->context.line);
+                code_push_statement(code, &stmt, instr->context);
                 stmt.opcode = INSTR_BITAND;
                 stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]) + j;
                 stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]) + j;
                 stmt.o3.s1 = ir_value_code_addr(func->owner->vinstr_temp[0]) + j;
-                code_push_statement(code, &stmt, instr->context.line);
+                code_push_statement(code, &stmt, instr->context);
             }
             stmt.opcode = INSTR_SUB_V;
             stmt.o1.s1 = ir_value_code_addr(instr->_ops[0]);
             stmt.o2.s1 = ir_value_code_addr(func->owner->vinstr_temp[0]);
             stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]);
-            code_push_statement(code, &stmt, instr->context.line);
+            code_push_statement(code, &stmt, instr->context);
 
             /* instruction generated */
             continue;
@@ -2915,13 +2908,13 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc
             stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]);
             stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]);
             stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]);
-            code_push_statement(code, &stmt, instr->context.line);
+            code_push_statement(code, &stmt, instr->context);
             ++stmt.o1.s1;
             ++stmt.o3.s1;
-            code_push_statement(code, &stmt, instr->context.line);
+            code_push_statement(code, &stmt, instr->context);
             ++stmt.o1.s1;
             ++stmt.o3.s1;
-            code_push_statement(code, &stmt, instr->context.line);
+            code_push_statement(code, &stmt, instr->context);
 
             /* instruction generated */
             continue;
@@ -2932,13 +2925,13 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc
             stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]);
             stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]);
             stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]);
-            code_push_statement(code, &stmt, instr->context.line);
+            code_push_statement(code, &stmt, instr->context);
             ++stmt.o1.s1;
             ++stmt.o3.s1;
-            code_push_statement(code, &stmt, instr->context.line);
+            code_push_statement(code, &stmt, instr->context);
             ++stmt.o1.s1;
             ++stmt.o3.s1;
-            code_push_statement(code, &stmt, instr->context.line);
+            code_push_statement(code, &stmt, instr->context);
 
             /* instruction generated */
             continue;
@@ -2950,18 +2943,18 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc
                 stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]) + j;
                 stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]);
                 stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]) + j;
-                code_push_statement(code, &stmt, instr->context.line);
+                code_push_statement(code, &stmt, instr->context);
                 stmt.opcode = INSTR_BITAND;
                 stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]) + j;
                 stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]);
                 stmt.o3.s1 = ir_value_code_addr(func->owner->vinstr_temp[0]) + j;
-                code_push_statement(code, &stmt, instr->context.line);
+                code_push_statement(code, &stmt, instr->context);
             }
             stmt.opcode = INSTR_SUB_V;
             stmt.o1.s1 = ir_value_code_addr(instr->_ops[0]);
             stmt.o2.s1 = ir_value_code_addr(func->owner->vinstr_temp[0]);
             stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]);
-            code_push_statement(code, &stmt, instr->context.line);
+            code_push_statement(code, &stmt, instr->context);
 
             /* instruction generated */
             continue;
@@ -2982,13 +2975,13 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc
                 stmt.opcode = INSTR_IF;
                 stmt.o2.s1 = (ontrue->code_start) - vec_size(code->statements);
                 if (stmt.o2.s1 != 1)
-                    code_push_statement(code, &stmt, instr->context.line);
+                    code_push_statement(code, &stmt, instr->context);
             }
             if (onfalse->generated) {
                 stmt.opcode = INSTR_IFNOT;
                 stmt.o2.s1 = (onfalse->code_start) - vec_size(code->statements);
                 if (stmt.o2.s1 != 1)
-                    code_push_statement(code, &stmt, instr->context.line);
+                    code_push_statement(code, &stmt, instr->context);
             }
             if (!ontrue->generated) {
                 if (onfalse->generated)
@@ -3008,7 +3001,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc
                 ontrue = tmp;
             }
             stidx = vec_size(code->statements);
-            code_push_statement(code, &stmt, instr->context.line);
+            code_push_statement(code, &stmt, instr->context);
             /* on false we jump, so add ontrue-path */
             if (!gen_blocks_recursive(code, func, ontrue))
                 return false;
@@ -3040,7 +3033,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc
                 stmt.o2.s1 = 0;
                 stmt.o3.s1 = 0;
                 if (stmt.o1.s1 != 1)
-                    code_push_statement(code, &stmt, instr->context.line);
+                    code_push_statement(code, &stmt, instr->context);
                 return true;
             }
             else if (stidx+2 == vec_size(code->statements) && code->statements[stidx].o2.s1 == 1) {
@@ -3079,7 +3072,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc
                     stmt.opcode = type_store_instr[param->vtype];
                 stmt.o1.u1 = ir_value_code_addr(param);
                 stmt.o2.u1 = OFS_PARM0 + 3 * p;
-                code_push_statement(code, &stmt, instr->context.line);
+                code_push_statement(code, &stmt, instr->context);
             }
             /* Now handle extparams */
             first = vec_size(instr->params);
@@ -3108,7 +3101,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc
                     stmt.opcode = type_store_instr[param->vtype];
                 stmt.o1.u1 = ir_value_code_addr(param);
                 stmt.o2.u1 = ir_value_code_addr(targetparam);
-                code_push_statement(code, &stmt, instr->context.line);
+                code_push_statement(code, &stmt, instr->context);
             }
 
             stmt.opcode = INSTR_CALL0 + vec_size(instr->params);
@@ -3117,7 +3110,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc
             stmt.o1.u1 = ir_value_code_addr(instr->_ops[1]);
             stmt.o2.u1 = 0;
             stmt.o3.u1 = 0;
-            code_push_statement(code, &stmt, instr->context.line);
+            code_push_statement(code, &stmt, instr->context);
 
             retvalue = instr->_ops[0];
             if (retvalue && retvalue->store != store_return &&
@@ -3131,7 +3124,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc
                 stmt.o1.u1 = OFS_RETURN;
                 stmt.o2.u1 = ir_value_code_addr(retvalue);
                 stmt.o3.u1 = 0;
-                code_push_statement(code, &stmt, instr->context.line);
+                code_push_statement(code, &stmt, instr->context);
             }
             continue;
         }
@@ -3181,7 +3174,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc
             }
         }
 
-        code_push_statement(code, &stmt, instr->context.line);
+        code_push_statement(code, &stmt, instr->context);
     }
     return true;
 }
@@ -3218,11 +3211,16 @@ static bool gen_function_code(code_t *code, ir_function *self)
         retst->opcode = INSTR_DONE;
         ++opts_optimizationcount[OPTIM_VOID_RETURN];
     } else {
+        lex_ctx_t last;
+
         stmt.opcode = INSTR_DONE;
-        stmt.o1.u1 = 0;
-        stmt.o2.u1 = 0;
-        stmt.o3.u1 = 0;
-        code_push_statement(code, &stmt, vec_last(code->linenums));
+        stmt.o1.u1  = 0;
+        stmt.o2.u1  = 0;
+        stmt.o3.u1  = 0;
+        last.line   = vec_last(code->linenums);
+        last.column = vec_last(code->columnnums);
+
+        code_push_statement(code, &stmt, last);
     }
     return true;
 }
@@ -3355,7 +3353,7 @@ static bool gen_function_extparam_copy(code_t *code, ir_function *self)
         }
         stmt.o1.u1 = ir_value_code_addr(ep);
         stmt.o2.u1 = ir_value_code_addr(self->locals[i]);
-        code_push_statement(code, &stmt, self->context.line);
+        code_push_statement(code, &stmt, self->context);
     }
 
     return true;
@@ -3380,7 +3378,7 @@ static bool gen_function_varargs_copy(code_t *code, ir_function *self)
         if (i < 8) {
             stmt.o1.u1 = OFS_PARM0 + 3*i;
             stmt.o2.u1 = ir_value_code_addr(self->locals[i]);
-            code_push_statement(code, &stmt, self->context.line);
+            code_push_statement(code, &stmt, self->context);
             continue;
         }
         ext = i - 8;
@@ -3391,7 +3389,7 @@ static bool gen_function_varargs_copy(code_t *code, ir_function *self)
 
         stmt.o1.u1 = ir_value_code_addr(ep);
         stmt.o2.u1 = ir_value_code_addr(self->locals[i]);
-        code_push_statement(code, &stmt, self->context.line);
+        code_push_statement(code, &stmt, self->context);
     }
 
     return true;
@@ -3876,11 +3874,16 @@ bool ir_builder_generate(ir_builder *self, const char *filename)
     /* DP errors if the last instruction is not an INSTR_DONE. */
     if (vec_last(self->code->statements).opcode != INSTR_DONE)
     {
+        lex_ctx_t last;
+
         stmt.opcode = INSTR_DONE;
-        stmt.o1.u1 = 0;
-        stmt.o2.u1 = 0;
-        stmt.o3.u1 = 0;
-        code_push_statement(self->code, &stmt, vec_last(self->code->linenums));
+        stmt.o1.u1  = 0;
+        stmt.o2.u1  = 0;
+        stmt.o3.u1  = 0;
+        last.line   = vec_last(self->code->linenums);
+        last.column = vec_last(self->code->columnnums);
+
+        code_push_statement(self->code, &stmt, last);
     }
 
     if (OPTS_OPTION_BOOL(OPTION_PP_ONLY))