From 9d3604e57b80856794363f45ffd98bfe0d93c09a Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Wed, 23 Dec 2015 17:01:40 +0200 Subject: [PATCH] [jit] Refactor strength reduction handling within mono_local_cprop --- mono/mini/local-propagation.c | 222 ++++++++++++++++++---------------- 1 file changed, 116 insertions(+), 106 deletions(-) diff --git a/mono/mini/local-propagation.c b/mono/mini/local-propagation.c index aa2a934f556..145d8fbc28f 100644 --- a/mono/mini/local-propagation.c +++ b/mono/mini/local-propagation.c @@ -41,6 +41,119 @@ mono_bitset_mp_new_noinit (MonoMemPool *mp, guint32 max_size) return mono_bitset_mem_new (mem, max_size, MONO_BITSET_DONT_FREE); } +/* + * Replaces ins with optimized opcodes. + * Returns TRUE if additional vregs were allocated. + */ +static gboolean +mono_strength_reduction_ins (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, const char **spec) +{ + gboolean allocated_vregs = FALSE; + + /* FIXME: Add long/float */ + switch (ins->opcode) { + case OP_MOVE: + case OP_XMOVE: + if (ins->dreg == ins->sreg1) { + MONO_DELETE_INS (bb, ins); + } + break; + case OP_ADD_IMM: + case OP_IADD_IMM: + case OP_SUB_IMM: + case OP_ISUB_IMM: +#if SIZEOF_REGISTER == 8 + case OP_LADD_IMM: + case OP_LSUB_IMM: +#endif + if (ins->inst_imm == 0) { + ins->opcode = OP_MOVE; + } + break; + case OP_MUL_IMM: + case OP_IMUL_IMM: +#if SIZEOF_REGISTER == 8 + case OP_LMUL_IMM: +#endif + if (ins->inst_imm == 0) { + ins->opcode = (ins->opcode == OP_LMUL_IMM) ? OP_I8CONST : OP_ICONST; + ins->inst_c0 = 0; + ins->sreg1 = -1; + } else if (ins->inst_imm == 1) { + ins->opcode = OP_MOVE; + } else if ((ins->opcode == OP_IMUL_IMM) && (ins->inst_imm == -1)) { + ins->opcode = OP_INEG; + } else if ((ins->opcode == OP_LMUL_IMM) && (ins->inst_imm == -1)) { + ins->opcode = OP_LNEG; + } else { + int power2 = mono_is_power_of_two (ins->inst_imm); + if (power2 >= 0) { + ins->opcode = (ins->opcode == OP_MUL_IMM) ? OP_SHL_IMM : ((ins->opcode == OP_LMUL_IMM) ? OP_LSHL_IMM : OP_ISHL_IMM); + ins->inst_imm = power2; + } + } + break; + case OP_IREM_UN_IMM: + case OP_IDIV_UN_IMM: { + int c = ins->inst_imm; + int power2 = mono_is_power_of_two (c); + + if (power2 >= 0) { + if (ins->opcode == OP_IREM_UN_IMM) { + ins->opcode = OP_IAND_IMM; + ins->sreg2 = -1; + ins->inst_imm = (1 << power2) - 1; + } else if (ins->opcode == OP_IDIV_UN_IMM) { + ins->opcode = OP_ISHR_UN_IMM; + ins->sreg2 = -1; + ins->inst_imm = power2; + } + } + break; + } + case OP_IDIV_IMM: { + int c = ins->inst_imm; + int power2 = mono_is_power_of_two (c); + MonoInst *tmp1, *tmp2, *tmp3, *tmp4; + + /* FIXME: Move this elsewhere cause its hard to implement it here */ + if (power2 == 1) { + int r1 = mono_alloc_ireg (cfg); + + NEW_BIALU_IMM (cfg, tmp1, OP_ISHR_UN_IMM, r1, ins->sreg1, 31); + mono_bblock_insert_after_ins (bb, ins, tmp1); + NEW_BIALU (cfg, tmp2, OP_IADD, r1, r1, ins->sreg1); + mono_bblock_insert_after_ins (bb, tmp1, tmp2); + NEW_BIALU_IMM (cfg, tmp3, OP_ISHR_IMM, ins->dreg, r1, 1); + mono_bblock_insert_after_ins (bb, tmp2, tmp3); + + NULLIFY_INS (ins); + allocated_vregs = TRUE; + } else if (power2 > 0 && power2 < 31) { + int r1 = mono_alloc_ireg (cfg); + + NEW_BIALU_IMM (cfg, tmp1, OP_ISHR_IMM, r1, ins->sreg1, 31); + mono_bblock_insert_after_ins (bb, ins, tmp1); + NEW_BIALU_IMM (cfg, tmp2, OP_ISHR_UN_IMM, r1, r1, (32 - power2)); + mono_bblock_insert_after_ins (bb, tmp1, tmp2); + NEW_BIALU (cfg, tmp3, OP_IADD, r1, r1, ins->sreg1); + mono_bblock_insert_after_ins (bb, tmp2, tmp3); + NEW_BIALU_IMM (cfg, tmp4, OP_ISHR_IMM, ins->dreg, r1, power2); + mono_bblock_insert_after_ins (bb, tmp3, tmp4); + + NULLIFY_INS (ins); + allocated_vregs = TRUE; + } + break; + } + default: + break; + } + + *spec = INS_INFO (ins->opcode); + return allocated_vregs; +} + /* * mono_local_cprop: * @@ -280,112 +393,9 @@ restart: } /* Do strength reduction here */ - /* FIXME: Add long/float */ - switch (ins->opcode) { - case OP_MOVE: - case OP_XMOVE: - if (ins->dreg == ins->sreg1) { - MONO_DELETE_INS (bb, ins); - spec = INS_INFO (ins->opcode); - } - break; - case OP_ADD_IMM: - case OP_IADD_IMM: - case OP_SUB_IMM: - case OP_ISUB_IMM: -#if SIZEOF_REGISTER == 8 - case OP_LADD_IMM: - case OP_LSUB_IMM: -#endif - if (ins->inst_imm == 0) { - ins->opcode = OP_MOVE; - spec = INS_INFO (ins->opcode); - } - break; - case OP_MUL_IMM: - case OP_IMUL_IMM: -#if SIZEOF_REGISTER == 8 - case OP_LMUL_IMM: -#endif - if (ins->inst_imm == 0) { - ins->opcode = (ins->opcode == OP_LMUL_IMM) ? OP_I8CONST : OP_ICONST; - ins->inst_c0 = 0; - ins->sreg1 = -1; - } else if (ins->inst_imm == 1) { - ins->opcode = OP_MOVE; - } else if ((ins->opcode == OP_IMUL_IMM) && (ins->inst_imm == -1)) { - ins->opcode = OP_INEG; - } else if ((ins->opcode == OP_LMUL_IMM) && (ins->inst_imm == -1)) { - ins->opcode = OP_LNEG; - } else { - int power2 = mono_is_power_of_two (ins->inst_imm); - if (power2 >= 0) { - ins->opcode = (ins->opcode == OP_MUL_IMM) ? OP_SHL_IMM : ((ins->opcode == OP_LMUL_IMM) ? OP_LSHL_IMM : OP_ISHL_IMM); - ins->inst_imm = power2; - } - } - spec = INS_INFO (ins->opcode); - break; - case OP_IREM_UN_IMM: - case OP_IDIV_UN_IMM: { - int c = ins->inst_imm; - int power2 = mono_is_power_of_two (c); - - if (power2 >= 0) { - if (ins->opcode == OP_IREM_UN_IMM) { - ins->opcode = OP_IAND_IMM; - ins->sreg2 = -1; - ins->inst_imm = (1 << power2) - 1; - } else if (ins->opcode == OP_IDIV_UN_IMM) { - ins->opcode = OP_ISHR_UN_IMM; - ins->sreg2 = -1; - ins->inst_imm = power2; - } - } - spec = INS_INFO (ins->opcode); - break; - } - case OP_IDIV_IMM: { - int c = ins->inst_imm; - int power2 = mono_is_power_of_two (c); - MonoInst *tmp1, *tmp2, *tmp3, *tmp4; - - /* FIXME: Move this elsewhere cause its hard to implement it here */ - if (power2 == 1) { - int r1 = mono_alloc_ireg (cfg); - - NEW_BIALU_IMM (cfg, tmp1, OP_ISHR_UN_IMM, r1, ins->sreg1, 31); - mono_bblock_insert_after_ins (bb, ins, tmp1); - NEW_BIALU (cfg, tmp2, OP_IADD, r1, r1, ins->sreg1); - mono_bblock_insert_after_ins (bb, tmp1, tmp2); - NEW_BIALU_IMM (cfg, tmp3, OP_ISHR_IMM, ins->dreg, r1, 1); - mono_bblock_insert_after_ins (bb, tmp2, tmp3); - - NULLIFY_INS (ins); - - // We allocated a new vreg, so need to restart - goto restart; - } else if (power2 > 0 && power2 < 31) { - int r1 = mono_alloc_ireg (cfg); - - NEW_BIALU_IMM (cfg, tmp1, OP_ISHR_IMM, r1, ins->sreg1, 31); - mono_bblock_insert_after_ins (bb, ins, tmp1); - NEW_BIALU_IMM (cfg, tmp2, OP_ISHR_UN_IMM, r1, r1, (32 - power2)); - mono_bblock_insert_after_ins (bb, tmp1, tmp2); - NEW_BIALU (cfg, tmp3, OP_IADD, r1, r1, ins->sreg1); - mono_bblock_insert_after_ins (bb, tmp2, tmp3); - NEW_BIALU_IMM (cfg, tmp4, OP_ISHR_IMM, ins->dreg, r1, power2); - mono_bblock_insert_after_ins (bb, tmp3, tmp4); - - NULLIFY_INS (ins); - - // We allocated a new vreg, so need to restart - goto restart; - } - break; - } - } - + if (mono_strength_reduction_ins (cfg, bb, ins, &spec)) + goto restart; + if (spec [MONO_INST_DEST] != ' ') { MonoInst *def = defs [ins->dreg]; -- 2.25.1