aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2005-01-24 09:54:25 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2005-01-24 09:54:25 +0100
commitb77302be88147ea826ab87d7d31e810fa68f4279 (patch)
tree0acef8526681eeb1372d896c1eb2e4f5656de04d /gcc
parent11c56af5905097e03289cdf395db4fb0eb78d61c (diff)
downloadgcc-b77302be88147ea826ab87d7d31e810fa68f4279.zip
gcc-b77302be88147ea826ab87d7d31e810fa68f4279.tar.gz
gcc-b77302be88147ea826ab87d7d31e810fa68f4279.tar.bz2
re PR middle-end/19551 (pure (complex types) function call removed as dead (LAPACK routine claic1.f bug))
* flow.c (propagate_one_insn): Formatting. PR middle-end/19551 * flow.c (libcall_dead_p): Be more conservative if unsure. If there are any instructions between insn and call, see if they are all dead before saying the libcall is dead. * gcc.c-torture/execute/20050121-1.c: New test. * gcc.dg/20050121-2.c: New test. From-SVN: r94145
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/flow.c18
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20050121-1.c63
-rw-r--r--gcc/testsuite/gcc.dg/20050121-2.c67
5 files changed, 159 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 63c1c1c..815f01f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2005-01-24 Jakub Jelinek <jakub@redhat.com>
+
+ * flow.c (propagate_one_insn): Formatting.
+
+ PR middle-end/19551
+ * flow.c (libcall_dead_p): Be more conservative if unsure.
+ If there are any instructions between insn and call, see if they are
+ all dead before saying the libcall is dead.
+
2005-01-24 Uros Bizjak <uros@kss-loka.si>
* config/i386/i386.md (*extendsfdf2_sse): Use "nonimmediate_operand"
diff --git a/gcc/flow.c b/gcc/flow.c
index 36232e9..0aa23c0 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -1581,7 +1581,7 @@ propagate_one_insn (struct propagate_block_info *pbi, rtx insn)
pbi->cc0_live = 0;
if (libcall_is_dead)
- prev = propagate_block_delete_libcall ( insn, note);
+ prev = propagate_block_delete_libcall (insn, note);
else
{
@@ -2284,7 +2284,7 @@ libcall_dead_p (struct propagate_block_info *pbi, rtx note, rtx insn)
{
rtx r = SET_SRC (x);
- if (REG_P (r))
+ if (REG_P (r) || GET_CODE (r) == SUBREG)
{
rtx call = XEXP (note, 0);
rtx call_pat;
@@ -2318,10 +2318,20 @@ libcall_dead_p (struct propagate_block_info *pbi, rtx note, rtx insn)
call_pat = XVECEXP (call_pat, 0, i);
}
- return insn_dead_p (pbi, call_pat, 1, REG_NOTES (call));
+ if (! insn_dead_p (pbi, call_pat, 1, REG_NOTES (call)))
+ return 0;
+
+ while ((insn = PREV_INSN (insn)) != call)
+ {
+ if (! INSN_P (insn))
+ continue;
+ if (! insn_dead_p (pbi, PATTERN (insn), 0, REG_NOTES (insn)))
+ return 0;
+ }
+ return 1;
}
}
- return 1;
+ return 0;
}
/* 1 if register REGNO was alive at a place where `setjmp' was called
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index bb6cc25..b64036b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2005-01-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/19551
+ * gcc.c-torture/execute/20050121-1.c: New test.
+ * gcc.dg/20050121-2.c: New test.
+
2004-01-23 Steven G. Kargl <kargls@comcast.net>
Paul Brook <paul@codesourcery.com>
diff --git a/gcc/testsuite/gcc.c-torture/execute/20050121-1.c b/gcc/testsuite/gcc.c-torture/execute/20050121-1.c
new file mode 100644
index 0000000..9d5dec4
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20050121-1.c
@@ -0,0 +1,63 @@
+/* PR middle-end/19551 */
+
+extern void abort ();
+
+#define T(type, name) \
+__attribute__((pure)) _Complex type \
+foo_##name (int x) \
+{ \
+ _Complex type r; \
+ __real r = x + 1; \
+ __imag r = x - 1; \
+ return r; \
+} \
+ \
+void \
+bar_##name (type *x) \
+{ \
+ *x = __real foo_##name (5); \
+} \
+ \
+void \
+baz_##name (type *x) \
+{ \
+ *x = __imag foo_##name (5); \
+}
+
+typedef long double ldouble_t;
+typedef long long llong;
+
+T (float, float)
+T (double, double)
+T (long double, ldouble_t)
+T (char, char)
+T (short, short)
+T (int, int)
+T (long, long)
+T (long long, llong)
+#undef T
+
+int
+main (void)
+{
+#define T(type, name) \
+ { \
+ type var = 0; \
+ bar_##name (&var); \
+ if (var != 6) \
+ abort (); \
+ var = 0; \
+ baz_##name (&var); \
+ if (var != 4) \
+ abort (); \
+ }
+ T (float, float)
+ T (double, double)
+ T (long double, ldouble_t)
+ T (char, char)
+ T (short, short)
+ T (int, int)
+ T (long, long)
+ T (long long, llong)
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/20050121-2.c b/gcc/testsuite/gcc.dg/20050121-2.c
new file mode 100644
index 0000000..6a6092c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/20050121-2.c
@@ -0,0 +1,67 @@
+/* PR middle-end/19551 */
+/* { dg-options "-O2" } */
+/* { dg-do link } */
+
+extern void abort ();
+
+#define T(type, name) \
+extern __attribute__((pure)) _Complex type \
+foo_c##name (int x); \
+ \
+void \
+bar_c##name (type *x) \
+{ \
+ type f = __real foo_c##name (5); \
+ if (0) *x = f; \
+} \
+ \
+void \
+baz_c##name (type *x) \
+{ \
+ type f = __imag foo_c##name (5); \
+ if (0) *x = f; \
+} \
+ \
+extern __attribute__((pure)) type \
+foo_##name (int x); \
+ \
+void \
+bar_##name (type *x) \
+{ \
+ type f = foo_##name (5); \
+ if (0) *x = f; \
+}
+
+typedef long double ldouble_t;
+typedef long long llong;
+
+T (float, float)
+T (double, double)
+T (long double, ldouble_t)
+T (char, char)
+T (short, short)
+T (int, int)
+T (long, long)
+T (long long, llong)
+#undef T
+
+int
+main (void)
+{
+#define T(type, name) \
+ { \
+ type var = 0; \
+ bar_c##name (&var); \
+ baz_c##name (&var); \
+ bar_##name (&var); \
+ }
+ T (float, float)
+ T (double, double)
+ T (long double, ldouble_t)
+ T (char, char)
+ T (short, short)
+ T (int, int)
+ T (long, long)
+ T (long long, llong)
+ return 0;
+}