This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]