summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2002-09-27 21:39:11 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2002-09-27 21:39:11 +0000
commitd2b033bbe3dfc420c052e10519c60be50f56a779 (patch)
tree915e4fd9c2d5575df891eb9167257b3854256772 /gcc
parentd2c38221df05656977231152a91b0957b86ba86c (diff)
downloadgcc-d2b033bbe3dfc420c052e10519c60be50f56a779.tar.gz
PR optimization/7520
* cfganal.c (flow_active_insn_p): New. (forwarder_block_p): Use it. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@57593 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/cfganal.c28
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20020927-1.c26
3 files changed, 58 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 30a220d8f21..ebf0d324635 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,11 @@
2002-09-27 Richard Henderson <rth@redhat.com>
+ PR optimization/7520
+ * cfganal.c (flow_active_insn_p): New.
+ (forwarder_block_p): Use it.
+
+2002-09-27 Richard Henderson <rth@redhat.com>
+
* emit-rtl.c (active_insn_p): Revert last change.
2002-09-27 Jakub Jelinek <jakub@redhat.com>
diff --git a/gcc/cfganal.c b/gcc/cfganal.c
index bc8fff2510b..10c6bcf2922 100644
--- a/gcc/cfganal.c
+++ b/gcc/cfganal.c
@@ -54,7 +54,31 @@ static void flow_dfs_compute_reverse_finish
PARAMS ((depth_first_search_ds));
static void remove_fake_successors PARAMS ((basic_block));
static bool need_fake_edge_p PARAMS ((rtx));
+static bool flow_active_insn_p PARAMS ((rtx));
+/* Like active_insn_p, except keep the return value clobber around
+ even after reload. */
+
+static bool
+flow_active_insn_p (insn)
+ rtx insn;
+{
+ if (active_insn_p (insn))
+ return true;
+
+ /* A clobber of the function return value exists for buggy
+ programs that fail to return a value. It's effect is to
+ keep the return value from being live across the entire
+ function. If we allow it to be skipped, we introduce the
+ possibility for register livetime aborts. */
+ if (GET_CODE (PATTERN (insn)) == CLOBBER
+ && GET_CODE (XEXP (PATTERN (insn), 0)) == REG
+ && REG_FUNCTION_VALUE_P (XEXP (PATTERN (insn), 0)))
+ return true;
+
+ return false;
+}
+
/* Return true if the block has no effect and only forwards control flow to
its single destination. */
@@ -69,12 +93,12 @@ forwarder_block_p (bb)
return false;
for (insn = bb->head; insn != bb->end; insn = NEXT_INSN (insn))
- if (INSN_P (insn) && active_insn_p (insn))
+ if (INSN_P (insn) && flow_active_insn_p (insn))
return false;
return (!INSN_P (insn)
|| (GET_CODE (insn) == JUMP_INSN && simplejump_p (insn))
- || !active_insn_p (insn));
+ || !flow_active_insn_p (insn));
}
/* Return nonzero if we can reach target from src by falling through. */
diff --git a/gcc/testsuite/gcc.c-torture/compile/20020927-1.c b/gcc/testsuite/gcc.c-torture/compile/20020927-1.c
new file mode 100644
index 00000000000..b93d8a18d5e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20020927-1.c
@@ -0,0 +1,26 @@
+/* PR optimization/7520 */
+/* ICE at -O3 on x86 due to register life problems caused by
+ the return-without-value in bar. */
+
+int
+foo ()
+{
+ int i;
+ long long int j;
+
+ while (1)
+ {
+ if (j & 1)
+ ++i;
+ j >>= 1;
+ if (j)
+ return i;
+ }
+}
+
+int
+bar ()
+{
+ if (foo ())
+ return;
+}