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:
*
}
/* 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];