aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@libertysurf.fr>2003-03-25 11:18:47 +0100
committerEric Botcazou <ebotcazou@gcc.gnu.org>2003-03-25 10:18:47 +0000
commitd2fc77254d4bc5cb5e784cc7823607cc85bc77af (patch)
tree97171a6cb94b5038efefa41b68e3e68b36a5edf5
parent9904e2320fd33d0d02d2582a6cb78cbb9f01bff4 (diff)
downloadgcc-d2fc77254d4bc5cb5e784cc7823607cc85bc77af.zip
gcc-d2fc77254d4bc5cb5e784cc7823607cc85bc77af.tar.gz
gcc-d2fc77254d4bc5cb5e784cc7823607cc85bc77af.tar.bz2
re PR rtl-optimization/8746 (gcc miscompiles Linux kernel ppa driver on x86)
PR optimization/8746 * config/i386/i386.md (and promoting splitters): Disable HImode to SImode promoting when the sign bit matters and is not preserved, or when TARGET_FAST_PREFIX is true. Disable promoting when optimizing for size. From-SVN: r64840
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/i386/i386.md28
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/i386-signbit-1.c28
-rw-r--r--gcc/testsuite/gcc.dg/i386-signbit-2.c28
-rw-r--r--gcc/testsuite/gcc.dg/i386-signbit-3.c32
6 files changed, 119 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7c6d4ee..2d71171 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2003-03-25 Eric Botcazou <ebotcazou@libertysurf.fr>
+
+ PR optimization/8746
+ * config/i386/i386.md (and promoting splitters): Disable HImode to
+ SImode promoting when the sign bit matters and is not preserved, or
+ when TARGET_FAST_PREFIX is true. Disable promoting when optimizing
+ for size.
+
2003-03-24 Kazu Hirata <kazu@cs.umass.edu>
* config/h8300/h8300.md (a peephole2): Extend to support loads
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index ae3957d..78663dc 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -17628,6 +17628,10 @@
operands[2] = gen_lowpart (SImode, operands[2]);
PUT_MODE (operands[3], SImode);")
+; Promote the QImode tests, as i386 has encoding of the AND
+; instruction with 32-bit sign-extended immediate and thus the
+; instruction size is unchanged, except in the %eax case for
+; which it is increased by one byte, hence the ! optimize_size.
(define_split
[(set (reg 17)
(compare (and (match_operand 1 "aligned_operand" "")
@@ -17636,12 +17640,11 @@
(set (match_operand 0 "register_operand" "")
(and (match_dup 1) (match_dup 2)))]
"! TARGET_PARTIAL_REG_STALL && reload_completed
- && ix86_match_ccmode (insn, CCNOmode)
- && (GET_MODE (operands[0]) == HImode
- || (GET_MODE (operands[0]) == QImode
- /* Ensure that the operand will remain sign extended immediate. */
- && INTVAL (operands[2]) >= 0
- && (TARGET_PROMOTE_QImode || optimize_size)))"
+ /* Ensure that the operand will remain sign-extended immediate. */
+ && ix86_match_ccmode (insn, INTVAL (operands[2]) >= 0 ? CCNOmode : CCZmode)
+ && ! optimize_size
+ && ((GET_MODE (operands[0]) == HImode && ! TARGET_FAST_PREFIX)
+ || (GET_MODE (operands[0]) == QImode && TARGET_PROMOTE_QImode))"
[(parallel [(set (reg:CCNO 17)
(compare:CCNO (and:SI (match_dup 1) (match_dup 2))
(const_int 0)))
@@ -17654,17 +17657,20 @@
operands[0] = gen_lowpart (SImode, operands[0]);
operands[1] = gen_lowpart (SImode, operands[1]);")
-; Don't promote the QImode tests, as i386 don't have encoding of
-; the test instruction with 32bit sign extended immediate and thus
-; the code grows.
+; Don't promote the QImode tests, as i386 doesn't have encoding of
+; the TEST instruction with 32-bit sign-extended immediate and thus
+; the instruction size would at least double, which is not what we
+; want even with ! optimize_size.
(define_split
[(set (reg 17)
(compare (and (match_operand:HI 0 "aligned_operand" "")
(match_operand:HI 1 "const_int_operand" ""))
(const_int 0)))]
"! TARGET_PARTIAL_REG_STALL && reload_completed
- && ix86_match_ccmode (insn, CCNOmode)
- && GET_MODE (operands[0]) == HImode"
+ /* Ensure that the operand will remain sign-extended immediate. */
+ && ix86_match_ccmode (insn, INTVAL (operands[1]) >= 0 ? CCNOmode : CCZmode)
+ && ! TARGET_FAST_PREFIX
+ && ! optimize_size"
[(set (reg:CCNO 17)
(compare:CCNO (and:SI (match_dup 0) (match_dup 1))
(const_int 0)))]
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 53a729b..cf70618 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,11 @@
2003-03-25 Eric Botcazou <ebotcazou@libertysurf.fr>
+ * gcc.dg/i386-signbit-1.c: New test.
+ * gcc.dg/i386-signbit-2.c: New test.
+ * gcc.dg/i386-signbit-3.c: New test.
+
+2003-03-25 Eric Botcazou <ebotcazou@libertysurf.fr>
+
* gcc.dg/ultrasp5.c: Fix options.
2003-03-24 Eric Botcazou <ebotcazou@libertysurf.fr>
diff --git a/gcc/testsuite/gcc.dg/i386-signbit-1.c b/gcc/testsuite/gcc.dg/i386-signbit-1.c
new file mode 100644
index 0000000..8b8866e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/i386-signbit-1.c
@@ -0,0 +1,28 @@
+/* PR optimization/8746 */
+/* { dg-do run { target i?86-*-* } } */
+/* { dg-options "-O1 -mtune=i586" } */
+
+extern void abort (void);
+
+unsigned char r0;
+
+int foo(int x)
+{
+ unsigned char r = x&0xf0;
+
+ if (!(r&0x80))
+ {
+ r0 = r;
+ return 0;
+ }
+ else
+ return 1;
+}
+
+int main(void)
+{
+ if (foo(0x80) != 1)
+ abort();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/i386-signbit-2.c b/gcc/testsuite/gcc.dg/i386-signbit-2.c
new file mode 100644
index 0000000..5687d85
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/i386-signbit-2.c
@@ -0,0 +1,28 @@
+/* PR optimization/8746 */
+/* { dg-do run { target i?86-*-* } } */
+/* { dg-options "-O1 -mtune=i586" } */
+
+extern void abort (void);
+
+unsigned short r0;
+
+int foo(int x)
+{
+ unsigned short r = x&0xf000;
+
+ if (!(r&0x8000))
+ {
+ r0 = r;
+ return 0;
+ }
+ else
+ return 1;
+}
+
+int main(void)
+{
+ if (foo(0x8000) != 1)
+ abort();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/i386-signbit-3.c b/gcc/testsuite/gcc.dg/i386-signbit-3.c
new file mode 100644
index 0000000..ae97f21
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/i386-signbit-3.c
@@ -0,0 +1,32 @@
+/* PR optimization/8746 */
+/* { dg-do run { target i?86-*-* } } */
+/* { dg-options "-O1 -mtune=i586" } */
+
+extern void abort (void);
+
+volatile int j;
+
+void f0() { j=0; }
+void f1() { j=1; }
+
+int foo(int x)
+{
+ if ((short int)(x&0x8000) > (short int)0)
+ {
+ f0();
+ return 0;
+ }
+ else
+ {
+ f1();
+ return 1;
+ }
+}
+
+int main(void)
+{
+ if (foo(0x8000) != 1)
+ abort();
+
+ return 0;
+}