This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR optimization/9888 (part #1)
- From: Eric Botcazou <ebotcazou at libertysurf dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 6 Mar 2003 09:40:54 +0100
- Subject: [PATCH] Fix PR optimization/9888 (part #1)
Hi,
GCC emits out of range 'loop' instructions on the 3.2 branch for the K6
family of processors. This is no breaking news since the insn length
counting machinery has been severely broken for x86 on that branch since the
following patch:
Tue Jun 6 16:57:30 CEST 2000 Jan Hubicka <jh at suse dot cz>
* genattrtab.c (write_attr_value): Do not abort for CONST_INT operands.
* i386.c (ix86_attr_length_default): Kill.
(ix86_attr_length_immediate_default, ix86_attr_length_address_default):
New.
* i386-protos.h (ix86_attr_length_default): Kill
(ix86_attr_length_immediate_default, ix86_attr_length_address_default):
Add prototype
* i386.md (attribute type): Add "test".
(attribute length_prefix): Kill.
(attribute length_opcode): Kill.
(attribute i387, mode, length_immediate, length_address, prefix_data16,
prefix_rep, prefix_0f, modrm): New.
(attribute length): Compute using the new attributes.
(attribute pent_prefix): New.
(attribute pent_pair): Compute using pent_prefix.
(all insn patterns): Set mode,modrm and immediate_length attributes where
needed.
(cmpsi patterns): Compute sizes propertly for test instruction.
(movsi, movhi patterns): Compute sizes propertly for eax shortcuts.
(movstricthi_xor, movstrictqi_xor): New patterns.
(andsi/andhi): Use splitters to generate xor instructions.
(xorqi_ext_1): New pattern.
(movstricthi->movstricthi_xor peep2): New
I think the complete fix will take at least three patches (the next 2 patches
will apply to mainline and 3.3 branch too) but I'd like to start by
backporting one of my patches (present on mainline and 3.3 branch) that
fixes the most obvious mistakes of the patch above, see:
http://gcc.gnu.org/ml/gcc-patches/2002-06/msg02173.html
Bootstrapped/regtested on k6-redhat-linux-gnu (c,c++,objc,f77). Ok for the
3.2 branch?
As mentioned in the message from 2002, the patch fixes two testsuite failures
FAIL: gcc.c-torture/execute/dbra-1.c execution, -O3 -fomit-frame-pointer
FAIL: gcc.c-torture/execute/dbra-1.c execution, -O3 -g
on k6-redhat-linux-gnu but, since GCC is not bootstrapped very often nowadays
on K6, I'd like the test to be run on all x86 processors so I made a gcc.dg
test modeled on it. Ok everywhere?
--
Eric Botcazou
2003-03-06 Eric Botcazou <ebotcazou at libertysurf dot fr>
PR optimization/9888
Backport patch from mainline:
2002-07-03 Eric Botcazou <ebotcazou at multimania dot com>
Jeff Law <law at redhat dot com>
* i386.md (length_immediate attribute): Fix typo.
(length_address attribute): Likewise.
(modrm attribute): Set it to 0 for immediate call instructions.
(jcc_1 pattern): Set modrm attribute to 0.
(jcc_2 pattern ): Likewise.
(jump pattern): Likewise.
(doloop_end_internal pattern): Explicitly set length.
(leave pattern): Fix typo.
(leave_rex64 pattern): Likewise.
2003-03-06 Eric Botcazou <ebotcazou at libertysurf dot fr>
*gcc.dg/i386-loop-1.c: New test.
Index: config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.339.2.13.2.2
diff -u -r1.339.2.13.2.2 i386.md
--- config/i386/i386.md 24 Oct 2002 17:11:54 -0000 1.339.2.13.2.2
+++ config/i386/i386.md 15 Feb 2003 15:43:52 -0000
@@ -131,7 +131,7 @@
;; The (bounding maximum) length of an instruction immediate.
(define_attr "length_immediate" ""
- (cond [(eq_attr "type" "incdec,setcc,icmov,ibr,str,cld,lea,other,multi,idiv,sse,mmx")
+ (cond [(eq_attr "type" "incdec,setcc,icmov,str,cld,lea,other,multi,idiv,sse,mmx")
(const_int 0)
(eq_attr "i387" "1")
(const_int 0)
@@ -162,7 +162,7 @@
(cond [(eq_attr "type" "str,cld,other,multi,fxch")
(const_int 0)
(and (eq_attr "type" "call")
- (match_operand 1 "constant_call_address_operand" ""))
+ (match_operand 0 "constant_call_address_operand" ""))
(const_int 0)
(and (eq_attr "type" "callv")
(match_operand 1 "constant_call_address_operand" ""))
@@ -205,6 +205,12 @@
(and (match_operand 0 "register_operand" "")
(match_operand 1 "immediate_operand" "")))
(const_int 0)
+ (and (eq_attr "type" "call")
+ (match_operand 0 "constant_call_address_operand" ""))
+ (const_int 0)
+ (and (eq_attr "type" "callv")
+ (match_operand 1 "constant_call_address_operand" ""))
+ (const_int 0)
]
(const_int 1)))
@@ -12961,6 +12967,7 @@
""
"%+j%C1\t%l0"
[(set_attr "type" "ibr")
+ (set_attr "modrm" "0")
(set (attr "prefix_0f")
(if_then_else (and (ge (minus (match_dup 0) (pc))
(const_int -128))
@@ -12978,6 +12985,7 @@
""
"%+j%c1\t%l0"
[(set_attr "type" "ibr")
+ (set_attr "modrm" "0")
(set (attr "prefix_0f")
(if_then_else (and (ge (minus (match_dup 0) (pc))
(const_int -128))
@@ -13244,7 +13252,8 @@
(label_ref (match_operand 0 "" "")))]
""
"jmp\t%l0"
- [(set_attr "type" "ibr")])
+ [(set_attr "type" "ibr")
+ (set_attr "modrm" "0")])
(define_expand "indirect_jump"
[(set (pc) (match_operand 0 "nonimmediate_operand" "rm"))]
@@ -13357,6 +13366,14 @@
return "dec{l}\t%1\;%+jne\t%l0";
}
[(set_attr "ppro_uops" "many")
+ (set (attr "length")
+ (if_then_else (and (eq_attr "alternative" "0")
+ (and (ge (minus (match_dup 0) (pc))
+ (const_int -128))
+ (lt (minus (match_dup 0) (pc))
+ (const_int 124))))
+ (const_int 2)
+ (const_int 16)))
(set (attr "type")
(if_then_else (and (eq_attr "alternative" "0")
(and (ge (minus (match_dup 0) (pc))
@@ -13879,7 +13896,6 @@
[(set_attr "length_immediate" "0")
(set_attr "length" "1")
(set_attr "modrm" "0")
- (set_attr "modrm" "0")
(set_attr "athlon_decode" "vector")
(set_attr "ppro_uops" "few")])
@@ -13891,7 +13907,6 @@
"leave"
[(set_attr "length_immediate" "0")
(set_attr "length" "1")
- (set_attr "modrm" "0")
(set_attr "modrm" "0")
(set_attr "athlon_decode" "vector")
(set_attr "ppro_uops" "few")])
/* PR optimization/9888 */
/* { dg-do run { target i?86-*-* } } */
/* { dg-options "-mcpu=k6 -O3" } */
/* Verify that GCC doesn't emit out of range 'loop' instructions. */
extern void abort (void);
extern void exit (int);
f1 (a)
long a;
{
int i;
for (i = 0; i < 10; i++)
{
if (--a == -1)
return i;
}
return -1;
}
f2 (a)
long a;
{
int i;
for (i = 0; i < 10; i++)
{
if (--a != -1)
return i;
}
return -1;
}
f3 (a)
long a;
{
int i;
for (i = 0; i < 10; i++)
{
if (--a == 0)
return i;
}
return -1;
}
f4 (a)
long a;
{
int i;
for (i = 0; i < 10; i++)
{
if (--a != 0)
return i;
}
return -1;
}
f5 (a)
long a;
{
int i;
for (i = 0; i < 10; i++)
{
if (++a == 0)
return i;
}
return -1;
}
f6 (a)
long a;
{
int i;
for (i = 0; i < 10; i++)
{
if (++a != 0)
return i;
}
return -1;
}
int main()
{
if (f1 (5L) != 5)
abort ();
if (f2 (1L) != 0)
abort ();
if (f2 (0L) != 1)
abort ();
if (f3 (5L) != 4)
abort ();
if (f4 (1L) != 1)
abort ();
if (f4 (0L) != 0)
abort ();
if (f5 (-5L) != 4)
abort ();
if (f6 (-1L) != 1)
abort ();
if (f6 (0L) != 0)
abort ();
exit (0);
}