[RFC? PATCH]: Fix PR rtl-optimization/26449, ICE in loop invariant motion

Zdenek Dvorak rakdver@kam.mff.cuni.cz
Mon Sep 17 15:17:00 GMT 2007


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
>       {



More information about the Gcc-patches mailing list