------- Comment #3 from kkojima at gcc dot gnu dot org 2006-08-23 04:35 ------- Here is a workaround. Although it doesn't solve the issue completely, it'd be better than nothing. It prevents to insert the mode switching code after the last insn of BB when that insn has the REG_EH_REGION note. It also checks if the last insn needs a mode which doesn't match with the mode given by the mode switching code in such case.
diff -uprN ORIG/trunk/gcc/mode-switching.c LOCAL/trunk/gcc/mode-switching.c --- ORIG/trunk/gcc/mode-switching.c 2006-03-09 15:11:37.000000000 +0900 +++ LOCAL/trunk/gcc/mode-switching.c 2006-08-22 09:55:23.000000000 +0900 @@ -612,9 +612,11 @@ optimize_mode_switching (void) of the previous block. */ if (eg->flags & EDGE_ABNORMAL) { + rtx last = BB_END (src_bb); + emited = true; - if (JUMP_P (BB_END (src_bb))) - emit_insn_before (mode_set, BB_END (src_bb)); + if (JUMP_P (last)) + emit_insn_before (mode_set, last); else { /* It doesn't make sense to switch to normal @@ -629,8 +631,19 @@ optimize_mode_switching (void) sense, anyway). In the case of EH edges, EH entry points also start in normal mode, so a similar reasoning applies. */ - gcc_assert (NONJUMP_INSN_P (BB_END (src_bb))); - emit_insn_after (mode_set, BB_END (src_bb)); + gcc_assert (NONJUMP_INSN_P (last)); + /* We cannot insert instructions after the insn + having a REG_EH_REGION note. */ + if (find_reg_note (last, REG_EH_REGION, NULL_RTX)) + { + gcc_assert ((MODE_NEEDED (entity_map[j], last) + == no_mode) + || (MODE_NEEDED (entity_map[j], last) + == mode)); + emit_insn_before (mode_set, last); + } + else + emit_insn_after (mode_set, last); } bb_info[j][src_bb->index].computing = mode; RESET_BIT (transp[src_bb->index], j); -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=28764