From 24c2fde2afab0a8108c03bb40bdd0543ca417155 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 6 Oct 2005 10:06:12 -0700 Subject: [PATCH] re PR target/23706 (ICE in rtl_verify_flow_info_1) PR 23706 * mode-switching.c (optimize_mode_switching): Clear transp bit for block with incomming abnormal edges. * config/sh/sh.c (fpscr_values, emit_fpu_switch): New. (fpscr_set_from_mem): Use them. * config/sh/sh.md (fpu_switch0, fpu_switch1): Remove. (fpscr postinc splitters): Rewrite as peephole2+split. From-SVN: r105045 --- gcc/ChangeLog | 11 +++++++ gcc/config/sh/sh.c | 44 +++++++++++++++++++++++++--- gcc/config/sh/sh.md | 70 ++++++++++++++++---------------------------- gcc/mode-switching.c | 12 ++++++++ 4 files changed, 88 insertions(+), 49 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8b27351604c..c8a51f005b2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2005-10-06 Richard Henderson + + PR 23706 + * mode-switching.c (optimize_mode_switching): Clear transp bit + for block with incomming abnormal edges. + + * config/sh/sh.c (fpscr_values, emit_fpu_switch): New. + (fpscr_set_from_mem): Use them. + * config/sh/sh.md (fpu_switch0, fpu_switch1): Remove. + (fpscr postinc splitters): Rewrite as peephole2+split. + 2005-10-06 David Edelsohn * config/rs6000/rs6000.md (eq): Add !TARGET_POWER. diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index c90185abd23..f1ac27c617d 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -7854,6 +7854,44 @@ get_fpscr_rtx (void) return fpscr_rtx; } +static GTY(()) tree fpscr_values; + +static void +emit_fpu_switch (rtx scratch, int index) +{ + rtx dst, src; + + if (fpscr_values == NULL) + { + tree t; + + t = build_index_type (integer_one_node); + t = build_array_type (integer_type_node, t); + t = build_decl (VAR_DECL, get_identifier ("__fpscr_values"), t); + DECL_ARTIFICIAL (t) = 1; + DECL_IGNORED_P (t) = 1; + DECL_EXTERNAL (t) = 1; + TREE_STATIC (t) = 1; + TREE_USED (t) = 1; + + fpscr_values = t; + } + + src = DECL_RTL (fpscr_values); + if (no_new_pseudos) + { + emit_move_insn (scratch, XEXP (src, 0)); + if (index != 0) + emit_insn (gen_addsi3 (scratch, scratch, GEN_INT (index * 4))); + src = adjust_automodify_address (src, PSImode, scratch, index * 4); + } + else + src = adjust_address (src, PSImode, index * 4); + + dst = get_fpscr_rtx (); + emit_move_insn (dst, src); +} + void emit_sf_insn (rtx pat) { @@ -8006,12 +8044,10 @@ void fpscr_set_from_mem (int mode, HARD_REG_SET regs_live) { enum attr_fp_mode fp_mode = mode; + enum attr_fp_mode norm_mode = ACTUAL_NORMAL_MODE (FP_MODE); rtx addr_reg = get_free_reg (regs_live); - if (fp_mode == (enum attr_fp_mode) ACTUAL_NORMAL_MODE (FP_MODE)) - emit_insn (gen_fpu_switch1 (addr_reg)); - else - emit_insn (gen_fpu_switch0 (addr_reg)); + emit_fpu_switch (addr_reg, fp_mode == norm_mode); } /* Is the given character a logical line separator for the assembler? */ diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index d0ce5963c83..42e05bce806 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -9760,34 +9760,6 @@ mov.l\\t1f,r0\\n\\ ;; ??? All patterns should have a type attribute. -(define_expand "fpu_switch0" - [(set (match_operand:SI 0 "" "") (match_dup 2)) - (set (match_dup 1) (mem:PSI (match_dup 0)))] - "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" - " -{ - operands[1] = get_fpscr_rtx (); - operands[2] = gen_rtx_SYMBOL_REF (SImode, \"__fpscr_values\"); - if (flag_pic) - operands[2] = legitimize_pic_address (operands[2], SImode, - no_new_pseudos ? operands[0] : 0); -}") - -(define_expand "fpu_switch1" - [(set (match_operand:SI 0 "" "") (match_dup 2)) - (set (match_dup 3) (plus:SI (match_dup 0) (const_int 4))) - (set (match_dup 1) (mem:PSI (match_dup 3)))] - "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" - " -{ - operands[1] = get_fpscr_rtx (); - operands[2] = gen_rtx_SYMBOL_REF (SImode, \"__fpscr_values\"); - if (flag_pic) - operands[2] = legitimize_pic_address (operands[2], SImode, - no_new_pseudos ? operands[0] : 0); - operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (SImode); -}") - (define_expand "movpsi" [(set (match_operand:PSI 0 "register_operand" "") (match_operand:PSI 1 "general_movsrc_operand" ""))] @@ -9822,35 +9794,43 @@ mov.l\\t1f,r0\\n\\ [(set_attr "length" "0,2,2,4,2,2,2,2,2") (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,store")]) -(define_split +(define_peephole2 [(set (reg:PSI FPSCR_REG) (mem:PSI (match_operand:SI 0 "register_operand" "")))] - "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))" - [(set (match_dup 0) (match_dup 0))] - " + "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])" + [(const_int 0)] { - rtx mem, insn; + rtx fpscr, mem, new_insn; + fpscr = SET_DEST (PATTERN (curr_insn)); mem = SET_SRC (PATTERN (curr_insn)); - mem = change_address (mem, PSImode, gen_rtx_POST_INC (Pmode, operands[0])); - insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (), mem)); - REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX); -}") + mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0])); + + new_insn = emit_insn (gen_fpu_switch (fpscr, mem)); + REG_NOTES (new_insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX); + DONE; +}) (define_split [(set (reg:PSI FPSCR_REG) (mem:PSI (match_operand:SI 0 "register_operand" "")))] - "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" - [(set (match_dup 0) (plus:SI (match_dup 0) (const_int -4)))] - " + "(TARGET_SH4 || TARGET_SH2A_DOUBLE) + && (flag_peephole2 ? flow2_completed : reload_completed)" + [(const_int 0)] { - rtx mem, insn; + rtx fpscr, mem, new_insn; + fpscr = SET_DEST (PATTERN (curr_insn)); mem = SET_SRC (PATTERN (curr_insn)); - mem = change_address (mem, PSImode, gen_rtx_POST_INC (Pmode, operands[0])); - insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (), mem)); - REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX); -}") + mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0])); + + new_insn = emit_insn (gen_fpu_switch (fpscr, mem)); + REG_NOTES (new_insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX); + + if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0]))) + emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4))); + DONE; +}) ;; ??? This uses the fp unit, but has no type indicating that. ;; If we did that, this would either give a bogus latency or introduce diff --git a/gcc/mode-switching.c b/gcc/mode-switching.c index a781cb2d743..30ad3a83357 100644 --- a/gcc/mode-switching.c +++ b/gcc/mode-switching.c @@ -456,6 +456,18 @@ optimize_mode_switching (FILE *file) REG_SET_TO_HARD_REG_SET (live_now, bb->il.rtl->global_live_at_start); + + /* Pretend the mode is clobbered across abnormal edges. */ + { + edge_iterator ei; + edge e; + FOR_EACH_EDGE (e, ei, bb->preds) + if (e->flags & EDGE_COMPLEX) + break; + if (e) + RESET_BIT (transp[bb->index], j); + } + for (insn = BB_HEAD (bb); insn != NULL && insn != NEXT_INSN (BB_END (bb)); insn = NEXT_INSN (insn)) -- 2.30.2