This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR optimization/9888 (part #4)
- From: Eric Botcazou <ebotcazou at libertysurf dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 10 Mar 2003 17:10:33 +0100
- Subject: [PATCH] Fix PR optimization/9888 (part #4)
Hi,
This is the final part. Currently the condition used to switch between short
and long branches is:
(if_then_else (and (ge (minus (match_dup 0) (pc))
(const_int -128))
(lt (minus (match_dup 0) (pc))
(const_int 124)))
This is wrong because the range (-128 to 127) must be mesured after the PC
has been incremented by the instruction length, which is 2 for the short
branch versions of all variable length instructions. Now the branch
shortening pass does the calculation before incrementing the current
address, so the range must be shifted by 2, that is -126 to 129.
However it is safer to assume that the calculation could be performed after
incrementing the current address too; so taking the intersection of both
ranges provides a good enough solution, that is -126 to 127 or
(if_then_else (and (ge (minus (match_dup 0) (pc))
(const_int -126))
(lt (minus (match_dup 0) (pc))
(const_int 128)))
(The stormy16 port uses this approach too).
Bootstrapped/regtested (c,c++,f77,objc for all 3 active branches) on
k6-redhat-linux-gnu. Also bootstrapped on the 3.2 branch with -g -Os.
Ok for mainline and 3.3? Ok for 3.2?
--
Eric Botcazou
2003-03-10 Eric Botcazou <ebotcazou at libertysurf dot fr>
PR optimization/9888
* config/i386/i386.md (jcc_1): Fix range.
(jcc_2): Likewise.
(jump): LIkewise.
(doloop_end_internal): Likewise.
2003-03-10 Eric Botcazou <ebotcazou at libertysurf dot fr>
* gcc.dg/i386-loop-2.c: New test.
Index: config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.404.2.8
diff -u -r1.404.2.8 i386.md
--- config/i386/i386.md 22 Feb 2003 10:04:12 -0000 1.404.2.8
+++ config/i386/i386.md 9 Mar 2003 23:10:23 -0000
@@ -12840,9 +12828,9 @@
(set_attr "modrm" "0")
(set (attr "length")
(if_then_else (and (ge (minus (match_dup 0) (pc))
- (const_int -128))
+ (const_int -126))
(lt (minus (match_dup 0) (pc))
- (const_int 124)))
+ (const_int 128)))
(const_int 2)
(const_int 6)))])
@@ -12858,9 +12846,9 @@
(set_attr "modrm" "0")
(set (attr "length")
(if_then_else (and (ge (minus (match_dup 0) (pc))
- (const_int -128))
+ (const_int -126))
(lt (minus (match_dup 0) (pc))
- (const_int 124)))
+ (const_int 128)))
(const_int 2)
(const_int 6)))])
@@ -13125,9 +13113,9 @@
[(set_attr "type" "ibr")
(set (attr "length")
(if_then_else (and (ge (minus (match_dup 0) (pc))
- (const_int -128))
+ (const_int -126))
(lt (minus (match_dup 0) (pc))
- (const_int 124)))
+ (const_int 128)))
(const_int 2)
(const_int 5)))
(set_attr "modrm" "0")])
@@ -13251,9 +13239,9 @@
(set (attr "length")
(if_then_else (and (eq_attr "alternative" "0")
(and (ge (minus (match_dup 0) (pc))
- (const_int -128))
+ (const_int -126))
(lt (minus (match_dup 0) (pc))
- (const_int 124))))
+ (const_int 128))))
(const_int 2)
(const_int 16)))
;; We don't know the type before shorten branches. Optimistically expect
/* PR optimization/9888 */
/* Originator: Jim Bray <jb at as220 dot org> */
/* { dg-do run { target i?86-*-* } } */
/* { dg-options "-mcpu=k6 -Os" } */
enum reload_type
{
RELOAD_FOR_INPUT, RELOAD_FOR_OUTPUT, RELOAD_FOR_INSN,
RELOAD_FOR_INPUT_ADDRESS, RELOAD_FOR_INPADDR_ADDRESS,
RELOAD_FOR_OUTPUT_ADDRESS, RELOAD_FOR_OUTADDR_ADDRESS,
RELOAD_FOR_OPERAND_ADDRESS, RELOAD_FOR_OPADDR_ADDR,
RELOAD_OTHER, RELOAD_FOR_OTHER_ADDRESS
};
#define FOO_SIZE 3
/* My results, varying with FOO_SIZE:
30: asm error "value of ..fff77 too large:
3 to 29: ....ff7d...
1 to 2: no error. */
struct reload
{
int foo[FOO_SIZE];
int opnum;
enum reload_type when_needed;
unsigned int optional:1;
unsigned int secondary_p:1;
};
#define N_RELOADS 2
struct reload rld[N_RELOADS];
int n_reloads = N_RELOADS;
int main(void)
{
int i;
enum reload_type operand_type[1];
enum reload_type address_type[1];
int operand_reloadnum[1];
int goal_alternative_matches[1];
for (i = 0; i < n_reloads; i++)
{
if (rld[i].secondary_p
&& rld[i].when_needed == operand_type[rld[i].opnum])
rld[i].when_needed = address_type[rld[i].opnum];
if ((rld[i].when_needed == RELOAD_FOR_INPUT_ADDRESS
|| rld[i].when_needed == RELOAD_FOR_OUTPUT_ADDRESS
|| rld[i].when_needed == RELOAD_FOR_INPADDR_ADDRESS
|| rld[i].when_needed == RELOAD_FOR_OUTADDR_ADDRESS)
&& (operand_reloadnum[rld[i].opnum] < 0
|| rld[operand_reloadnum[rld[i].opnum]].optional))
{
if (rld[i].when_needed == RELOAD_FOR_INPADDR_ADDRESS
|| rld[i].when_needed == RELOAD_FOR_OUTADDR_ADDRESS)
rld[i].when_needed = RELOAD_FOR_OPADDR_ADDR;
else
rld[i].when_needed = RELOAD_FOR_OPERAND_ADDRESS;
}
if ((rld[i].when_needed == RELOAD_FOR_INPUT_ADDRESS
|| rld[i].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
&& operand_reloadnum[rld[i].opnum] >= 0
&& (rld[operand_reloadnum[rld[i].opnum]].when_needed
== RELOAD_OTHER))
rld[i].when_needed = RELOAD_FOR_OTHER_ADDRESS;
if (goal_alternative_matches[rld[i].opnum] >= 0)
rld[i].opnum = goal_alternative_matches[rld[i].opnum];
}
return 0;
}