Article View: gnu.gcc.bug
Article #6366GCC patch #3
From: buc
Date: Tue, 05 Dec 1995 00:00
Date: Tue, 05 Dec 1995 00:00
167 lines
5273 bytes
5273 bytes
*cse.c (fold_rtx): don`t eliminate regs storing const address
GCC: 2.7.0
(Our configuration:
CPU: mc68030/mc68882
Computer: BESTA (similar to `mot3300 delta')
System: SVR3.1 (similar to sysV68)
asm: SGS System V/68 R2V1 syntax )
We`ve found out a case, when GCC not efficiently chooses
addressing modes for insns.
E.g.,
test #1
****file foo1.c****
extern long *A, *B;
void foo( void ) {
long *a = A, *b = B;
*a++ = *b++;
*a++ = *b++;
*a++ = *b++;
*a++ = *b++;
}
********************
`gcc -S -O2 foo1.c'
result #1
****file foo1.s*****
file "foo1.c"
text
even
global foo
foo:
mov.l A,%a1
mov.l B,%a0
mov.l (%a0)+,(%a1)+
mov.l (%a0)+,(%a1)+
mov.l (%a0)+,(%a1)+
mov.l (%a0),(%a1)
rts
nop
********************
Everything is OK hear, but:
test #2
****file foo2.c****
extern long A[],B[];
void foo( void ) {
long *a = A, *b = B;
*a++ = *b++;
*a++ = *b++;
*a++ = *b++;
*a++ = *b++;
}
********************
`gcc -S -O2 foo2.c'
result #2
****file foo2.s*****
file "kaka2.c"
text
even
global foo
foo:
mov.l B,A
mov.l B+4,A+4
mov.l B+8,A+8
mov.l B+12,A+12
rts
nop
********************
That was a bad code, for instead of the fast two-byte`s insn
`mov.l (%a0+),(%a1)+' the more slow ten-byte`s `mov.l EA1.l EA2.l'
was used.
The code damage takes place after cse compilation phase, when
regs and `a' and `b' variables are eliminated (last example).
I think, many machines have increment, decrement or offset
addressing modes, which in similar cases are executed much more
efficiently than direct memory addressing. So, if a user define variables
(as `a' and `b' in the above example), then let these variables stay
variables. To generate codes similar to the second example, one may use
` A[0] = B[0]; A[1] = B[1]; ... ' etc.
To fix the problem considered, one should patch the file cse.c :
`diff -p -c8' for cse.c:
*** cseOLD.c Wed Nov 29 18:06:17 1995
--- cse.c Wed Nov 29 18:05:16 1995
*************** fold_rtx (x, insn)
*** 5088,5112 ****
--- 5088,5136 ----
rtx cheap_arg, expensive_arg;
rtx replacements[2];
int j;
/* Most arguments are cheap, so handle them specially. */
switch (GET_CODE (arg))
{
case REG:
+
+ /* #if 0 ... #endif :
+ If there are some reasons for it to be a reg, let it be reg.
+
+ One of the reasons:
+ Try on machine, which has postincrement:
+ { extern int A[],B[];
+ int *a = A, *b = B;
+ . . .
+ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; . . .
+ . . .
+ }
+ and compare assembler result with the result of another variant:
+ { extern int *A, *B;
+ int *a = A, *b = B;
+ . . .
+ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; . . .
+ . . .
+ }
+ I want the first result to be the same as the second. */
+ #if 0
+
/* This is the same as calling equiv_constant; it is duplicated
here for speed. */
if (REGNO_QTY_VALID_P (REGNO (arg))
&& qty_const[reg_qty[REGNO (arg)]] != 0
&& GET_CODE (qty_const[reg_qty[REGNO (arg)]]) != REG
&& GET_CODE (qty_const[reg_qty[REGNO (arg)]]) != PLUS)
const_arg
= gen_lowpart_if_possible (GET_MODE (arg),
qty_const[reg_qty[REGNO (arg)]]);
+ #endif /* 0 */
+
break;
case CONST:
case CONST_INT:
case SYMBOL_REF:
case LABEL_REF:
case CONST_DOUBLE:
const_arg = arg;
Probably, hear instead of `#if 0 ' a check of some machine-depended
macro should be used. However, this problem might be a general one.
Dmitry K. Butskoy,
Saint-Petersburg State Technical University,
St. Petersburg, Russia.
<buc@stu.spb.su>
Technical Details
Message-ID:
<AAAd6nmmf3@stu.spb.su>Path:
arc1-ca.pugleaf.net!unknown!not-for-mailShow Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 113d02,fb878d25557e212b,start X-Google-Attributes: gid113d02,public From: buc@stu.spb.SU Subject: GCC patch #3 Date: 1995/12/05 Message-ID: <AAAd6nmmf3@stu.spb.su> X-Deja-AN: 120945680 distribution: gnu sender: daemon@cis.ohio-state.edu organization: State Technical University of St. Petersburg newsgroups: gnu.gcc.bug