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]

Re: builtin_constant_p


On Thu, Jun 18, 1998 at 03:24:30PM -0700, Jim Wilson wrote:
> 	The reference is 1997-Dec/0485.html.  I'll try applying it to the
> 	current tree and see what happens.
> 
> The patch looks reasonable to me.

The biggest flaw I saw in the patch is that it doesn't care for
side effects of expressions.  So __builtin_constant_p(i++) would
return false, but i would still be incremented.

The following updated patch tries to address this deficiency.
I have not addressed the concerns quoted below for the list's benefit.

> I think we will lose some optimization possibilities if we don't handle
> CONSTANT_P_RTX like other constants.  E.g. it should be accepted by the
> CONSTANT_P macro, and probably many other places that accept constants.
> This might imply modifying some backends to accept CONSTANT_P_RTX in various
> places.  This is probably too much work though.  It depends on what operations
> we want to define as valid for CONSTANT_P_RTX.  If the only thing it is valid
> for is loading into a pseudo, then we don't need to worry about it.  But if
> we want to allow it to be used in addresses, then we need more support for it.

It doesn't seem likely that __builtin_constant_p will be used in addresses.
I see it most often used in

	__builtin_constant_p(x) ? compile_time_expr(x) : run_time_expr(x)

> We might also need to worry about whether various predicates accept
> CONSTANT_P_RTX.  This probably works fine on the x86 because it accepts
> practically any kind of operand anywhere you want it.  This is not true
> of RISC targets though.
> 
> 	Am I correct is assuming that this is similar to ADDRESSOF in that
> 	we effectively want to delay emitting const0_rtx if the expression
> 	is not initially a constant so that optimizers get a chance to
> 	propagate constants, potentially through inline function calls?
> 
> yes.
> 
> 	Seems to me that we could have CSE do the same thing -- ie leave it
> 	alone if its argument is still not a constant, but perform the
> 	replacement if the expression is constant.  Then we have pass that
> 	runs after gcse (or maybe even cse2) which performs the substitution
> 	on any remaining CONSTANT_P_RTX expressions.
> 
> There is a tradeoff on what optimizations can be performed.  It we don't
> reduce CONSTANT_P_RTX to a one/zero until after cse/gcse, then it will be
> impossible for cse/gcse to perform any contant propagation on these values.
> This may result in worse code, if we aren't careful, because stuff that
> should have been optimized away may not be.  For instance, consider branches
> on CONSTANT_P_RTX, which can't be optimized away if we don't know whether
> this is a one or a zero.  Hence we need to do this at least before the last
> run of the jump optimization pass.
> 
> Of course, if we treat CONSTANT_P_RTX exactly as if it is a constant value
> which isn't known yet, then we can still perform constant propagation.
> This implies that CONSTANT_P_RTX will end up in more places that it would
> otherwise, which means we need to look at all RTL when we are getting rid
> of the CONSTANT_P_RTX operations.  This also will probably work only if all
> ports are modified to recognize CONSTANT_P_RTX as constants.
> 
> It looks like we really should do this during cse or during gcse, so that
> we can get constant propagation, and so that the following jump optimize
> pass can eliminate now unnecessary branches.

So given the above expectation, do we still need to modify ports?  Or
is updating CONSTANT_P sufficient?


r~
? m3cg
Index: cse.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cse.c,v
retrieving revision 1.35
diff -u -p -r1.35 cse.c
--- cse.c	1998/06/17 20:20:21	1.35
+++ cse.c	1998/06/23 22:05:00
@@ -5715,6 +5715,12 @@ fold_rtx (x, insn)
 					const_arg1 ? const_arg1 : folded_arg1,
 					const_arg2 ? const_arg2 : XEXP (x, 2));
       break;
+
+    case 'x':
+      /* Always eliminate CONSTANT_P_RTX at this stage. */
+      if (code == CONSTANT_P_RTX)
+	return (const_arg0 ? const1_rtx : const0_rtx);
+      break;
     }
 
   return new ? new : x;
Index: expr.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/expr.c,v
retrieving revision 1.73
diff -u -p -r1.73 expr.c
--- expr.c	1998/06/19 22:06:11	1.73
+++ expr.c	1998/06/23 22:05:24
@@ -8442,10 +8442,18 @@ expand_builtin (exp, target, subtarget, 
 	  tree arg = TREE_VALUE (arglist);
 
 	  STRIP_NOPS (arg);
-	  return (TREE_CODE_CLASS (TREE_CODE (arg)) == 'c'
-		  || (TREE_CODE (arg) == ADDR_EXPR
-		      && TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST)
-		  ? const1_rtx : const0_rtx);
+	  if (really_constant_p (arg)
+	      || (TREE_CODE (arg) == ADDR_EXPR
+		  && TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST))
+	    return const1_rtx;
+
+	  /* Only emit CONSTANT_P_RTX if CSE will be run.  Moreover, we
+	     can't expand trees that have side effects.  */
+	  if (optimize > 0 && no_side_effects_p (arg))
+	    return gen_rtx_CONSTANT_P_RTX (TYPE_MODE (integer_type_node),
+				           expand_expr (TREE_VALUE (arglist),
+						        NULL_RTX, VOIDmode, 0));
+	  return const0_rtx;
 	}
 
     case BUILT_IN_FRAME_ADDRESS:
Index: rtl.def
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/rtl.def,v
retrieving revision 1.9
diff -u -p -r1.9 rtl.def
--- rtl.def	1998/06/17 16:13:53	1.9
+++ rtl.def	1998/06/23 22:05:27
@@ -834,6 +834,11 @@ DEF_RTL_EXPR(RANGE_VAR, "range_var", "et
    0 is the live bitmap.  Operand 1 is the original block number.  */
 DEF_RTL_EXPR(RANGE_LIVE, "range_live", "bi", 'x')
 
+/* A unary `__builtin_constant_p' expression.  These are only emitted
+   during RTL generation, and then only if optimize > 0.  They are
+   eliminated by the first CSE pass. */
+DEF_RTL_EXPR(CONSTANT_P_RTX, "constant_p", "e", 'x')
+
 /*
 Local variables:
 mode:c
Index: tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/tree.c,v
retrieving revision 1.33
diff -u -p -r1.33 tree.c
--- tree.c	1998/06/20 00:35:42	1.33
+++ tree.c	1998/06/23 22:05:38
@@ -1802,6 +1802,57 @@ really_constant_p (exp)
     exp = TREE_OPERAND (exp, 0);
   return TREE_CONSTANT (exp);
 }
+
+/* Nonzero if EXP has no side effects.  */
+
+int
+no_side_effects_p (exp)
+     tree exp;
+{
+  switch (TREE_CODE (exp))
+    {
+    /* 'e' */
+    case COND_EXPR:
+      if (!no_side_effects_p (TREE_OPERAND (exp, 2)))
+        return 0;
+    case TRUTH_ANDIF_EXPR:
+    case TRUTH_ORIF_EXPR:
+    case TRUTH_AND_EXPR:
+    case TRUTH_OR_EXPR:
+      if (!no_side_effects_p (TREE_OPERAND (exp, 1)))
+        return 0;
+    case TRUTH_XOR_EXPR:
+    case TRUTH_NOT_EXPR:
+    case ADDR_EXPR:
+    case REFERENCE_EXPR:
+      return no_side_effects_p (TREE_OPERAND (exp, 0));
+
+    case SAVE_EXPR:
+      /* ??? A difference based on when we examine something?  */
+      if (SAVE_EXPR_RTL (exp) != 0)
+	return 1;
+      return no_side_effects_p (TREE_OPERAND (exp, 0));
+    }
+
+  switch (TREE_CODE_CLASS (TREE_CODE (exp)))
+    {
+    case 'd': case 'c':
+      return 1;
+
+    case '<': case '2':
+      if (!no_side_effects_p (TREE_OPERAND (exp, 1)))
+	return 0;
+    case '1':
+      return no_side_effects_p (TREE_OPERAND (exp, 0));
+
+    case 's':
+    case 'r': case 'e':
+      return 0;
+
+    default:
+      abort();
+    }
+}
 
 /* Return first list element whose TREE_VALUE is ELEM.
    Return 0 if ELEM is not in LIST.  */
Index: tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/tree.h,v
retrieving revision 1.41
diff -u -p -r1.41 tree.h
--- tree.h	1998/06/17 16:13:58	1.41
+++ tree.h	1998/06/23 22:05:43
@@ -2028,6 +2028,7 @@ extern void pop_obstacks PROTO((void));
 
 /* In tree.c */
 extern int really_constant_p		PROTO ((tree));
+extern int no_side_effects_p		PROTO ((tree));
 extern void push_obstacks		PROTO ((struct obstack *,
 						struct obstack *));
 extern void pop_momentary_nofree	PROTO ((void));

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