This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
__builtin_constant_p regression
- To: egcs at cygnus dot com
- Subject: __builtin_constant_p regression
- From: Andreas Schwab <schwab at issan dot informatik dot uni-dortmund dot de>
- Date: 28 Dec 1998 10:52:13 +0100
Consider the following example, where the strcpy macro is a greatly
simplyfied copy from the GNU libc:
------------------------------
typedef __SIZE_TYPE__ size_t;
char *strcpy (char *, const char *);
void *memcpy (void *, const void *, size_t);
char one[50], two[50];
#define strcpy(a, b) \
(__builtin_constant_p (b) \
? (strlen (b) < 4 \
? ({ char *__dest = (a); \
switch (strlen (b)) \
{ \
case 3: __dest[3] = (b)[3]; \
case 2: __dest[2] = (b)[2]; \
case 1: __dest[1] = (b)[1]; \
case 0: __dest[0] = (b)[0]; \
} \
__dest; \
}) \
: (char *) memcpy (a, b, strlen (b) + 1)) \
: strcpy (a, b))
int main ()
{
strcpy (one, two);
return 0;
}
------------------------------
When compiled with egcs this generates horrible code:
------------------------------
.file "const.c"
.version "01.01"
gcc2_compiled.:
.text
.align 2
.globl main
.type main,@function
main:
link.w %a6,#0
movm.l #0x2030,-(%sp)
pea two
lea strlen,%a3
jbsr (%a3)
addq.l #4,%sp
moveq.l #3,%d1
cmp.l %d0,%d1
jbcs .L12
lea one,%a2
pea two
jbsr (%a3)
moveq.l #1,%d1
cmp.l %d0,%d1
jbeq .L6
jbhi .L7
moveq.l #2,%d1
cmp.l %d0,%d1
jbeq .L5
moveq.l #3,%d1
cmp.l %d0,%d1
jbne .L11
move.b two+3,3(%a2)
.L5:
move.b two+2,2(%a2)
.L6:
move.b two+1,1(%a2)
.L7:
move.b two,(%a2)
jbra .L11
.align 2
.L12:
move.l #two,%d2
move.l %d2,-(%sp)
jbsr strlen
addq.l #4,%sp
addq.l #1,%d0
move.l %d0,-(%sp)
move.l %d2,-(%sp)
pea one
jbsr memcpy
.L11:
clr.l %d0
movm.l -12(%a6),#0xc04
unlk %a6
rts
.Lfe1:
.size main,.Lfe1-main
.comm one,50,1
.comm two,50,1
.ident "GCC: (GNU) egcs-2.92.32 19981220 (gcc2 ss-980609 experimental)"
------------------------------
This is because egcs erroneously considers the address of a variable as a
compile time constant. But things don't work that way. By contrast, gcc
2.8.1 is doing it right:
------------------------------
.file "const.c"
.version "01.01"
gcc2_compiled.:
.globl memcpy
.text
.align 2
.globl main
.type main,@function
main:
link.w %a6,#0
pea two
pea one
jbsr strcpy
clr.l %d0
unlk %a6
rts
.Lfe1:
.size main,.Lfe1-main
.comm one,50,1
.comm two,50,1
.ident "GCC: (GNU) 2.8.1"
------------------------------
1998-12-27 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
* expr.c (expand_builtin, case BUILT_IN_CONSTANT_P): Return true
only for compile-time constants.
* cse.c (fold_rtx): Check that the argument of CONSTANT_P_RTX is a
compile-time constant.
--- egcs-2.92/gcc/cse.c.~1~ Mon Dec 14 20:33:16 1998
+++ egcs-2.92/gcc/cse.c Mon Dec 14 21:07:41 1998
@@ -5854,7 +5854,12 @@
case 'x':
/* Always eliminate CONSTANT_P_RTX at this stage. */
if (code == CONSTANT_P_RTX)
- return (const_arg0 ? const1_rtx : const0_rtx);
+ return ((const_arg0
+ && (GET_CODE (const_arg0) == CONST_INT
+ || GET_CODE (const_arg0) == CONST_DOUBLE
+ || (GET_CODE (const_arg0) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (const_arg0))))
+ ? const1_rtx : const0_rtx);
break;
}
--- egcs-2.92/gcc/expr.c.~1~ Mon Dec 21 19:16:24 1998
+++ egcs-2.92/gcc/expr.c Mon Dec 21 20:15:10 1998
@@ -9011,8 +9011,12 @@
{
tree arg = TREE_VALUE (arglist);
- STRIP_NOPS (arg);
- if (really_constant_p (arg)
+ /* This is not quite the same as STRIP_NOPS. It does more. */
+ while (TREE_CODE (arg) == NOP_EXPR
+ || TREE_CODE (arg) == CONVERT_EXPR
+ || TREE_CODE (arg) == NON_LVALUE_EXPR)
+ arg = TREE_OPERAND (arg, 0);
+ if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'c'
|| (TREE_CODE (arg) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST))
return const1_rtx;
--
Andreas Schwab "And now for something
schwab@issan.cs.uni-dortmund.de completely different"
schwab@gnu.org