This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [lno] loop-optimize2 ICE


Hello,

> > Got a loop-optimize2 ICE on SPEC's bzip2:
> > 
> > ========
> > gcc -c -o bzip2.o -O3 -floop-optimize2 bzip2.c
> > 
> > GNU C version 3.5-tree-ssa-lno 20040225 (merged 20040221)
> > (powerpc-apple-darwin7.0.0)
> >         compiled by GNU C version 3.5-tree-ssa-lno 20040225 (merged
> > 20040221).
> > bzip2.c: In function `undoReversibleTransformation_small':
> > bzip2.c:2585: internal compiler error: in trunc_int_for_mode, at
> > explow.c:54
> > ========
> > 
> > Below is the smallest test case I came up with ("ttt.c"), and some more
> > details.
> > 
> > The same problem comes up in gap (aggroup.c), crafty (iterate.c) and gcc
> > (function.c).
> 
> sorry for this; I noticed this problem already when I merged this to
> mainline, but I forgot to commit the fix also to lno branch.  I will do
> this as soon as possible,

this patch should help.

Zdenek

Index: ChangeLog.lno
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/ChangeLog.lno,v
retrieving revision 1.1.2.63
diff -c -3 -p -r1.1.2.63 ChangeLog.lno
*** ChangeLog.lno	25 Feb 2004 15:10:19 -0000	1.1.2.63
--- ChangeLog.lno	27 Feb 2004 00:41:15 -0000
***************
*** 1,3 ****
--- 1,20 ----
+ 2004-02-27  Zdenek Dvorak  <rakdver@atrey.karlin.mff.cuni.cz>
+ 
+ 	* cfgloopmanip.c (loopify): Fix comment.
+ 	* loop-iv.c (lowpart_byte, lowpart_subreg_p): Removed.
+ 	(lowpart_subreg, simple_reg_p, iv_get_reaching_def, get_biv_step_1,
+ 	iv_analyse_op, iv_analyse, get_iv_value): Use standard subreg
+ 	manipulation functions.
+ 	(simplify_using_assignment): Handle hardregs correctly.
+ 	(canon_condition): Use swap_commutative_operands_p.
+ 	(iv_number_of_iterations): Avoid overflow.
+ 	* loop-unroll.c (unroll_loop_runtime_iterations): Pass additional
+ 	argument to compare_and_jump_seq.
+ 	* loop-unswitch.c (unswitch_loop, may_unswitch_on,
+ 	unswitch_single_loop, compare_and_jump_seq): Handle comparisons of
+ 	ccmode registers.
+ 	* rtl.h (compare_and_jump_seq): Declaration changed.
+ 
  2004-02-25  Dorit Naishlos <dorit@il.ibm.com>
  
          * tree-vectorizer.h (assignment_vec_info_type): New enum value for
Index: cfgloopmanip.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgloopmanip.c,v
retrieving revision 1.3.2.11.2.7
diff -c -3 -p -r1.3.2.11.2.7 cfgloopmanip.c
*** cfgloopmanip.c	21 Feb 2004 23:09:31 -0000	1.3.2.11.2.7
--- cfgloopmanip.c	27 Feb 2004 00:41:15 -0000
*************** scale_loop_frequencies (struct loop *loo
*** 480,487 ****
     accordingly. Everything between them plus LATCH_EDGE destination must
     be dominated by HEADER_EDGE destination, and back-reachable from
     LATCH_EDGE source.  HEADER_EDGE is redirected to basic block SWITCH_BB,
!    FALLTHRU_EDGE (SWITCH_BB) to original destination of LATCH_EDGE and
!    BRANCH_EDGE (SWITCH_BB) to original destination of HEADER_EDGE.
     Returns newly created loop.  */
  
  struct loop *
--- 480,487 ----
     accordingly. Everything between them plus LATCH_EDGE destination must
     be dominated by HEADER_EDGE destination, and back-reachable from
     LATCH_EDGE source.  HEADER_EDGE is redirected to basic block SWITCH_BB,
!    FALLTHRU_EDGE (SWITCH_BB) to original destination of HEADER_EDGE and
!    BRANCH_EDGE (SWITCH_BB) to original destination of LATCH_EDGE.
     Returns newly created loop.  */
  
  struct loop *
Index: loop-iv.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/loop-iv.c,v
retrieving revision 1.1.4.5
diff -c -3 -p -r1.1.4.5 loop-iv.c
*** loop-iv.c	8 Feb 2004 23:18:04 -0000	1.1.4.5
--- loop-iv.c	27 Feb 2004 00:41:15 -0000
*************** assign_luids (basic_block bb)
*** 153,189 ****
      }
  }
  
- /* Returns the byte for taking the least significant OUTER_MODE subreg of
-    INNER_MODE.  */
- 
- static unsigned
- lowpart_byte (enum machine_mode outer_mode, enum machine_mode inner_mode)
- {
-   unsigned offset = 0;
- 
-   if (WORDS_BIG_ENDIAN)
-     offset = GET_MODE_SIZE (inner_mode) - GET_MODE_SIZE (outer_mode);
- 
-   if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
-       && GET_MODE_SIZE (outer_mode) < UNITS_PER_WORD)
-     {
-       /* We must swap the positions inside the word.  */
-       offset = (offset + UNITS_PER_WORD - GET_MODE_SIZE (outer_mode)
- 		- 2 * (offset % UNITS_PER_WORD));
-     }
- 
-   return offset;
- }
- 
- /* Checks whether subreg EXPR takes the least significant part of EXPR.  */
- 
- static bool
- lowpart_subreg_p (rtx expr)
- {
-   return SUBREG_BYTE (expr) == lowpart_byte (GET_MODE (expr),
- 					     GET_MODE (SUBREG_REG (expr)));
- }
- 
  /* Generates a subreg to get the least significant part of EXPR (in mode
     INNER_MODE) to OUTER_MODE.  */
  
--- 153,158 ----
*************** lowpart_subreg (enum machine_mode outer_
*** 192,198 ****
  		enum machine_mode inner_mode)
  {
    return simplify_gen_subreg (outer_mode, expr, inner_mode,
! 			      lowpart_byte (outer_mode, inner_mode));
  }
  
  /* Checks whether REG is a well-behaved register.  */
--- 161,167 ----
  		enum machine_mode inner_mode)
  {
    return simplify_gen_subreg (outer_mode, expr, inner_mode,
! 			      subreg_lowpart_offset (outer_mode, inner_mode));
  }
  
  /* Checks whether REG is a well-behaved register.  */
*************** simple_reg_p (rtx reg)
*** 204,210 ****
  
    if (GET_CODE (reg) == SUBREG)
      {
!       if (!lowpart_subreg_p (reg))
  	return false;
        reg = SUBREG_REG (reg);
      }
--- 173,179 ----
  
    if (GET_CODE (reg) == SUBREG)
      {
!       if (!subreg_lowpart_p (reg))
  	return false;
        reg = SUBREG_REG (reg);
      }
*************** mark_single_set (rtx insn, rtx set)
*** 301,307 ****
    return def;
  }
  
! /* Marks set register REG as wrong, unless it is equal to EXCEPT.  */
  
  static void
  kill_sets (rtx reg, rtx by ATTRIBUTE_UNUSED, void *except)
--- 270,276 ----
    return def;
  }
  
! /* Invalidate register REG unless it is equal to EXCEPT.  */
  
  static void
  kill_sets (rtx reg, rtx by ATTRIBUTE_UNUSED, void *except)
*************** iv_get_reaching_def (rtx insn, rtx reg)
*** 391,397 ****
  
    if (GET_CODE (reg) == SUBREG)
      {
!       if (!lowpart_subreg_p (reg))
  	return const0_rtx;
        reg = SUBREG_REG (reg);
      }
--- 360,366 ----
  
    if (GET_CODE (reg) == SUBREG)
      {
!       if (!subreg_lowpart_p (reg))
  	return const0_rtx;
        reg = SUBREG_REG (reg);
      }
*************** get_biv_step_1 (rtx insn, rtx reg,
*** 697,703 ****
  
    if (GET_CODE (next) == SUBREG)
      {
!       if (!lowpart_subreg_p (next))
  	return false;
  
        nextr = SUBREG_REG (next);
--- 666,672 ----
  
    if (GET_CODE (next) == SUBREG)
      {
!       if (!subreg_lowpart_p (next))
  	return false;
  
        nextr = SUBREG_REG (next);
*************** iv_analyse_op (rtx insn, rtx op, struct 
*** 912,918 ****
  
    if (GET_CODE (op) == SUBREG)
      {
!       if (!lowpart_subreg_p (op))
  	return false;
  
        if (!iv_analyse_op (insn, SUBREG_REG (op), iv))
--- 881,887 ----
  
    if (GET_CODE (op) == SUBREG)
      {
!       if (!subreg_lowpart_p (op))
  	return false;
  
        if (!iv_analyse_op (insn, SUBREG_REG (op), iv))
*************** iv_analyse (rtx insn, rtx def, struct rt
*** 975,981 ****
  
    if (GET_CODE (def) == SUBREG)
      {
!       if (!lowpart_subreg_p (def))
  	return false;
  
        if (!iv_analyse (insn, SUBREG_REG (def), iv))
--- 944,950 ----
  
    if (GET_CODE (def) == SUBREG)
      {
!       if (!subreg_lowpart_p (def))
  	return false;
  
        if (!iv_analyse (insn, SUBREG_REG (def), iv))
*************** iv_analyse (rtx insn, rtx def, struct rt
*** 1024,1030 ****
        switch (code)
  	{
  	case SUBREG:
! 	  if (!lowpart_subreg_p (rhs))
  	    goto end;
  	  op0 = rhs;
  	  break;
--- 993,999 ----
        switch (code)
  	{
  	case SUBREG:
! 	  if (!subreg_lowpart_p (rhs))
  	    goto end;
  	  op0 = rhs;
  	  break;
*************** get_iv_value (struct rtx_iv *iv, rtx ite
*** 1148,1156 ****
    if (iv->first_special)
      abort ();
  
!   val = simplify_gen_binary (PLUS, iv->extend_mode, iv->base,
! 			     simplify_gen_binary (MULT, iv->extend_mode,
! 						  iv->step, iteration));
  
    if (iv->extend_mode == iv->mode)
      return val;
--- 1117,1128 ----
    if (iv->first_special)
      abort ();
  
!   if (iv->step != const0_rtx && iteration != const0_rtx)
!     val = simplify_gen_binary (PLUS, iv->extend_mode, iv->base,
! 			       simplify_gen_binary (MULT, iv->extend_mode,
! 						    iv->step, iteration));
!   else
!     val = iv->base;
  
    if (iv->extend_mode == iv->mode)
      return val;
*************** simplify_using_assignment (rtx insn, rtx
*** 1351,1356 ****
--- 1323,1337 ----
      ret = true;
  
    note_stores (PATTERN (insn), mark_altered, altered);
+   if (GET_CODE (insn) == CALL_INSN)
+     {
+       int i;
+ 
+       /* Kill all call clobbered registers.  */
+       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ 	if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
+ 	  SET_REGNO_REG_SET (altered, i);
+     }
  
    if (ret)
      return;
*************** implies_p (rtx a, rtx b)
*** 1400,1406 ****
  
  /* Canonicalizes COND so that
  
!    (1) If an operand is a constant, it will be the second operand.
     (2) (LE x const) will be replaced with (LT x <const+1>) and similarly
         for GE, GEU, and LEU.  */
  
--- 1381,1388 ----
  
  /* Canonicalizes COND so that
  
!    (1) Ensure that operands are ordered according to
!        swap_commutative_operands_p.
     (2) (LE x const) will be replaced with (LT x <const+1>) and similarly
         for GE, GEU, and LEU.  */
  
*************** canon_condition (rtx cond)
*** 1410,1422 ****
    rtx tem;
    rtx op0, op1;
    enum rtx_code code;
  
    code = GET_CODE (cond);
    op0 = XEXP (cond, 0);
    op1 = XEXP (cond, 1);
  
!   /* If constant is first, put it last.  */
!   if (CONSTANT_P (op0))
      {
        code = swap_condition (code);
        tem = op0;
--- 1392,1404 ----
    rtx tem;
    rtx op0, op1;
    enum rtx_code code;
+   enum machine_mode mode;
  
    code = GET_CODE (cond);
    op0 = XEXP (cond, 0);
    op1 = XEXP (cond, 1);
  
!   if (swap_commutative_operands_p (op0, op1))
      {
        code = swap_condition (code);
        tem = op0;
*************** canon_condition (rtx cond)
*** 1424,1437 ****
        op1 = tem;
      }
  
    if (GET_CODE (op1) == CONST_INT
!       && GET_MODE (op0) != VOIDmode
!       && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT)
      {
        HOST_WIDE_INT const_val = INTVAL (op1);
        unsigned HOST_WIDE_INT uconst_val = const_val;
        unsigned HOST_WIDE_INT max_val
! 	= (unsigned HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (op0));
  
        switch (code)
  	{
--- 1406,1425 ----
        op1 = tem;
      }
  
+   mode = GET_MODE (op0);
+   if (mode == VOIDmode)
+     mode = GET_MODE (op1);
+   if (mode == VOIDmode)
+     abort ();
+ 
    if (GET_CODE (op1) == CONST_INT
!       && GET_MODE_CLASS (mode) != MODE_CC
!       && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
      {
        HOST_WIDE_INT const_val = INTVAL (op1);
        unsigned HOST_WIDE_INT uconst_val = const_val;
        unsigned HOST_WIDE_INT max_val
! 	= (unsigned HOST_WIDE_INT) GET_MODE_MASK (mode);
  
        switch (code)
  	{
*************** canon_condition (rtx cond)
*** 1446,1462 ****
  	  if ((HOST_WIDE_INT) (const_val & max_val)
  	      != (((HOST_WIDE_INT) 1
  		   << (GET_MODE_BITSIZE (GET_MODE (op0)) - 1))))
! 	    code = GT, op1 = gen_int_mode (const_val - 1, GET_MODE (op0));
  	  break;
  
  	case LEU:
  	  if (uconst_val < max_val)
! 	    code = LTU, op1 = gen_int_mode (uconst_val + 1, GET_MODE (op0));
  	  break;
  
  	case GEU:
  	  if (uconst_val != 0)
! 	    code = GTU, op1 = gen_int_mode (uconst_val - 1, GET_MODE (op0));
  	  break;
  
  	default:
--- 1434,1450 ----
  	  if ((HOST_WIDE_INT) (const_val & max_val)
  	      != (((HOST_WIDE_INT) 1
  		   << (GET_MODE_BITSIZE (GET_MODE (op0)) - 1))))
! 	    code = GT, op1 = gen_int_mode (const_val - 1, mode);
  	  break;
  
  	case LEU:
  	  if (uconst_val < max_val)
! 	    code = LTU, op1 = gen_int_mode (uconst_val + 1, mode);
  	  break;
  
  	case GEU:
  	  if (uconst_val != 0)
! 	    code = GTU, op1 = gen_int_mode (uconst_val - 1, mode);
  	  break;
  
  	default:
*************** iv_number_of_iterations (struct loop *lo
*** 1935,1940 ****
--- 1923,1932 ----
    if (iv1.extend_mode == VOIDmode)
      iv1.mode = iv1.extend_mode = mode;
  
+   if (GET_MODE_BITSIZE (iv0.extend_mode) > HOST_BITS_PER_WIDE_INT
+       || GET_MODE_BITSIZE (iv1.extend_mode) > HOST_BITS_PER_WIDE_INT)
+     goto fail;
+ 
    /* Check condition and normalize it.  */
  
    switch (cond)
*************** iv_number_of_iterations (struct loop *lo
*** 1965,1970 ****
--- 1957,1963 ----
      goto fail;
  
    comp_mode = iv0.extend_mode;
+   mode = iv0.mode;
    size = GET_MODE_BITSIZE (mode);
    get_mode_bounds (mode, (cond == LE || cond == LT), &mmin, &mmax);
  
Index: loop-unroll.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/loop-unroll.c,v
retrieving revision 1.2.2.6.2.3
diff -c -3 -p -r1.2.2.6.2.3 loop-unroll.c
*** loop-unroll.c	10 Feb 2004 20:13:35 -0000	1.2.2.6.2.3
--- loop-unroll.c	27 Feb 2004 00:41:15 -0000
*************** unroll_loop_runtime_iterations (struct l
*** 931,937 ****
  
        preheader = loop_split_edge_with (loop_preheader_edge (loop), NULL_RTX);
        branch_code = compare_and_jump_seq (copy_rtx (niter), GEN_INT (j), EQ,
! 					  block_label (preheader), p);
  
        swtch = loop_split_edge_with (swtch->pred, branch_code);
        set_immediate_dominator (CDI_DOMINATORS, preheader, swtch);
--- 931,937 ----
  
        preheader = loop_split_edge_with (loop_preheader_edge (loop), NULL_RTX);
        branch_code = compare_and_jump_seq (copy_rtx (niter), GEN_INT (j), EQ,
! 					  block_label (preheader), p, NULL_RTX);
  
        swtch = loop_split_edge_with (swtch->pred, branch_code);
        set_immediate_dominator (CDI_DOMINATORS, preheader, swtch);
*************** unroll_loop_runtime_iterations (struct l
*** 948,954 ****
        swtch = ezc_swtch;
        preheader = loop_split_edge_with (loop_preheader_edge (loop), NULL_RTX);
        branch_code = compare_and_jump_seq (copy_rtx (niter), const0_rtx, EQ,
! 					  block_label (preheader), p);
  
        swtch = loop_split_edge_with (swtch->succ, branch_code);
        set_immediate_dominator (CDI_DOMINATORS, preheader, swtch);
--- 948,954 ----
        swtch = ezc_swtch;
        preheader = loop_split_edge_with (loop_preheader_edge (loop), NULL_RTX);
        branch_code = compare_and_jump_seq (copy_rtx (niter), const0_rtx, EQ,
! 					  block_label (preheader), p, NULL_RTX);
  
        swtch = loop_split_edge_with (swtch->succ, branch_code);
        set_immediate_dominator (CDI_DOMINATORS, preheader, swtch);
Index: loop-unswitch.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/loop-unswitch.c,v
retrieving revision 1.2.2.6.2.8
diff -c -3 -p -r1.2.2.6.2.8 loop-unswitch.c
*** loop-unswitch.c	21 Feb 2004 23:09:52 -0000	1.2.2.6.2.8
--- loop-unswitch.c	27 Feb 2004 00:41:15 -0000
*************** Software Foundation, 59 Temple Place - S
*** 79,110 ****
    with handling this case.  */
  
  static struct loop *unswitch_loop (struct loops *, struct loop *,
! 				   basic_block, rtx);
  static void unswitch_single_loop (struct loops *, struct loop *, rtx, int);
! static rtx may_unswitch_on (basic_block, struct loop *);
  
  /* Prepare a sequence comparing OP0 with OP1 using COMP and jumping to LABEL if
!    true, with probability PROB.  */
  
  rtx
! compare_and_jump_seq (rtx op0, rtx op1, enum rtx_code comp, rtx label, int prob)
  {
!   rtx seq, jump;
    enum machine_mode mode;
  
-   start_sequence ();
-   op0 = force_operand (op0, NULL_RTX);
-   op1 = force_operand (op1, NULL_RTX);
    mode = GET_MODE (op0);
    if (mode == VOIDmode)
      mode = GET_MODE (op1);
!   do_compare_rtx_and_jump (op0, op1, comp, 0,
! 			   mode, NULL_RTX, NULL_RTX, label);
!   jump = get_last_insn ();
    REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob),
  					REG_NOTES (jump));
-   JUMP_LABEL (jump) = label;
-   LABEL_NUSES (label)++;
    seq = get_insns ();
    end_sequence ();
  
--- 79,136 ----
    with handling this case.  */
  
  static struct loop *unswitch_loop (struct loops *, struct loop *,
! 				   basic_block, rtx, rtx);
  static void unswitch_single_loop (struct loops *, struct loop *, rtx, int);
! static rtx may_unswitch_on (basic_block, struct loop *, rtx *);
  
  /* Prepare a sequence comparing OP0 with OP1 using COMP and jumping to LABEL if
!    true, with probability PROB.  If CINSN is not NULL, it is the insn to copy
!    in order to create a jump.  */
  
  rtx
! compare_and_jump_seq (rtx op0, rtx op1, enum rtx_code comp, rtx label, int prob,
! 		      rtx cinsn)
  {
!   rtx seq, jump, cond;
    enum machine_mode mode;
  
    mode = GET_MODE (op0);
    if (mode == VOIDmode)
      mode = GET_MODE (op1);
! 
!   start_sequence ();
!   if (GET_MODE_CLASS (mode) == MODE_CC)
!     {
!       /* A hack -- there seems to be no easy generic way how to make a
! 	 conditional jump from a ccmode comparison.  */
!       if (!cinsn)
! 	abort ();
!       cond = XEXP (SET_SRC (pc_set (cinsn)), 0);
!       if (GET_CODE (cond) != comp
! 	  || !rtx_equal_p (op0, XEXP (cond, 0))
! 	  || !rtx_equal_p (op1, XEXP (cond, 1)))
! 	abort ();
!       emit_jump_insn (copy_insn (PATTERN (cinsn)));
!       jump = get_last_insn ();
!       JUMP_LABEL (jump) = JUMP_LABEL (cinsn);
!       LABEL_NUSES (JUMP_LABEL (jump))++;
!       redirect_jump (jump, label, 0);
!     }
!   else
!     {
!       if (cinsn)
! 	abort ();
! 
!       op0 = force_operand (op0, NULL_RTX);
!       op1 = force_operand (op1, NULL_RTX);
!       do_compare_rtx_and_jump (op0, op1, comp, 0,
! 			       mode, NULL_RTX, NULL_RTX, label);
!       jump = get_last_insn ();
!       JUMP_LABEL (jump) = label;
!       LABEL_NUSES (label)++;
!     }
    REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob),
  					REG_NOTES (jump));
    seq = get_insns ();
    end_sequence ();
  
*************** unswitch_loops (struct loops *loops)
*** 142,155 ****
  }
  
  /* Checks whether we can unswitch LOOP on condition at end of BB -- one of its
!    basic blocks (for what it means see comments below).  */
  
  static rtx
! may_unswitch_on (basic_block bb, struct loop *loop)
  {
    rtx test, at, insn, op[2];
    struct rtx_iv iv;
    unsigned i;
  
    /* BB must end in a simple conditional jump.  */
    if (!bb->succ || !bb->succ->succ_next || bb->succ->succ_next->succ_next)
--- 168,183 ----
  }
  
  /* Checks whether we can unswitch LOOP on condition at end of BB -- one of its
!    basic blocks (for what it means see comments below).  In case condition
!    compares loop invariant cc mode register, return the jump in CINSN.  */
  
  static rtx
! may_unswitch_on (basic_block bb, struct loop *loop, rtx *cinsn)
  {
    rtx test, at, insn, op[2];
    struct rtx_iv iv;
    unsigned i;
+   enum machine_mode mode;
  
    /* BB must end in a simple conditional jump.  */
    if (!bb->succ || !bb->succ->succ_next || bb->succ->succ_next->succ_next)
*************** may_unswitch_on (basic_block bb, struct 
*** 189,194 ****
--- 217,238 ----
        op[i] = get_iv_value (&iv, const0_rtx);
      }
  
+   mode = GET_MODE (op[0]);
+   if (mode == VOIDmode)
+     mode = GET_MODE (op[1]);
+   if (GET_MODE_CLASS (mode) == MODE_CC)
+     {
+       if (at != BB_END (bb))
+ 	return NULL_RTX;
+ 
+       *cinsn = BB_END (bb);
+       if (!rtx_equal_p (op[0], XEXP (test, 0))
+ 	  || !rtx_equal_p (op[1], XEXP (test, 1)))
+ 	return NULL_RTX;
+ 
+       return test;
+     }
+ 
    return canon_condition (gen_rtx_fmt_ee (GET_CODE (test), SImode,
  					  op[0], op[1]));
  }
*************** unswitch_single_loop (struct loops *loop
*** 218,224 ****
    basic_block *bbs;
    struct loop *nloop;
    unsigned i;
!   rtx cond, rcond, conds, rconds, acond;
    int repeat;
    edge e;
  
--- 262,268 ----
    basic_block *bbs;
    struct loop *nloop;
    unsigned i;
!   rtx cond, rcond, conds, rconds, acond, cinsn = NULL_RTX;
    int repeat;
    edge e;
  
*************** unswitch_single_loop (struct loops *loop
*** 278,284 ****
        bbs = get_loop_body (loop);
        iv_analysis_loop_init (loop);
        for (i = 0; i < loop->num_nodes; i++)
! 	if ((cond = may_unswitch_on (bbs[i], loop)))
  	  break;
  
        if (i == loop->num_nodes)
--- 322,328 ----
        bbs = get_loop_body (loop);
        iv_analysis_loop_init (loop);
        for (i = 0; i < loop->num_nodes; i++)
! 	if ((cond = may_unswitch_on (bbs[i], loop, &cinsn)))
  	  break;
  
        if (i == loop->num_nodes)
*************** unswitch_single_loop (struct loops *loop
*** 324,336 ****
      fprintf (rtl_dump_file, ";; Unswitching loop\n");
  
    /* Unswitch the loop on this condition.  */
!   nloop = unswitch_loop (loops, loop, bbs[i], cond);
    if (!nloop)
!   abort ();
  
    /* Invoke itself on modified loops.  */
!   unswitch_single_loop (loops, nloop, conds, num + 1);
!   unswitch_single_loop (loops, loop, rconds, num + 1);
  
    free_EXPR_LIST_node (conds);
    if (rcond)
--- 368,380 ----
      fprintf (rtl_dump_file, ";; Unswitching loop\n");
  
    /* Unswitch the loop on this condition.  */
!   nloop = unswitch_loop (loops, loop, bbs[i], cond, cinsn);
    if (!nloop)
!     abort ();
  
    /* Invoke itself on modified loops.  */
!   unswitch_single_loop (loops, nloop, rconds, num + 1);
!   unswitch_single_loop (loops, loop, conds, num + 1);
  
    free_EXPR_LIST_node (conds);
    if (rcond)
*************** unswitch_single_loop (struct loops *loop
*** 341,351 ****
     unswitching of innermost loops.  UNSWITCH_ON must be executed in every
     iteration, i.e. it must dominate LOOP latch.  COND is the condition
     determining which loop is entered.  Returns NULL if impossible, new loop
!    otherwise.  The new loop is entered if COND is true.  */
  
  static struct loop *
  unswitch_loop (struct loops *loops, struct loop *loop, basic_block unswitch_on,
! 	       rtx cond)
  {
    edge entry, latch_edge, true_edge, false_edge, e;
    basic_block switch_bb, unswitch_on_alt, src;
--- 385,396 ----
     unswitching of innermost loops.  UNSWITCH_ON must be executed in every
     iteration, i.e. it must dominate LOOP latch.  COND is the condition
     determining which loop is entered.  Returns NULL if impossible, new loop
!    otherwise.  The new loop is entered if COND is true.  If CINSN is not
!    NULL, it is the insn in that COND is compared.  */
  
  static struct loop *
  unswitch_loop (struct loops *loops, struct loop *loop, basic_block unswitch_on,
! 	       rtx cond, rtx cinsn)
  {
    edge entry, latch_edge, true_edge, false_edge, e;
    basic_block switch_bb, unswitch_on_alt, src;
*************** unswitch_loop (struct loops *loops, stru
*** 385,392 ****
  
    /* Record the block with condition we unswitch on.  */
    unswitch_on_alt = unswitch_on->rbi->copy;
!   true_edge = BRANCH_EDGE (unswitch_on);
!   false_edge = FALLTHRU_EDGE (unswitch_on_alt);
    latch_edge = loop->latch->rbi->copy->succ;
  
    /* Create a block with the condition.  */
--- 430,437 ----
  
    /* Record the block with condition we unswitch on.  */
    unswitch_on_alt = unswitch_on->rbi->copy;
!   true_edge = BRANCH_EDGE (unswitch_on_alt);
!   false_edge = FALLTHRU_EDGE (unswitch_on);
    latch_edge = loop->latch->rbi->copy->succ;
  
    /* Create a block with the condition.  */
*************** unswitch_loop (struct loops *loops, stru
*** 394,400 ****
    switch_bb = create_empty_bb (EXIT_BLOCK_PTR->prev_bb);
    seq = compare_and_jump_seq (XEXP (cond, 0), XEXP (cond, 1), GET_CODE (cond),
  			      block_label (true_edge->dest),
! 			      prob);
    emit_insn_after (seq, BB_END (switch_bb));
    e = make_edge (switch_bb, true_edge->dest, 0);
    e->probability = prob;
--- 439,445 ----
    switch_bb = create_empty_bb (EXIT_BLOCK_PTR->prev_bb);
    seq = compare_and_jump_seq (XEXP (cond, 0), XEXP (cond, 1), GET_CODE (cond),
  			      block_label (true_edge->dest),
! 			      prob, cinsn);
    emit_insn_after (seq, BB_END (switch_bb));
    e = make_edge (switch_bb, true_edge->dest, 0);
    e->probability = prob;
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.362.2.30.2.5
diff -c -3 -p -r1.362.2.30.2.5 rtl.h
*** rtl.h	21 Feb 2004 23:09:59 -0000	1.362.2.30.2.5
--- rtl.h	27 Feb 2004 00:41:15 -0000
*************** extern rtx doloop_condition_get (rtx);
*** 2352,2358 ****
  
  /* In loop-unswitch.c  */
  extern rtx reversed_condition (rtx);
! extern rtx compare_and_jump_seq (rtx, rtx, enum rtx_code, rtx, int);
  
  /* In loop-iv.c  */
  extern rtx canon_condition (rtx);
--- 2352,2358 ----
  
  /* In loop-unswitch.c  */
  extern rtx reversed_condition (rtx);
! extern rtx compare_and_jump_seq (rtx, rtx, enum rtx_code, rtx, int, rtx);
  
  /* In loop-iv.c  */
  extern rtx canon_condition (rtx);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]