This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR optimization/8746 (x86)


Hi,

This is a kernel miscompilation bug on i586 present on the 3.2 branch only, a 
regression from gcc 2.95.3.

The following insn

(insn 19 62 20 (parallel[ 
            (set (reg:CCGOC 17 flags)
                (compare:CCGOC (and:QI (reg/v:QI 0 al [60])
                        (const_int -16 [0xfffffff0]))
                    (const_int 0 [0x0])))
            (set (reg/v:QI 0 al [60])
                (and:QI (reg/v:QI 0 al [60])
                    (const_int -16 [0xfffffff0])))
        ] ) 300 {*andqi_2} (nil)
    (nil))

is transformed by the split pass into

(insn 19 62 20 (parallel[ 
            (set (reg:CCNO 17 flags)
                (compare:CCNO (and:SI (reg:SI 0 eax [60])
                        (const_int 240 [0xf0]))
                    (const_int 0 [0x0])))
            (set (reg:SI 0 eax [60])
                (and:SI (reg:SI 0 eax [60])
                    (const_int 240 [0xf0])))
        ] ) -1 (insn_list 62 (nil))
    (nil))

which is wrong because the sign bit, considered by both CC modes, is shifted 
from bit 7 to bit 31. And the associated jump insn uses CCGOC mode.

(jump_insn 20 19 54 (set (pc)
        (if_then_else (lt (reg:CCGOC 17 flags)
                (const_int 0 [0x0]))
            (label_ref 35)
            (pc))) 490 {*jcc_1} (insn_list 19 (nil))
    (expr_list:REG_BR_PROB (const_int 5000 [0x1388])
        (nil)))


This was fixed on mainline a while ago by Jan (at one point the bug prevented 
the compiler from bootstrapping on i586) by the following patch:

Thu Jun  6 23:14:46 CEST 2002  Jan Hubicka  <jh at suse dot cz>

	* i386.md (and promoting splitters): Disable QI to SImode promoting
	when doing so changes immediate to be 32bit.

Only the first hunk of the patch is necessary in order to fix the bug, but I 
think the second hunk is low risk.

Bootstrapped/regtested on i586-redhat-linux-gnu (c,c++,objc,f77 3.2 branch).

-- 
Eric Botcazou


2003-03-19  Eric Botcazou  <ebotcazou at libertysurf dot fr>

        PR optimization/8746
	Backport from mainline:

	Thu Jun  6 23:14:46 CEST 2002  Jan Hubicka  <jh at suse dot cz>

	* i386.md (and promoting splitters): Disable QI to SImode promoting
	when doing so changes immediate to be 32bit.


2003-03-18  Eric Botcazou  <ebotcazou at libertysurf dot fr>

        * gcc.dg/20030319-1.c: New test
Index: config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.369
retrieving revision 1.370
diff -u -r1.369 -r1.370
--- config/i386/i386.md	29 May 2002 20:54:00 -0000	1.369
+++ config/i386/i386.md	6 Jun 2002 21:20:43 -0000	1.370
@@ -16358,6 +16358,8 @@
    && 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)))"
   [(parallel [(set (reg:CCNO 17)
 		   (compare:CCNO (and:SI (match_dup 1) (match_dup 2))
@@ -16371,16 +16373,17 @@
    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.
 (define_split
   [(set (reg 17)
-	(compare (and (match_operand 0 "aligned_operand" "")
-		      (match_operand 1 "const_int_operand" ""))
+	(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
-       || (GET_MODE (operands[0]) == QImode 
-	   && (TARGET_PROMOTE_QImode || optimize_size)))"
+   && GET_MODE (operands[0]) == HImode"
   [(set (reg:CCNO 17)
 	(compare:CCNO (and:SI (match_dup 0) (match_dup 1))
 		      (const_int 0)))]
/* PR optimization/8746 */
/* { dg-do run } */
/* { dg-options "-mcpu=i586 -O" { target i?86-*-* } } */

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;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]