This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
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);