MonoInst *
mono_branch_optimize_exception_target (MonoCompile *cfg, MonoBasicBlock *bb, const char * exname)
{
- MonoMethod *method = cfg->method;
- MonoMethodHeader *header = mono_method_get_header (method);
+ MonoMethodHeader *header = cfg->header;
MonoExceptionClause *clause;
MonoClass *exclass;
int i;
return jump;
}
+ return NULL;
+ } else {
+ /* Branching to an outer clause could skip inner clauses */
return NULL;
}
} else {
if (cfg->ret && ins1->dreg == cfg->ret->dreg)
continue;
+ if (!(cfg->opt & MONO_OPT_DEADCE))
+ /*
+ * It is possible that dreg is never set before, so we can't use
+ * it as an sreg of the cmov instruction (#582322).
+ */
+ continue;
+
if (cfg->verbose_level > 2) {
printf ("\tBranch -> CMove optimization (2) in BB%d on\n", bb->block_num);
printf ("\t\t"); mono_print_ins (compare);
if ((bb->out_bb [0]->in_count == 1) && (bb->out_bb [0] != cfg->bb_exit) &&
(bb->region == bb->out_bb [0]->region)) {
mono_merge_basic_blocks (cfg, bb, bb->out_bb [0]);
+
+ /*
+ * bbn might have fallen through to the next bb without a branch,
+ * have to add one now (#474718).
+ * FIXME: Maybe need to do this more generally in
+ * merge_basic_blocks () ?
+ */
+ if (!(bb->last_ins && MONO_IS_BRANCH_OP (bb->last_ins)) && bb->out_count) {
+ MONO_INST_NEW (cfg, ins1, OP_BR);
+ ins1->inst_target_bb = bb->out_bb [0];
+ MONO_ADD_INS (bb, ins1);
+ }
goto restart;
}
}
mono_handle_global_vregs (cfg);
if (cfg->opt & (MONO_OPT_CONSPROP | MONO_OPT_COPYPROP))
mono_local_cprop (cfg);
- mono_local_deadce (cfg);
+ if (cfg->opt & MONO_OPT_DEADCE)
+ mono_local_deadce (cfg);
}
#endif
}
mono_unlink_bblock (cfg, bbn, bbn->out_bb [0]);
/* Handle the branch at the end of the bb */
- for (inst = bb->code; inst != NULL; inst = inst->next) {
- if (inst->opcode == OP_CALL_HANDLER) {
- g_assert (inst->inst_target_bb == bbn);
- NULLIFY_INS (inst);
+ if (bb->has_call_handler) {
+ for (inst = bb->code; inst != NULL; inst = inst->next) {
+ if (inst->opcode == OP_CALL_HANDLER) {
+ g_assert (inst->inst_target_bb == bbn);
+ NULLIFY_INS (inst);
+ }
}
- if (MONO_IS_JUMP_TABLE (inst)) {
- int i;
- MonoJumpInfoBBTable *table = MONO_JUMP_TABLE_FROM_INS (inst);
- for (i = 0; i < table->table_size; i++ ) {
- /* Might be already NULL from a previous merge */
- if (table->table [i])
- g_assert (table->table [i] == bbn);
- table->table [i] = NULL;
+ }
+ if (bb->has_jump_table) {
+ for (inst = bb->code; inst != NULL; inst = inst->next) {
+ if (MONO_IS_JUMP_TABLE (inst)) {
+ int i;
+ MonoJumpInfoBBTable *table = MONO_JUMP_TABLE_FROM_INS (inst);
+ for (i = 0; i < table->table_size; i++ ) {
+ /* Might be already NULL from a previous merge */
+ if (table->table [i])
+ g_assert (table->table [i] == bbn);
+ table->table [i] = NULL;
+ }
+ /* Can't nullify this as later instructions depend on it */
}
- /* Can't nullify this as later instructions depend on it */
}
}
if (bb->last_ins && MONO_IS_COND_BRANCH_OP (bb->last_ins)) {
NULLIFY_INS (bb->last_ins);
}
+ bb->has_call_handler |= bbn->has_call_handler;
+ bb->has_jump_table |= bbn->has_jump_table;
+
if (bb->last_ins) {
if (bbn->code) {
bb->last_ins->next = bbn->code;
bb->code = bbn->code;
bb->last_ins = bbn->last_ins;
}
+
for (prev_bb = cfg->bb_entry; prev_bb && prev_bb->next_bb != bbn; prev_bb = prev_bb->next_bb)
;
if (prev_bb) {
bb->next_bb = bbn->next_bb;
}
mono_nullify_basic_block (bbn);
+
+ /*
+ * If bbn fell through to its next bblock, have to add a branch, since bb
+ * will not fall though to the same bblock (#513931).
+ */
+ if (bb->last_ins && bb->out_count == 1 && bb->out_bb [0] != bb->next_bb && !MONO_IS_BRANCH_OP (bb->last_ins)) {
+ MONO_INST_NEW (cfg, inst, OP_BR);
+ inst->inst_target_bb = bb->out_bb [0];
+ MONO_ADD_INS (bb, inst);
+ }
}
static void
/* the block are in sequence anyway ... */
/* branches to the following block can be removed */
- if (bb->last_ins && bb->last_ins->opcode == OP_BR) {
+ if (bb->last_ins && bb->last_ins->opcode == OP_BR && !bbn->out_of_line) {
bb->last_ins->opcode = OP_NOP;
changed = TRUE;
if (cfg->verbose_level > 2)
}
if (bb->last_ins && MONO_IS_COND_BRANCH_NOFP (bb->last_ins)) {
- if (bb->last_ins->inst_false_bb && bb->last_ins->inst_false_bb->out_of_line && (bb->region == bb->last_ins->inst_false_bb->region)) {
+ if (bb->last_ins->inst_false_bb && bb->last_ins->inst_false_bb->out_of_line && (bb->region == bb->last_ins->inst_false_bb->region) && !cfg->disable_out_of_line_bblocks) {
/* Reverse the branch */
bb->last_ins->opcode = mono_reverse_branch_op (bb->last_ins->opcode);
bbn = bb->last_ins->inst_false_bb;