summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog23
-rw-r--r--gcc/basic-block.h1
-rw-r--r--gcc/cfgrtl.c29
-rw-r--r--gcc/config/arm/thumb2.md3
-rw-r--r--gcc/config/bfin/bfin.md4
-rw-r--r--gcc/config/c6x/c6x.md4
-rw-r--r--gcc/config/ia64/ia64.md3
-rw-r--r--gcc/config/mep/mep.md6
-rw-r--r--gcc/config/rs6000/rs6000.md3
-rw-r--r--gcc/config/s390/s390.md3
-rw-r--r--gcc/config/sh/sh.md5
-rw-r--r--gcc/config/spu/spu.md3
-rw-r--r--gcc/config/tilegx/tilegx.md3
-rw-r--r--gcc/config/tilepro/tilepro.md3
-rw-r--r--gcc/doc/md.texi4
-rw-r--r--gcc/loop-doloop.c17
16 files changed, 88 insertions, 26 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7542474a53e..0b14270ee51 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,26 @@
+2012-10-16 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * loop-doloop.c (doloop_modify): Pass doloop_end pattern to
+ gen_doloop_begin.
+ (doloop_optimize): Pass flag to indicate if loop is entered at top
+ to gen_doloop_end.
+ * config/arm/thumb2.md (doloop_end): Accept extra operand.
+ * config/bfin/bfin.md (doloop_end): Likewise.
+ * config/c6x/c6x.md (doloop_end): Likewise.
+ * config/ia64/ia64.md (doloop_end): Likewise.
+ * config/mep/mep.md (doloop_begin, doloop_end): Likewise.
+ * config/rs6000/rs6000.md (doloop_end): Likewise.
+ * config/s390/s390.md (doloop_end): Likewise.
+ * config/sh/sh.md (doloop_end): Likewise.
+ * config/spu/spu.md (doloop_end): Likewise.
+ * config/tilegx/tilegx.md (doloop_end): Likewise.
+ * config/tilepro/tilepro.md (doloop_end): Likewise.
+ * doc/md.texi (doloop_end): Document new operand.
+ * basic-block.h (contains_no_active_insn_p): Declare.
+ * cfgrtl.c (contains_no_active_insn_p): New function, factored
+ out of ...
+ (forwarder_block_p): ... here.
+
2012-10-16 Manuel López-Ibáñez <manu@gcc.gnu.org>
PR c/53063
diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index 61351fb248d..d9bd3b7e550 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -802,6 +802,7 @@ extern bool purge_all_dead_edges (void);
extern bool purge_dead_edges (basic_block);
extern bool fixup_abnormal_edges (void);
extern basic_block force_nonfallthru_and_redirect (edge, basic_block, rtx);
+extern bool contains_no_active_insn_p (const_basic_block);
extern bool forwarder_block_p (const_basic_block);
extern bool can_fallthru (basic_block, basic_block);
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 1b578d7feeb..b58562fcc5f 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -541,10 +541,9 @@ flow_active_insn_p (const_rtx insn)
/* Return true if the block has no effect and only forwards control flow to
its single destination. */
-/* FIXME: Make this a cfg hook. */
bool
-forwarder_block_p (const_basic_block bb)
+contains_no_active_insn_p (const_basic_block bb)
{
rtx insn;
@@ -552,6 +551,24 @@ forwarder_block_p (const_basic_block bb)
|| !single_succ_p (bb))
return false;
+ for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = NEXT_INSN (insn))
+ if (INSN_P (insn) && flow_active_insn_p (insn))
+ return false;
+
+ return (!INSN_P (insn)
+ || (JUMP_P (insn) && simplejump_p (insn))
+ || !flow_active_insn_p (insn));
+}
+
+/* Likewise, but protect loop latches, headers and preheaders. */
+/* FIXME: Make this a cfg hook. */
+
+bool
+forwarder_block_p (const_basic_block bb)
+{
+ if (!contains_no_active_insn_p (bb))
+ return false;
+
/* Protect loop latches, headers and preheaders. */
if (current_loops)
{
@@ -563,13 +580,7 @@ forwarder_block_p (const_basic_block bb)
return false;
}
- for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = NEXT_INSN (insn))
- if (INSN_P (insn) && flow_active_insn_p (insn))
- return false;
-
- return (!INSN_P (insn)
- || (JUMP_P (insn) && simplejump_p (insn))
- || !flow_active_insn_p (insn));
+ return true;
}
/* Return nonzero if we can reach target from src by falling through. */
diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md
index 57d1539ee3d..a5302f479f5 100644
--- a/gcc/config/arm/thumb2.md
+++ b/gcc/config/arm/thumb2.md
@@ -996,7 +996,8 @@
(use (match_operand 1 "" "")) ; iterations; zero if unknown
(use (match_operand 2 "" "")) ; max iterations
(use (match_operand 3 "" "")) ; loop level
- (use (match_operand 4 "" ""))] ; label
+ (use (match_operand 4 "" "")) ; label
+ (use (match_operand 5 "" ""))] ; flag: 1 if loop entered at top, else 0
"TARGET_32BIT"
"
{
diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md
index 1774d3adff6..63ad1755020 100644
--- a/gcc/config/bfin/bfin.md
+++ b/gcc/config/bfin/bfin.md
@@ -1933,6 +1933,7 @@
; operand 2 is the maximum number of loop iterations
; operand 3 is the number of levels of enclosed loops
; operand 4 is the label to jump to at the top of the loop
+; operand 5 indicates if the loop is entered at the top
(define_expand "doloop_end"
[(parallel [(set (pc) (if_then_else
(ne (match_operand:SI 0 "" "")
@@ -1943,7 +1944,7 @@
(plus:SI (match_dup 0)
(const_int -1)))
(unspec [(const_int 0)] UNSPEC_LSETUP_END)
- (clobber (match_scratch:SI 5 ""))])]
+ (clobber (match_operand 5 ""))])] ; match_scratch
""
{
/* The loop optimizer doesn't check the predicates... */
@@ -1956,6 +1957,7 @@
&& (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 0xFFFFFFFF)
FAIL;
bfin_hardware_loop ();
+ operands[5] = gen_rtx_SCRATCH (SImode);
})
(define_insn "loop_end"
diff --git a/gcc/config/c6x/c6x.md b/gcc/config/c6x/c6x.md
index 99f02d5dc98..e612ef68293 100644
--- a/gcc/config/c6x/c6x.md
+++ b/gcc/config/c6x/c6x.md
@@ -1425,6 +1425,7 @@
; operand 2 is the maximum number of loop iterations
; operand 3 is the number of levels of enclosed loops
; operand 4 is the label to jump to at the top of the loop
+; operand 5 indicates if the loop is entered at the top
(define_expand "doloop_end"
[(parallel [(set (pc) (if_then_else
(ne (match_operand:SI 0 "" "")
@@ -1434,12 +1435,13 @@
(set (match_dup 0)
(plus:SI (match_dup 0)
(const_int -1)))
- (clobber (match_scratch:SI 5 ""))])]
+ (clobber (match_operand 5 ""))])] ; match_scratch
"TARGET_INSNS_64PLUS && optimize"
{
/* The loop optimizer doesn't check the predicates... */
if (GET_MODE (operands[0]) != SImode)
FAIL;
+ operands[5] = gen_rtx_SCRATCH (SImode);
})
(define_insn "mvilc"
diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md
index aa5e78636ea..f84f1ad6332 100644
--- a/gcc/config/ia64/ia64.md
+++ b/gcc/config/ia64/ia64.md
@@ -3960,7 +3960,8 @@
(use (match_operand 1 "" "")) ; iterations; zero if unknown
(use (match_operand 2 "" "")) ; max iterations
(use (match_operand 3 "" "")) ; loop level
- (use (match_operand 4 "" ""))] ; label
+ (use (match_operand 4 "" "")) ; label
+ (use (match_operand 5 "" ""))] ; flag: 1 if loop entered at top, else 0
""
{
/* Only use cloop on innermost loops. */
diff --git a/gcc/config/mep/mep.md b/gcc/config/mep/mep.md
index 773a9a0aa14..35b6e1490bc 100644
--- a/gcc/config/mep/mep.md
+++ b/gcc/config/mep/mep.md
@@ -2079,7 +2079,8 @@
[(use (match_operand 0 "register_operand" ""))
(use (match_operand:QI 1 "const_int_operand" ""))
(use (match_operand:QI 2 "const_int_operand" ""))
- (use (match_operand:QI 3 "const_int_operand" ""))]
+ (use (match_operand:QI 3 "const_int_operand" ""))
+ (use (match_operand 4 "" ""))]
"!profile_arc_flag && TARGET_OPT_REPEAT"
"if (INTVAL (operands[3]) > 1)
FAIL;
@@ -2115,7 +2116,8 @@
(use (match_operand:QI 1 "const_int_operand" ""))
(use (match_operand:QI 2 "const_int_operand" ""))
(use (match_operand:QI 3 "const_int_operand" ""))
- (use (label_ref (match_operand 4 "" "")))]
+ (use (label_ref (match_operand 4 "" "")))
+ (use (match_operand 5 "" ""))]
"!profile_arc_flag && TARGET_OPT_REPEAT"
"if (INTVAL (operands[3]) > 1)
FAIL;
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 96f4f6a8321..5bf2fec18e4 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -13085,7 +13085,8 @@
(use (match_operand 1 "" "")) ; iterations; zero if unknown
(use (match_operand 2 "" "")) ; max iterations
(use (match_operand 3 "" "")) ; loop level
- (use (match_operand 4 "" ""))] ; label
+ (use (match_operand 4 "" "")) ; label
+ (use (match_operand 5 "" ""))] ; flag: 1 if loop entered at top, else 0
""
"
{
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index efe1a470e8d..9279a9876c4 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -8166,7 +8166,8 @@
(use (match_operand 1 "" "")) ; iterations; zero if unknown
(use (match_operand 2 "" "")) ; max iterations
(use (match_operand 3 "" "")) ; loop level
- (use (match_operand 4 "" ""))] ; label
+ (use (match_operand 4 "" "")) ; label
+ (use (match_operand 5 "" ""))] ; flag: 1 if loop entered at top, else 0
""
{
if (GET_MODE (operands[0]) == SImode && !TARGET_CPU_ZARCH)
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 6e6394504f6..2ef4a1a4ee0 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -8474,11 +8474,14 @@ label:
(pc)))
(set (match_dup 0)
(plus:SI (match_dup 0) (const_int -1)))
- (clobber (reg:SI T_REG))])]
+ (clobber (reg:SI T_REG))])
+ (match_operand 5 "" "")]
"TARGET_SH2"
{
if (GET_MODE (operands[0]) != SImode)
FAIL;
+ emit_insn (gen_doloop_end_split (operands[0], operands[4], operands[0]));
+ DONE;
})
(define_insn_and_split "doloop_end_split"
diff --git a/gcc/config/spu/spu.md b/gcc/config/spu/spu.md
index ee5fced6665..3446e986f27 100644
--- a/gcc/config/spu/spu.md
+++ b/gcc/config/spu/spu.md
@@ -4490,7 +4490,8 @@ selb\t%0,%4,%0,%3"
(use (match_operand 1 "" "")) ; iterations; zero if unknown
(use (match_operand 2 "" "")) ; max iterations
(use (match_operand 3 "" "")) ; loop level
- (use (match_operand 4 "" ""))] ; label
+ (use (match_operand 4 "" "")) ; label
+ (match_operand 5 "" "")]
""
"
{
diff --git a/gcc/config/tilegx/tilegx.md b/gcc/config/tilegx/tilegx.md
index 92a6d651eda..b5dc9c8844f 100644
--- a/gcc/config/tilegx/tilegx.md
+++ b/gcc/config/tilegx/tilegx.md
@@ -2316,7 +2316,8 @@
(use (match_operand 1 "" "")) ;; iterations; zero if unknown
(use (match_operand 2 "" "")) ;; max iterations
(use (match_operand 3 "" "")) ;; loop level
- (use (match_operand 4 "" ""))] ;; label
+ (use (match_operand 4 "" "")) ;; label
+ (use (match_operand 5 "" ""))] ;; flag: 1 if loop entered at top, else 0
""
{
if (optimize > 0 && flag_modulo_sched)
diff --git a/gcc/config/tilepro/tilepro.md b/gcc/config/tilepro/tilepro.md
index 9d5d44e85ed..1d1838e6de8 100644
--- a/gcc/config/tilepro/tilepro.md
+++ b/gcc/config/tilepro/tilepro.md
@@ -1322,7 +1322,8 @@
(use (match_operand 1 "" "")) ;; iterations; zero if unknown
(use (match_operand 2 "" "")) ;; max iterations
(use (match_operand 3 "" "")) ;; loop level
- (use (match_operand 4 "" ""))] ;; label
+ (use (match_operand 4 "" "")) ;; label
+ (use (match_operand 5 "" ""))] ;; flag: 1 if loop entered at top, else 0
""
{
if (optimize > 0)
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 6a1db6ad607..32866d5c156 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -5517,7 +5517,9 @@ iterations as a @code{const_int} or @code{const0_rtx} if this cannot be
determined until run-time; operand 2 is the actual or estimated maximum
number of iterations as a @code{const_int}; operand 3 is the number of
enclosed loops as a @code{const_int} (an innermost loop has a value of
-1); operand 4 is the label to jump to if the register is nonzero.
+1); operand 4 is the label to jump to if the register is nonzero;
+operand 5 is const1_rtx if the loop in entered at its top, const0_rtx
+otherwise.
@xref{Looping Patterns}.
This optional instruction pattern should be defined for machines with
diff --git a/gcc/loop-doloop.c b/gcc/loop-doloop.c
index 8dcfea5bba8..9be87c64aea 100644
--- a/gcc/loop-doloop.c
+++ b/gcc/loop-doloop.c
@@ -1,5 +1,5 @@
/* Perform doloop optimizations
- Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010
+ Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010, 2012
Free Software Foundation, Inc.
Based on code by Michael P. Hayes (m.hayes@elec.canterbury.ac.nz)
@@ -561,7 +561,8 @@ doloop_modify (struct loop *loop, struct niter_desc *desc,
init = gen_doloop_begin (counter_reg,
desc->const_iter ? desc->niter_expr : const0_rtx,
iter_rtx,
- GEN_INT (level));
+ GEN_INT (level),
+ doloop_seq);
if (init)
{
start_sequence ();
@@ -619,6 +620,7 @@ doloop_optimize (struct loop *loop)
unsigned word_mode_size;
unsigned HOST_WIDE_INT word_mode_max;
double_int iter;
+ int entered_at_top;
if (dump_file)
fprintf (dump_file, "Doloop: Processing loop %d.\n", loop->num);
@@ -681,8 +683,14 @@ doloop_optimize (struct loop *loop)
not like. */
start_label = block_label (desc->in_edge->dest);
doloop_reg = gen_reg_rtx (mode);
+ entered_at_top = loop_preheader_edge (loop)->dest == desc->in_edge->dest;
+ fprintf (stderr, "entered at top orig: %d\n", entered_at_top);
+ entered_at_top = (loop->latch == desc->in_edge->dest
+ && contains_no_active_insn_p (loop->latch));
+ fprintf (stderr, "entered at top Zdenek: %d\n", entered_at_top);
doloop_seq = gen_doloop_end (doloop_reg, iterations, iterations_max,
- GEN_INT (level), start_label);
+ GEN_INT (level), start_label,
+ GEN_INT (entered_at_top));
word_mode_size = GET_MODE_PRECISION (word_mode);
word_mode_max
@@ -712,7 +720,8 @@ doloop_optimize (struct loop *loop)
}
PUT_MODE (doloop_reg, word_mode);
doloop_seq = gen_doloop_end (doloop_reg, iterations, iterations_max,
- GEN_INT (level), start_label);
+ GEN_INT (level), start_label,
+ GEN_INT (entered_at_top));
}
if (! doloop_seq)
{