X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=ir.c;h=73cbc9af06abec83170abbf9e3b98c9bb867f28a;hp=00d81c25dbb5ae3334b560f1e01476c1afd8cc31;hb=6024e377ba11dcbcf24577100d95355536e0c9db;hpb=806850e4083d3a993fdb941cddb5c257d37f3617 diff --git a/ir.c b/ir.c index 00d81c2..73cbc9a 100644 --- a/ir.c +++ b/ir.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013, 2014 + * Copyright (C) 2012, 2013, 2014, 2015 * Wolfgang Bumiller * Dale Weiler * @@ -1124,6 +1124,7 @@ ir_value* ir_value_var(const char *name, int storetype, int vtype) /* helper function */ static ir_value* ir_builder_imm_float(ir_builder *self, float value, bool add_to_list) { ir_value *v = ir_value_var("#IMMEDIATE", store_global, TYPE_FLOAT); + v->flags |= IR_FLAG_ERASABLE; v->hasvalue = true; v->cvq = CV_CONST; v->constval.vfloat = value; @@ -1916,6 +1917,9 @@ ir_value* ir_block_create_unary(ir_block *self, lex_ctx_t ctx, ir_value *operand) { int ot = TYPE_FLOAT; + ir_value *minus_1 = NULL; + if (opcode == VINSTR_NEG_F || opcode == VINSTR_NEG_V) + minus_1 = ir_builder_imm_float(self->owner->owner, -1.0f, false); switch (opcode) { case INSTR_NOT_F: case INSTR_NOT_V: @@ -1925,15 +1929,11 @@ ir_value* ir_block_create_unary(ir_block *self, lex_ctx_t ctx, case INSTR_NOT_I: */ ot = TYPE_FLOAT; break; - - /* - * Negation for virtual instructions is emulated with 0-value. Thankfully - * the operand for 0 already exists so we just source it from here. - */ + /* Negation is implemented as -1 * */ case VINSTR_NEG_F: - return ir_block_create_general_instr(self, ctx, label, INSTR_SUB_F, NULL, operand, ot); + return ir_block_create_general_instr(self, ctx, label, INSTR_MUL_F, minus_1, operand, TYPE_FLOAT); case VINSTR_NEG_V: - return ir_block_create_general_instr(self, ctx, label, INSTR_SUB_V, NULL, operand, TYPE_VECTOR); + return ir_block_create_general_instr(self, ctx, label, INSTR_MUL_FV, minus_1, operand, TYPE_VECTOR); default: ot = operand->vtype; @@ -3580,7 +3580,7 @@ static bool gen_global_function_code(ir_builder *ir, ir_value *global) * If there is no definition and the thing is eraseable, we can ignore * outputting the function to begin with. */ - if (global->flags & IR_FLAG_ERASEABLE && irfun->code_function_def < 0) { + if (global->flags & IR_FLAG_ERASABLE && irfun->code_function_def < 0) { return true; } @@ -3692,7 +3692,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc * if we're eraseable and the function isn't referenced ignore outputting * the function. */ - if (global->flags & IR_FLAG_ERASEABLE && vec_size(global->reads) == 0) { + if (global->flags & IR_FLAG_ERASABLE && vec_size(global->reads) == 0) { return true; } @@ -3771,6 +3771,8 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc { ir_value_code_setaddr(global, vec_size(self->code->globals)); if (global->hasvalue) { + if (global->cvq == CV_CONST && !vec_size(global->reads)) + return true; iptr = (int32_t*)&global->constval.ivec[0]; vec_push(self->code->globals, *iptr); } else { @@ -3786,7 +3788,10 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc { ir_value_code_setaddr(global, vec_size(self->code->globals)); if (global->hasvalue) { - uint32_t load = code_genstring(self->code, global->constval.vstring); + uint32_t load; + if (global->cvq == CV_CONST && !vec_size(global->reads)) + return true; + load = code_genstring(self->code, global->constval.vstring); vec_push(self->code->globals, load); } else { vec_push(self->code->globals, 0);