aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Sayle <sayle@gcc.gnu.org>2006-01-26 02:48:01 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2006-01-26 02:48:01 +0000
commitd89b36e1a2179df76edf089cc2a11f5f3409cb72 (patch)
tree8f729514e4450856c50071a4d4fd1e43842ed815
parent51302a4168aced438d184aa0dce95c9766aefd97 (diff)
downloadgcc-d89b36e1a2179df76edf089cc2a11f5f3409cb72.zip
gcc-d89b36e1a2179df76edf089cc2a11f5f3409cb72.tar.gz
gcc-d89b36e1a2179df76edf089cc2a11f5f3409cb72.tar.bz2
re PR rtl-optimization/25703 (ACATS cxa4024 failure)
PR rtl-optimization/25703 * combine.c (try_combine): Handle zero_extract and strict_low_part of non-lowpart SUBREGs for constant reg_subword_p set optimization. * gcc.target/i386/20060125-1.c: New test case. * gcc.target/i386/20060125-2.c: New test case. From-SVN: r110242
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/combine.c38
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.target/i386/20060125-1.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/20060125-2.c30
5 files changed, 91 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 370f701..df995ab 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2006-01-25 Roger Sayle <roger@eyesopen.com>
+
+ PR rtl-optimization/25703
+ * combine.c (try_combine): Handle zero_extract and strict_low_part
+ of non-lowpart SUBREGs for constant reg_subword_p set optimization.
+
2006-01-25 Peter Bergner <bergner@vnet.ibm.com>
* global.c: Fix comment typos.
diff --git a/gcc/combine.c b/gcc/combine.c
index 0ec4580..2c90be5 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -1951,40 +1951,38 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
int offset = -1;
int width = 0;
- if (GET_CODE (dest) == STRICT_LOW_PART)
- {
- width = GET_MODE_BITSIZE (GET_MODE (XEXP (dest, 0)));
- offset = 0;
- }
- else if (GET_CODE (dest) == ZERO_EXTRACT)
+ if (GET_CODE (dest) == ZERO_EXTRACT)
{
if (GET_CODE (XEXP (dest, 1)) == CONST_INT
&& GET_CODE (XEXP (dest, 2)) == CONST_INT)
{
width = INTVAL (XEXP (dest, 1));
offset = INTVAL (XEXP (dest, 2));
-
+ dest = XEXP (dest, 0);
if (BITS_BIG_ENDIAN)
- offset = GET_MODE_BITSIZE (GET_MODE (XEXP (dest, 0)))
- - width - offset;
+ offset = GET_MODE_BITSIZE (GET_MODE (dest)) - width - offset;
}
}
- else if (subreg_lowpart_p (dest))
+ else
{
+ if (GET_CODE (dest) == STRICT_LOW_PART)
+ dest = XEXP (dest, 0);
width = GET_MODE_BITSIZE (GET_MODE (dest));
offset = 0;
}
- /* ??? Preserve the original logic to handle setting the high word
- of double-word pseudos, where inner is half the size of outer
- but not the lowpart. This could be generalized by handling
- SUBREG_BYTE, WORDS_BIG_ENDIAN and BYTES_BIG_ENDIAN ourselves.
- Unfortunately this logic is tricky to get right and probably
- not worth the effort. */
- else if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (temp)))
- == 2 * GET_MODE_BITSIZE (GET_MODE (dest)))
+
+ if (offset >= 0)
{
- width = GET_MODE_BITSIZE (GET_MODE (dest));
- offset = width;
+ /* If this is the low part, we're done. */
+ if (subreg_lowpart_p (dest))
+ ;
+ /* Handle the case where inner is twice the size of outer. */
+ else if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (temp)))
+ == 2 * GET_MODE_BITSIZE (GET_MODE (dest)))
+ offset += GET_MODE_BITSIZE (GET_MODE (dest));
+ /* Otherwise give up for now. */
+ else
+ offset = -1;
}
if (offset >= 0)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 28d3297..075def5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2006-01-25 Jan Hubicka <jh@suse.cz>
+ Roger Sayle <roger@eyesopen.com>
+
+ PR rtl-optimization/25703
+ * gcc.target/i386/20060125-1.c: New test case.
+ * gcc.target/i386/20060125-2.c: New test case.
+
2006-01-25 Tobias Schlüter <tobias.schlueter@physik.uni-muenchen.de>
PR fortran/18540
diff --git a/gcc/testsuite/gcc.target/i386/20060125-1.c b/gcc/testsuite/gcc.target/i386/20060125-1.c
new file mode 100644
index 0000000..cbb4e65
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/20060125-1.c
@@ -0,0 +1,30 @@
+/* PR rtl-optimization/25703 */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-options "-O2 -mtune=i486" } */
+
+extern void abort (void);
+
+struct a
+{
+ int a;
+ char b,c,d,e;
+};
+
+__attribute__ ((noinline))
+__attribute__ ((regparm(1))) t(struct a a)
+{
+ if (a.a!=1 || a.b!=1 || a.c!=1)
+ abort();
+}
+
+int main()
+{
+ struct a a;
+ a.c=1;
+ a.a=1;
+ a.b=1;
+ t(a);
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/20060125-2.c b/gcc/testsuite/gcc.target/i386/20060125-2.c
new file mode 100644
index 0000000..7964ca1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/20060125-2.c
@@ -0,0 +1,30 @@
+/* PR rtl-optimization/25703 */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-options "-O2 -mtune=pentiumpro" } */
+
+extern void abort (void);
+
+struct a
+{
+ int a;
+ char b,c,d,e;
+};
+
+__attribute__ ((noinline))
+__attribute__ ((regparm(1))) t(struct a a)
+{
+ if (a.a!=1 || a.b!=1 || a.c!=1)
+ abort();
+}
+
+int main()
+{
+ struct a a;
+ a.c=1;
+ a.a=1;
+ a.b=1;
+ t(a);
+ return 0;
+}
+