This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [RFC? PATCH]: Fix PR rtl-optimization/26449, ICE in loop invariant motion
- From: Zdenek Dvorak <rakdver at kam dot mff dot cuni dot cz>
- To: Uros Bizjak <ubizjak at gmail dot com>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 17 Sep 2007 16:35:10 +0200
- Subject: Re: [RFC? PATCH]: Fix PR rtl-optimization/26449, ICE in loop invariant motion
- References: <46EBB2E5.6060707@gmail.com> <20070915143217.GA5558@kam.mff.cuni.cz>
Hello,
I have bootstrapped & regtested this fix on i686, and I am going to
commit it (the proposed alternative fixes would require changing
force_operand, which might cause further problems elsewhere).
Zdenek
> Index: loop-invariant.c
> ===================================================================
> *** loop-invariant.c (revision 128372)
> --- loop-invariant.c (working copy)
> *************** find_invariants_to_move (void)
> *** 1154,1173 ****
> }
> }
>
> - /* Returns true if all insns in SEQ are valid. */
> -
> - static bool
> - seq_insns_valid_p (rtx seq)
> - {
> - rtx x;
> -
> - for (x = seq; x; x = NEXT_INSN (x))
> - if (insn_invalid_p (x))
> - return false;
> -
> - return true;
> - }
> -
> /* Move invariant INVNO out of the LOOP. Returns true if this succeeds, false
> otherwise. */
>
> --- 1154,1159 ----
> *************** move_invariant_reg (struct loop *loop, u
> *** 1178,1184 ****
> struct invariant *repr = VEC_index (invariant_p, invariants, inv->eqto);
> unsigned i;
> basic_block preheader = loop_preheader_edge (loop)->src;
> ! rtx reg, set, dest, seq, op;
> struct use *use;
> bitmap_iterator bi;
>
> --- 1164,1170 ----
> struct invariant *repr = VEC_index (invariant_p, invariants, inv->eqto);
> unsigned i;
> basic_block preheader = loop_preheader_edge (loop)->src;
> ! rtx reg, set, dest, note;
> struct use *use;
> bitmap_iterator bi;
>
> *************** move_invariant_reg (struct loop *loop, u
> *** 1209,1257 ****
> dest = SET_DEST (set);
> reg = gen_reg_rtx (GET_MODE (dest));
>
> ! /* If the SET_DEST of the invariant insn is a pseudo, we can just move
> ! the insn out of the loop. Otherwise, we have to use gen_move_insn
> ! to let emit_move_insn produce a valid instruction stream. */
> ! if (REG_P (dest) && !HARD_REGISTER_P (dest))
> ! {
> ! rtx note;
>
> ! emit_insn_after (gen_move_insn (dest, reg), inv->insn);
> ! SET_DEST (set) = reg;
> ! df_insn_rescan (inv->insn);
> ! reorder_insns (inv->insn, inv->insn, BB_END (preheader));
> !
> ! /* If there is a REG_EQUAL note on the insn we just moved, and
> ! insn is in a basic block that is not always executed, the note
> ! may no longer be valid after we move the insn.
> ! Note that uses in REG_EQUAL notes are taken into account in
> ! the computation of invariants. Hence it is safe to retain the
> ! note even if the note contains register references. */
> ! if (! inv->always_executed
> ! && (note = find_reg_note (inv->insn, REG_EQUAL, NULL_RTX)))
> ! remove_note (inv->insn, note);
> ! }
> ! else
> ! {
> ! start_sequence ();
> ! op = force_operand (SET_SRC (set), reg);
> ! if (!op)
> ! {
> ! end_sequence ();
> ! goto fail;
> ! }
> ! if (op != reg)
> ! emit_move_insn (reg, op);
> ! seq = get_insns ();
> ! end_sequence ();
> !
> ! if (!seq_insns_valid_p (seq))
> ! goto fail;
> ! emit_insn_after (seq, BB_END (preheader));
> !
> ! emit_insn_after (gen_move_insn (dest, reg), inv->insn);
> ! delete_insn (inv->insn);
> ! }
> }
> else
> {
> --- 1195,1217 ----
> dest = SET_DEST (set);
> reg = gen_reg_rtx (GET_MODE (dest));
>
> ! /* Try replacing the destination by a new pseudoregister. */
> ! if (!validate_change (inv->insn, &SET_DEST (set), reg, false))
> ! goto fail;
> ! df_insn_rescan (inv->insn);
>
> ! emit_insn_after (gen_move_insn (dest, reg), inv->insn);
> ! reorder_insns (inv->insn, inv->insn, BB_END (preheader));
> !
> ! /* If there is a REG_EQUAL note on the insn we just moved, and
> ! insn is in a basic block that is not always executed, the note
> ! may no longer be valid after we move the insn.
> ! Note that uses in REG_EQUAL notes are taken into account in
> ! the computation of invariants. Hence it is safe to retain the
> ! note even if the note contains register references. */
> ! if (! inv->always_executed
> ! && (note = find_reg_note (inv->insn, REG_EQUAL, NULL_RTX)))
> ! remove_note (inv->insn, note);
> }
> else
> {