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 25, 1998 at 07:18:06PM -0700, Jim Wilson wrote:
> Note that if we do install this patch, then we have the immediate problem
> that builtin_constant_p no longer works for some targets, which is a bad
> idea.

Ok, I've now added a check to see if constant_p can be matched,
if not and __builtin_constant_p is used in a context where we'd
like to emit CONSTANT_P_RTX, I issue a warning and do nothing.

> You also need to fix PREDICATE_CODES in alpha.h to accept CONSTANT_P_RTX.

Oh yeah...

Here is the new version, along with my test program.


r~
Index: gcc/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/27 20:04:15
@@ -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: gcc/expr.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/expr.c,v
retrieving revision 1.77
diff -u -p -r1.77 expr.c
--- expr.c	1998/06/25 15:14:26	1.77
+++ expr.c	1998/06/27 20:04:38
@@ -104,6 +104,11 @@ static rtx saveregs_value;
 /* Similarly for __builtin_apply_args.  */
 static rtx apply_args_value;
 
+/* Nonzero if the machine description has been fixed to accept
+   CONSTANT_P_RTX patterns.  We will emit a warning and continue
+   if we find we must actually use such a beast.  */
+static int can_handle_constant_p;
+
 /* Don't check memory usage, since code is being emitted to check a memory
    usage.  Used when flag_check_memory_usage is true, to avoid infinite
    recursion.  */
@@ -239,6 +244,7 @@ init_expr_once ()
 {
   rtx insn, pat;
   enum machine_mode mode;
+  int num_clobbers;
   /* Try indexing by frame ptr and try by stack ptr.
      It is known that on the Convex the stack ptr isn't a valid index.
      With luck, one or the other is valid on any machine.  */
@@ -254,7 +260,6 @@ init_expr_once ()
     {
       int regno;
       rtx reg;
-      int num_clobbers;
 
       direct_load[(int) mode] = direct_store[(int) mode] = 0;
       PUT_MODE (mem, mode);
@@ -295,6 +300,14 @@ init_expr_once ()
 	  }
     }
 
+  /* Find out if CONSTANT_P_RTX is accepted.  */
+  SET_DEST (pat) = gen_rtx_REG (TYPE_MODE (integer_type_node),
+			        FIRST_PSEUDO_REGISTER);
+  SET_SRC (pat) = gen_rtx_CONSTANT_P_RTX (TYPE_MODE (integer_type_node),
+					  SET_DEST (pat));
+  if (recog (pat, insn, &num_clobbers) >= 0)
+    can_handle_constant_p = 1;
+
   end_sequence ();
 }
       
@@ -8542,10 +8555,29 @@ 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
+	     don't want to expand trees that have side effects, as we want
+	     this to be a non-intrusive function a-la sizeof.  */
+	  if (! cse_not_expected && ! TREE_SIDE_EFFECTS (arg))
+	    {
+	      /* Lazy fixup of old code: issue a warning and fail the test.  */
+	      if (! can_handle_constant_p)
+		{
+		  warning ("Delayed evaluation of __builtin_constant_p not supported on this target.");
+		  warning ("Please report this as a bug to egcs-bugs@cygnus.com.");
+		  return const0_rtx;
+		}
+	      return gen_rtx_CONSTANT_P_RTX (TYPE_MODE (integer_type_node),
+				             expand_expr (arg, NULL_RTX,
+							  VOIDmode, 0));
+	    }
+
+	  return const0_rtx;
 	}
 
     case BUILT_IN_FRAME_ADDRESS:
Index: gcc/rtl.def
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/rtl.def,v
retrieving revision 1.10
diff -u -p -r1.10 rtl.def
--- rtl.def	1998/06/25 15:14:31	1.10
+++ rtl.def	1998/06/27 20:04:40
@@ -842,6 +842,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: gcc/rtl.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/rtl.h,v
retrieving revision 1.38
diff -u -p -r1.38 rtl.h
--- rtl.h	1998/06/25 15:14:32	1.38
+++ rtl.h	1998/06/27 20:04:45
@@ -219,7 +219,8 @@ typedef struct rtvec_def{
 #define CONSTANT_P(X)   \
   (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF		\
    || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE		\
-   || GET_CODE (X) == CONST || GET_CODE (X) == HIGH)
+   || GET_CODE (X) == CONST || GET_CODE (X) == HIGH			\
+   || GET_CODE (X) == CONSTANT_P_RTX)
 
 /* General accessor macros for accessing the fields of an rtx.  */
 
Index: gcc/config/alpha/alpha.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/alpha/alpha.c,v
retrieving revision 1.48
diff -u -p -r1.48 alpha.c
--- alpha.c	1998/06/26 06:41:01	1.48
+++ alpha.c	1998/06/27 20:04:53
@@ -337,6 +337,7 @@ reg_or_6bit_operand (op, mode)
 {
   return ((GET_CODE (op) == CONST_INT
 	   && (unsigned HOST_WIDE_INT) INTVAL (op) < 64)
+	  || GET_CODE (op) == CONSTANT_P_RTX
 	  || register_operand (op, mode));
 }
 
@@ -350,6 +351,7 @@ reg_or_8bit_operand (op, mode)
 {
   return ((GET_CODE (op) == CONST_INT
 	   && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100)
+	  || GET_CODE (op) == CONSTANT_P_RTX
 	  || register_operand (op, mode));
 }
 
@@ -360,8 +362,9 @@ cint8_operand (op, mode)
      register rtx op;
      enum machine_mode mode ATTRIBUTE_UNUSED;
 {
-  return (GET_CODE (op) == CONST_INT
-	  && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100);
+  return ((GET_CODE (op) == CONST_INT
+	   && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100)
+	  || GET_CODE (op) == CONSTANT_P_RTX);
 }
 
 /* Return 1 if the operand is a valid second operand to an add insn.  */
@@ -375,6 +378,8 @@ add_operand (op, mode)
     return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'K')
 	    || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L')
 	    || CONST_OK_FOR_LETTER_P (INTVAL (op), 'O'));
+  else if (GET_CODE (op) == CONSTANT_P_RTX)
+    return 1;
 
   return register_operand (op, mode);
 }
@@ -390,6 +395,8 @@ sext_add_operand (op, mode)
   if (GET_CODE (op) == CONST_INT)
     return ((unsigned HOST_WIDE_INT) INTVAL (op) < 255
 	    || (unsigned HOST_WIDE_INT) (- INTVAL (op)) < 255);
+  else if (GET_CODE (op) == CONSTANT_P_RTX)
+    return 1;
 
   return register_operand (op, mode);
 }
@@ -420,6 +427,8 @@ and_operand (op, mode)
     return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100
 	    || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100
 	    || zap_mask (INTVAL (op)));
+  else if (GET_CODE (op) == CONSTANT_P_RTX)
+    return 1;
 
   return register_operand (op, mode);
 }
@@ -434,6 +443,8 @@ or_operand (op, mode)
   if (GET_CODE (op) == CONST_INT)
     return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100
 	    || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100);
+  else if (GET_CODE (op) == CONSTANT_P_RTX)
+    return 1;
 
   return register_operand (op, mode);
 }
@@ -532,7 +543,9 @@ reg_or_cint_operand (op, mode)
     register rtx op;
     enum machine_mode mode;
 {
-     return GET_CODE (op) == CONST_INT || register_operand (op, mode);
+     return (GET_CODE (op) == CONST_INT
+	     || GET_CODE (op) == CONSTANT_P_RTX
+	     || register_operand (op, mode));
 }
 
 /* Return 1 if OP is something that can be reloaded into a register;
@@ -548,8 +561,8 @@ some_operand (op, mode)
 
   switch (GET_CODE (op))
     {
-    case REG:  case MEM:  case CONST_DOUBLE:
-    case CONST_INT:  case LABEL_REF:  case SYMBOL_REF:  case CONST:
+    case REG:  case MEM:  case CONST_DOUBLE:  case CONST_INT:  case LABEL_REF:
+    case SYMBOL_REF:  case CONST:  case CONSTANT_P_RTX:
       return 1;
 
     case SUBREG:
@@ -580,7 +593,7 @@ input_operand (op, mode)
     case LABEL_REF:
     case SYMBOL_REF:
     case CONST:
-        /* This handles both the Windows/NT and OSF cases.  */
+      /* This handles both the Windows/NT and OSF cases.  */
       return mode == ptr_mode || mode == DImode;
 
     case REG:
@@ -598,6 +611,7 @@ input_operand (op, mode)
       return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode);
 
     case CONST_INT:
+    case CONSTANT_P_RTX:
       return mode == QImode || mode == HImode || add_operand (op, mode);
 
     default:
Index: gcc/config/alpha/alpha.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/alpha/alpha.h,v
retrieving revision 1.38
diff -u -p -r1.38 alpha.h
--- alpha.h	1998/06/26 06:41:03	1.38
+++ alpha.h	1998/06/27 20:05:01
@@ -2205,36 +2205,36 @@ do {									\
 }
 /* Define the codes that are matched by predicates in alpha.c.  */
 
-#define PREDICATE_CODES \
-  {"reg_or_0_operand", {SUBREG, REG, CONST_INT}},	\
-  {"reg_or_6bit_operand", {SUBREG, REG, CONST_INT}},	\
-  {"reg_or_8bit_operand", {SUBREG, REG, CONST_INT}},	\
-  {"cint8_operand", {CONST_INT}},                       \
-  {"reg_or_cint_operand", {SUBREG, REG, CONST_INT}},	\
-  {"add_operand", {SUBREG, REG, CONST_INT}},		\
-  {"sext_add_operand", {SUBREG, REG, CONST_INT}},	\
-  {"const48_operand", {CONST_INT}},			\
-  {"and_operand", {SUBREG, REG, CONST_INT}},		\
-  {"or_operand", {SUBREG, REG, CONST_INT}},		\
-  {"mode_mask_operand", {CONST_INT}},			\
-  {"mul8_operand", {CONST_INT}},			\
-  {"mode_width_operand", {CONST_INT}},			\
-  {"reg_or_fp0_operand", {SUBREG, REG, CONST_DOUBLE}},	\
-  {"alpha_comparison_operator", {EQ, LE, LT, LEU, LTU}}, \
-  {"alpha_swapped_comparison_operator", {EQ, GE, GT, GEU, GTU}}, \
-  {"signed_comparison_operator", {EQ, NE, LE, LT, GE, GT}}, \
-  {"divmod_operator", {DIV, MOD, UDIV, UMOD}},		\
-  {"fp0_operand", {CONST_DOUBLE}},			\
-  {"current_file_function_operand", {SYMBOL_REF}},	\
-  {"call_operand", {REG, SYMBOL_REF}},			\
-  {"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE,	\
-		     SYMBOL_REF, CONST, LABEL_REF}},	\
-  {"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \
-		    SYMBOL_REF, CONST, LABEL_REF}},	\
-  {"aligned_memory_operand", {MEM}},			\
-  {"unaligned_memory_operand", {MEM}},			\
-  {"reg_or_unaligned_mem_operand", {SUBREG, REG, MEM}},	\
-  {"any_memory_operand", {MEM}},			\
+#define PREDICATE_CODES 						\
+  {"reg_or_0_operand", {SUBREG, REG, CONST_INT}},			\
+  {"reg_or_6bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}},	\
+  {"reg_or_8bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}},	\
+  {"cint8_operand", {CONST_INT, CONSTANT_P_RTX}},                       \
+  {"reg_or_cint_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}},	\
+  {"add_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}},		\
+  {"sext_add_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}},	\
+  {"const48_operand", {CONST_INT}},					\
+  {"and_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}},		\
+  {"or_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}},		\
+  {"mode_mask_operand", {CONST_INT}},					\
+  {"mul8_operand", {CONST_INT}},					\
+  {"mode_width_operand", {CONST_INT}},					\
+  {"reg_or_fp0_operand", {SUBREG, REG, CONST_DOUBLE}},			\
+  {"alpha_comparison_operator", {EQ, LE, LT, LEU, LTU}},		\
+  {"alpha_swapped_comparison_operator", {EQ, GE, GT, GEU, GTU}},	\
+  {"signed_comparison_operator", {EQ, NE, LE, LT, GE, GT}},		\
+  {"divmod_operator", {DIV, MOD, UDIV, UMOD}},				\
+  {"fp0_operand", {CONST_DOUBLE}},					\
+  {"current_file_function_operand", {SYMBOL_REF}},			\
+  {"call_operand", {REG, SYMBOL_REF}},					\
+  {"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE,		\
+		     SYMBOL_REF, CONST, LABEL_REF, CONSTANT_P_RTX}},	\
+  {"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE,		\
+		    SYMBOL_REF, CONST, LABEL_REF, CONSTANT_P_RTX}},	\
+  {"aligned_memory_operand", {MEM}},					\
+  {"unaligned_memory_operand", {MEM}},					\
+  {"reg_or_unaligned_mem_operand", {SUBREG, REG, MEM}},			\
+  {"any_memory_operand", {MEM}},					\
   {"hard_fp_register_operand", {SUBREG, REG}},
 
 /* Tell collect that the object format is ECOFF.  */
int global;

/* These must fail.  */
int bad0(void) { return __builtin_constant_p(global); }
int bad1(void) { return __builtin_constant_p(global++); }
inline int bad2(int x) { return __builtin_constant_p(x++); }
inline int bad3(int x) { return __builtin_constant_p(x); }
inline int bad4(const char *x) { return __builtin_constant_p(x); }
int bad5(void) { return bad2(1); }
inline int bad6(int x) { return __builtin_constant_p(x+1); }
int bad7(void) { return __builtin_constant_p(abort()); }
int bad8(void) { char buf[10]; return __builtin_constant_p(buf); }
int bad9(const char *x) { return __builtin_constant_p(x[123456]); }

/* These must pass, or we've broken gcc2 functionality.  */
int good0(void) { return __builtin_constant_p(1); }
int good1(void) { return __builtin_constant_p("hi"); }
int good2(void) { return __builtin_constant_p((1234 + 45) & ~7); }

/* These are extensions to gcc2.  Failure indicates an optimization
   regression.  */
int opt0(void) { return bad3(1); }
int opt1(void) { return bad4("hi"); }
int opt2(void) { return bad6(1); }
int opt3(void) { return __builtin_constant_p(&global); }
int opt4(void) { return __builtin_constant_p("hi"[0]); }

/* Call through tables so -finline-functions can't screw with us.  */
int (*bad_t0[])(void) = {
	bad0, bad1, bad5, bad7, bad8
};

int (*bad_t1[])(int x) = {
	bad2, bad3, bad6
};

int (*bad_t2[])(const char *x) = {
	bad4, bad9
};

int (*good_t0[])(void) = {
	good0, good1, good2
};

int (*opt_t0[])(void) = {
	opt0, opt1, opt2, opt3, opt4
};

#define N(arr) (sizeof(arr)/sizeof(*arr))

int main()
{
  int i;

  for (i = 0; i < N(bad_t0); ++i)
    if ((*bad_t0[i])())
      abort();

  for (i = 0; i < N(bad_t1); ++i)
    if ((*bad_t1[i])(1))
      abort();

  for (i = 0; i < N(bad_t2); ++i)
    if ((*bad_t2[i])("hi"))
      abort();

  for (i = 0; i < N(good_t0); ++i)
    if (! (*good_t0[i])())
      abort();

#ifdef __OPTIMIZE__
  for (i = 0; i < N(good_t0); ++i)
    if (! (*opt_t0[i])())
      abort();
#endif

  exit(0);
}

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