This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Overhaul __builtin_constant_p processing
- From: Roger Sayle <roger at www dot eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 20 Jan 2003 07:43:48 -0700 (MST)
- Subject: [PATCH] Overhaul __builtin_constant_p processing
The following patch reorganizes the way that __builtin_constant_p
is handled by GCC. Rather than use CSE's fold-rtx to instantiate
the CONSTANT_P_RTX nodes, we postpone the closure and make use of
a new pass to instantiate them after GCSE and before loop. This
allows GCSE's cprop to propagate constants into __builtin_constant_p.
And thanks to the new "jump bypassing" pass, dead-code in the CFG
will be cleaned up once __builtin_constant_p expressions have been
converted in ones or zeros.
One minor surprise with an early version of this patch, were the
unexpected failures of builtin-constant.c and 20010119-1.c in
gcc.c-torture/execute, but only at -O1. The reason for this is
that at -O1, GCSE isn't run, so although the generated code is
correct, "link_error" style tests fail because the dead-code isn't
eliminated by any pass after loop. The solution below is to
preserve the original semantics and instantiate during CSE if
"flag_gcse" indicates that GCSE/jump bypassing won't get run.
The good news is that apart from -O1 this resolves PR optimization/8423
and the __builtin_constant_p aspects of PR middle-end/3919. On
i686-pc-linux-gnu, I now get four XPASSES of builtin-constant.c
at -O2, -O3 -fomit-frame-pointer, -O3 -g and -Os. We also get a
improved "success mode" for 20010119-1.c:
extern inline void foo (int a, int b)
{
int c = 0;
while (c++ < b)
(__builtin_constant_p (a) ? ((a) > 20000 ? undef() : bar(a)) : baz(a));
}
int main (void)
{
foo(10, 100);
exit (0);
}
This currently passes on GCC mainline because the __builtin_constant_p
in the inlined function foo is determined to be false, and so the loop
calls "baz". With the patch below, __builtin_constant_p is now
considered true at -O2 and higher, so the inlined loop now calls bar!
The following patch has been tested by bootstraping on i686-pc-linux-gnu,
all languages except Ada and treelang, with no new regressions from a
"make -k check", but four new successes for builtin-constant.c.
Ok for mainline?
2003-01-20 Roger Sayle <roger@eyesopen.com>
PR optimization/8423
* cse.c (fold_rtx): Only eliminate a CONSTANT_P_RTX to 1 when
its argument is constant, or 0 if !flag_gcse.
* simplify-rtx.c (simplify_rtx): Convert CONSTANT_P_RTX to 1
if it's argument is constant.
* gcse.c (want_to_gcse_p): Ignore CONSTANT_P_RTX nodes.
(hash_scan_set): Don't record CONSTANT_P_RTX expressions.
* builtins.c (purge_builtin_constant_p): New function to force
instantiation of any remaining CONSTANT_P_RTX nodes.
* rtl.h (purge_builtin_constant_p): Prototype here.
* toplev.c (rest_of_compilation): Invoke purge_builtin_constant_p
pass after GCSE and before loop.
(flag_gcse): No longer static.
* flags.h (flag_gcse): Prototype here.
Index: cse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cse.c,v
retrieving revision 1.245
diff -c -3 -p -r1.245 cse.c
*** cse.c 16 Dec 2002 18:19:19 -0000 1.245
--- cse.c 20 Jan 2003 03:45:03 -0000
***************
*** 1,6 ****
/* Common subexpression elimination for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998
! 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
--- 1,6 ----
/* Common subexpression elimination for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998
! 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
*************** fold_rtx (x, insn)
*** 4332,4340 ****
break;
case 'x':
! /* Always eliminate CONSTANT_P_RTX at this stage. */
if (code == CONSTANT_P_RTX)
! return (const_arg0 ? const1_rtx : const0_rtx);
break;
}
--- 4332,4345 ----
break;
case 'x':
! /* Eliminate CONSTANT_P_RTX if its constant. */
if (code == CONSTANT_P_RTX)
! {
! if (const_arg0)
! return const1_rtx;
! if (!flag_gcse)
! return const0_rtx;
! }
break;
}
Index: simplify-rtx.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/simplify-rtx.c,v
retrieving revision 1.128
diff -c -3 -p -r1.128 simplify-rtx.c
*** simplify-rtx.c 24 Dec 2002 08:30:31 -0000 1.128
--- simplify-rtx.c 20 Jan 2003 03:45:04 -0000
***************
*** 1,6 ****
/* RTL simplification functions for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
! 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
--- 1,6 ----
/* RTL simplification functions for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
! 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
*************** simplify_rtx (x)
*** 2729,2739 ****
: GET_MODE (XEXP (x, 1))),
XEXP (x, 0), XEXP (x, 1));
case 'x':
- /* The only case we try to handle is a SUBREG. */
if (code == SUBREG)
return simplify_gen_subreg (mode, SUBREG_REG (x),
GET_MODE (SUBREG_REG (x)),
SUBREG_BYTE (x));
return NULL;
default:
return NULL;
--- 2729,2743 ----
: GET_MODE (XEXP (x, 1))),
XEXP (x, 0), XEXP (x, 1));
case 'x':
if (code == SUBREG)
return simplify_gen_subreg (mode, SUBREG_REG (x),
GET_MODE (SUBREG_REG (x)),
SUBREG_BYTE (x));
+ if (code == CONSTANT_P_RTX)
+ {
+ if (CONSTANT_P (XEXP (x,0)))
+ return const1_rtx;
+ }
return NULL;
default:
return NULL;
Index: gcse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcse.c,v
retrieving revision 1.227
diff -c -3 -p -r1.227 gcse.c
*** gcse.c 17 Jan 2003 14:24:22 -0000 1.227
--- gcse.c 20 Jan 2003 03:45:05 -0000
*************** want_to_gcse_p (x)
*** 1305,1310 ****
--- 1305,1311 ----
case CONST_DOUBLE:
case CONST_VECTOR:
case CALL:
+ case CONSTANT_P_RTX:
return 0;
default:
*************** hash_scan_set (pat, insn, table)
*** 2216,2222 ****
&& REGNO (src) >= FIRST_PSEUDO_REGISTER
&& can_copy_p [GET_MODE (dest)]
&& REGNO (src) != regno)
! || CONSTANT_P (src))
/* A copy is not available if its src or dest is subsequently
modified. Here we want to search from INSN+1 on, but
oprs_available_p searches from INSN on. */
--- 2217,2224 ----
&& REGNO (src) >= FIRST_PSEUDO_REGISTER
&& can_copy_p [GET_MODE (dest)]
&& REGNO (src) != regno)
! || (CONSTANT_P (src)
! && GET_CODE (src) != CONSTANT_P_RTX))
/* A copy is not available if its src or dest is subsequently
modified. Here we want to search from INSN+1 on, but
oprs_available_p searches from INSN on. */
Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.167
diff -c -3 -p -r1.167 builtins.c
*** builtins.c 15 Jan 2003 17:40:26 -0000 1.167
--- builtins.c 20 Jan 2003 03:45:06 -0000
*************** expand_builtin_constant_p (exp)
*** 1461,1468 ****
arglist = TREE_VALUE (arglist);
/* We have taken care of the easy cases during constant folding. This
! case is not obvious, so emit (constant_p_rtx (ARGLIST)) and let CSE get a
! chance to see if it can deduce whether ARGLIST is constant. */
tmp = expand_expr (arglist, NULL_RTX, VOIDmode, 0);
tmp = gen_rtx_CONSTANT_P_RTX (value_mode, tmp);
--- 1461,1468 ----
arglist = TREE_VALUE (arglist);
/* We have taken care of the easy cases during constant folding. This
! case is not obvious, so emit (constant_p_rtx (ARGLIST)) and let CSE
! get a chance to see if it can deduce whether ARGLIST is constant. */
tmp = expand_expr (arglist, NULL_RTX, VOIDmode, 0);
tmp = gen_rtx_CONSTANT_P_RTX (value_mode, tmp);
*************** default_expand_builtin (exp, target, sub
*** 4496,4498 ****
--- 4496,4527 ----
{
return NULL_RTX;
}
+
+ /* Instantiate all remaining CONSTANT_P_RTX nodes. */
+
+ void
+ purge_builtin_constant_p ()
+ {
+ rtx insn, done, set;
+ rtx arg, new, note;
+ basic_block bb;
+
+ FOR_EACH_BB (bb)
+ {
+ done = NEXT_INSN (bb->end);
+ for (insn = bb->head; insn != done; insn = NEXT_INSN (insn))
+ if (INSN_P (insn)
+ && (set = single_set (insn)) != NULL_RTX
+ && GET_CODE (SET_SRC (set)) == CONSTANT_P_RTX)
+ {
+ arg = XEXP (SET_SRC (set), 0);
+ new = CONSTANT_P (arg) ? const1_rtx : const0_rtx;
+ validate_change (insn, &SET_SRC (set), new, 0);
+
+ /* Remove the REG_EQUAL note from the insn. */
+ if ((note = find_reg_note (insn, REG_EQUAL, NULL_RTX)) != 0)
+ remove_note (insn, note);
+ }
+ }
+ }
+
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.380
diff -c -3 -p -r1.380 rtl.h
*** rtl.h 16 Jan 2003 01:06:32 -0000 1.380
--- rtl.h 20 Jan 2003 03:45:06 -0000
*************** extern int ceil_log2 PARAMS ((unsigned
*** 1346,1351 ****
--- 1346,1352 ----
/* In builtins.c */
extern rtx expand_builtin_expect_jump PARAMS ((tree, rtx, rtx));
+ extern void purge_builtin_constant_p PARAMS ((void));
/* In explow.c */
extern void set_stack_check_libfunc PARAMS ((rtx));
Index: flags.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/flags.h,v
retrieving revision 1.94
diff -c -3 -p -r1.94 flags.h
*** flags.h 17 Jan 2003 14:24:20 -0000 1.94
--- flags.h 20 Jan 2003 03:45:06 -0000
*************** extern enum graph_dump_types graph_dump_
*** 633,638 ****
--- 633,642 ----
extern int flag_no_ident;
+ /* Nonzero means perform global CSE. */
+
+ extern int flag_gcse;
+
/* Nonzero if we want to perform enhanced load motion during gcse. */
extern int flag_gcse_lm;
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.697
diff -c -3 -p -r1.697 toplev.c
*** toplev.c 17 Jan 2003 03:28:09 -0000 1.697
--- toplev.c 20 Jan 2003 03:45:07 -0000
*************** int flag_volatile_static;
*** 621,630 ****
int flag_syntax_only = 0;
- /* Nonzero means perform global cse. */
-
- static int flag_gcse;
-
/* Nonzero means perform loop optimizer. */
static int flag_loop_optimize;
--- 621,626 ----
*************** static int flag_if_conversion2;
*** 646,651 ****
--- 642,651 ----
static int flag_delete_null_pointer_checks;
+ /* Nonzero means perform global CSE. */
+
+ int flag_gcse = 0;
+
/* Nonzero means to do the enhanced load motion during gcse, which trys
to hoist loads by not killing them when a store to the same location
is seen. */
*************** rest_of_compilation (decl)
*** 2920,2925 ****
--- 2920,2928 ----
verify_flow_info ();
#endif
}
+
+ /* Instantiate any remaining CONSTANT_P_RTX nodes. */
+ purge_builtin_constant_p ();
/* Move constant computations out of loops. */
Roger
--
Roger Sayle, E-mail: roger@eyesopen.com
OpenEye Scientific Software, WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road, Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507. Fax: (+1) 505-473-0833