[ast-optimizer-branch] More simplification fixes [patch]

Diego Novillo dnovillo@redhat.com
Tue Apr 30 17:33:00 GMT 2002


This patch gets us almost all the way through stage1.  There is
no new functionality, just bug fixes.

Stage 2 will probably be even more annoying, as we will be
dealing with miscompilation of stage1 objects.  But there is some
relief in that some of the binaries built by stage1 seem to work
fine.

Committed to the branch.

Diego.


	* c-pretty-print.c (NIY): Display an error string instead of aborting.
	(op_prio): Add support for COMPOUND_EXPR, TRUTH_XOR_EXPR, MIN_EXPR,
	MAX_EXPR and NON_LVALUE_EXPR.
	For EXPR_WITH_FILE_LOCATION nodes, return the priority of
	the internal node.
	(op_symbol): Add support for TRUTH_XOR_EXPR.
	* c-simplify.c (simplify_stmt): Only remove null statements that
	have been nullified by simplification.
	Call debug_tree() dump unhandled tree nodes.
	(simplify_for_stmt): Always deep-copy PRE_COND_S before adding it
	to PRE_P.
	(simplify_expr): When simplifying a MODIFY_EXPR node into an
	rvalue, return operand 0.
	Handle VA_ARG_EXPR, BIT_FIELD_REF and NON_LVALUE_EXPR nodes.
	Treat TRUTH_AND_EXPR, TRUTH_OR_EXPR and TRUTH_XOR_EXPR nodes as
	regular binary expressions.
	Call debug_tree() to dump an unhandled expression.
	(simplify_array_ref): Do not simplify the base of an array.
	(simplify_call_expr): Do not simplify calls to builtins.
	(simplify_cond_expr): Handle conditional expressions of type void.
	(simplify_boolean_expr): Return 'T != 0' instead of 'T'.
	(simplify_save_expr): Do not wrap statement trees inside SAVE_EXPR
	nodes.
	(tree_last_decl): Ignore FILE_STMT nodes preceding a SCOPE_STMT.
	* tree-simple.c: Update grammar to accept any valid C array as the
	array base.
	(is_simple_compstmt): Accept DECL_INITIAL expressions for read-only
	variables.
	(is_simple_expr): Do not abort if the incoming tree is NULL.
	(is_simple_modify_expr): Allow SAVE_EXPR, EXPR_WITH_FILE_LOCATION
	and NON_LVALUE_EXPR wrappers.
	(is_simple_binary_expr): Ditto.
	(is_simple_condexpr): Ditto.
	Accept TRUTH_AND_EXPR, TRUTH_OR_EXPR and TRUTH_XOR_EXPR.
	(is_simple_unary_expr): Do not abort it the incoming tree is NULL.
	Allow SAVE_EXPR, EXPR_WITH_FILE_LOCATION and NON_LVALUE_EXPR
	wrappers.
	Handle BIT_FIELD_REF and VA_ARG_EXPR nodes.
	(is_simple_call_expr): Always return 1 for builtin calls.
	(is_simple_arrayref): Do not check the array base.

Index: c-pretty-print.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/c-pretty-print.c,v
retrieving revision 1.1.2.6
diff -d -p -d -u -p -r1.1.2.6 c-pretty-print.c
--- c-pretty-print.c	22 Apr 2002 14:42:08 -0000	1.1.2.6
+++ c-pretty-print.c	1 May 2002 00:09:36 -0000
@@ -43,7 +43,9 @@ static void print_call_name     PARAMS (
 #define INDENT(SPACE) do { \
   int i; for (i = 0; i<SPACE; i++) output_add_space (buffer); } while (0)
 #define NIY do { \
-  debug_output_buffer (buffer); debug_tree (node); abort (); } while (0)
+    output_add_string (buffer, "<<< Unknown tree: "); \
+    output_add_string (buffer, tree_code_name[(int) TREE_CODE (node)]); \
+    output_add_string (buffer, " >>>\n"); } while (0)
 
 #define PRINT_FUNCTION_NAME(NODE)  output_printf             \
   (buffer, "%s", TREE_CODE (NODE) == NOP_EXPR ?              \
@@ -1219,6 +1221,7 @@ op_prio (op)
   switch (TREE_CODE (op))
     {
     case TREE_LIST:
+    case COMPOUND_EXPR:
       return 1;
 
     case MODIFY_EXPR:
@@ -1239,6 +1242,7 @@ op_prio (op)
       return 6;
 
     case BIT_XOR_EXPR:
+    case TRUTH_XOR_EXPR:
       return 7;
 
     case BIT_AND_EXPR:
@@ -1300,9 +1304,16 @@ op_prio (op)
 
       /* Special expressions.  */
     case STMT_EXPR:
+    case MIN_EXPR:
+    case MAX_EXPR:
+      return 16;
+
     case SAVE_EXPR:
+    case NON_LVALUE_EXPR:
+      return op_prio (TREE_OPERAND (op, 0));
+
     case EXPR_WITH_FILE_LOCATION:
-      return 16;
+      return op_prio (EXPR_WFL_NODE (op));
 
     default:
       /* If OP is any type of expression operator, abort because we
@@ -1350,6 +1361,7 @@ op_symbol (op)
     case BIT_IOR_EXPR:
       return "|";
       
+    case TRUTH_XOR_EXPR:
     case BIT_XOR_EXPR:
       return "^";
       
Index: c-simplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/c-simplify.c,v
retrieving revision 1.1.2.13
diff -d -p -d -u -p -r1.1.2.13 c-simplify.c
--- c-simplify.c	30 Apr 2002 04:47:48 -0000	1.1.2.13
+++ c-simplify.c	1 May 2002 00:09:36 -0000
@@ -133,7 +133,7 @@ static void 
 simplify_stmt (stmt)
      tree stmt;
 {
-  tree next, prev, pre, post;
+  tree prev;
 
   /* PRE and POST are tree chains that contain the side-effects of the
      simplified tree.  For instance, given the expression tree:
@@ -150,8 +150,12 @@ simplify_stmt (stmt)
   prev = stmt;
   while (stmt && stmt != error_mark_node)
     {
+      tree next, pre, post;
+      int stmt_was_null;
+
       pre = NULL;
       post = NULL;
+      stmt_was_null = 0;
       next = TREE_CHAIN (stmt);
       
       switch (TREE_CODE (stmt))
@@ -188,8 +192,22 @@ simplify_stmt (stmt)
 	  break;
 
 	case EXPR_STMT:
-	  EXPR_STMT_EXPR (stmt) = simplify_expr (EXPR_STMT_EXPR (stmt), &pre,
-	                                         &post, is_simple_expr, 0);
+	  {
+	    tree e = EXPR_STMT_EXPR (stmt);
+
+	    /* Simplification of a statement expression will nullify the
+	       statement if all its side effects are moved to PRE and POST.
+	       In this case we will not want to emit the simplified
+	       statement.  However, if the statement was already null
+	       before simplification, we should leave it to avoid changing
+	       the semantics of the program.  */
+	    if (!expr_has_effect (e))
+	      stmt_was_null = 1;
+
+	    EXPR_STMT_EXPR (stmt) = simplify_expr (e, &pre, &post,
+		                                   is_simple_expr, 0);
+	  }
+	    
 	  break;
 
 	case DECL_STMT:
@@ -247,9 +265,7 @@ simplify_stmt (stmt)
 	default:
 	  prep_stmt (stmt);
 	  fprintf (stderr, "unhandled statement node in simplify_stmt ():\n");
-	  print_node_brief (stderr, "", stmt, 0);
-	  debug_c_node (stmt);
-	  fprintf (stderr, "\n");
+	  debug_tree (stmt);
 	  abort ();
 	  break;
 	}
@@ -273,7 +289,11 @@ simplify_stmt (stmt)
       TREE_CHAIN (stmt) = NULL_TREE;
 
       chainon (prev, pre);
-      if (stmt_has_effect (stmt))
+      /* If the statement had no effect before simplification, we emit it
+	 anyway to avoid changing the semantics of the original program.
+	 This is mainly used for the return value of statement-expressions.  */
+      if (stmt_was_null
+	  || stmt_has_effect (stmt))
 	{
 	  chainon (prev, stmt);
 	  chainon (stmt, post);
@@ -437,13 +457,15 @@ simplify_for_stmt (stmt, pre_p, post_p)
      doesn't resemble the original.  To minimize shape changes, we try to
      insert expressions in FOR_INIT_STMT and FOR_EXPR.  */
 
-  /* Link PRE_INIT_S, INIT_S, POST_INIT_S and PRE_COND_S to make up
-     a new FOR_INIT_STMT.  If the last tree in the list is an
-     expression tree, it is emmitted inside FOR_INIT_STMT.  */
+  /* Link PRE_INIT_S, INIT_S, POST_INIT_S and a copy of PRE_COND_S to make
+     up a new FOR_INIT_STMT.  If the last tree in the list is an expression
+     tree, it is emmitted inside FOR_INIT_STMT.  We emit a copy of
+     PRE_COND_S because we also need to emit it at every wrap-around point
+     in the loop body.  */
   add_tree (pre_init_s, pre_p);
   add_tree (init_s, pre_p);
   add_tree (post_init_s, pre_p);
-  add_tree (pre_cond_s, pre_p);
+  add_tree (deep_copy_list (pre_cond_s), pre_p);
 
   if (*pre_p)
     {
@@ -967,7 +989,7 @@ simplify_expr (expr, pre_p, post_p, simp
       if (simple_test_f != is_simple_expr)
 	{
 	  add_tree (expr_s, pre_p);
-	  expr_s = TREE_OPERAND (expr_s, 1);
+	  expr_s = TREE_OPERAND (expr_s, 0);
 	}
       break;
 
@@ -983,6 +1005,10 @@ simplify_expr (expr, pre_p, post_p, simp
       expr_s = expr;
       break;
 
+    case VA_ARG_EXPR:
+      expr_s = expr;
+      break;
+
     case NOP_EXPR:
     case CONVERT_EXPR:
     case FIX_TRUNC_EXPR:
@@ -1036,6 +1062,27 @@ simplify_expr (expr, pre_p, post_p, simp
 	                          needs_lvalue);
       break;
 
+    case BIT_FIELD_REF:
+      expr_s = expr;
+      TREE_OPERAND (expr_s, 0) = simplify_expr (TREE_OPERAND (expr_s, 0),
+	                                        pre_p, post_p, is_simple_id,
+						needs_lvalue);
+
+      TREE_OPERAND (expr_s, 1) = simplify_expr (TREE_OPERAND (expr_s, 1),
+	                                        pre_p, post_p, is_simple_val,
+						0);
+
+      TREE_OPERAND (expr_s, 2) = simplify_expr (TREE_OPERAND (expr_s, 2),
+	                                        pre_p, post_p, is_simple_val,
+						0);
+      break;
+
+    case NON_LVALUE_EXPR:
+      expr_s = expr;
+      TREE_OPERAND (expr_s, 0) = simplify_expr (TREE_OPERAND (expr_s, 0),
+	                                        pre_p, post_p, simple_test_f,
+						0);
+      break;
 
     /* If EXPR does not need to be special-cased, handle it according to
        its class.  */
@@ -1052,7 +1099,10 @@ simplify_expr (expr, pre_p, post_p, simp
 	    TREE_OPERAND (expr_s, 0) = t;
 	  }
 	else if (TREE_CODE_CLASS (TREE_CODE (expr_s)) == '2'
-	         || TREE_CODE_CLASS (TREE_CODE (expr_s)) == '<')
+	         || TREE_CODE_CLASS (TREE_CODE (expr_s)) == '<'
+		 || TREE_CODE (expr_s) == TRUTH_AND_EXPR
+		 || TREE_CODE (expr_s) == TRUTH_OR_EXPR
+		 || TREE_CODE (expr_s) == TRUTH_XOR_EXPR)
 	  {
 	    tree lhs, rhs;
 
@@ -1068,10 +1118,7 @@ simplify_expr (expr, pre_p, post_p, simp
 	else
 	  {
 	    fprintf (stderr, "unhandled expression in simplify_expr ():\n");
-	    print_node_brief (stderr, "", expr_s, 0);
-	    fputs ("\n", stderr);
-	    debug_c_node (expr_s);
-	    fputs ("\n", stderr);
+	    debug_tree (expr_s);
 	    abort ();
 	  }
       }
@@ -1088,10 +1135,8 @@ simplify_expr (expr, pre_p, post_p, simp
   if (!is_simple_rhs (expr_s))
     {
       fprintf (stderr, "Could not convert expression into a SIMPLE RHS:\n");
-      print_node_brief (stderr, "", expr_s, 0);
-      fputs ("\n", stderr);
-      debug_c_node (expr_s);
-      fputs ("\n", stderr);
+      debug_tree (expr_s);
+      fprintf (stderr, "\n");
       abort ();
     }
 
@@ -1152,7 +1197,7 @@ simplify_expr (expr, pre_p, post_p, simp
     SIMPLE grammar:
 
      arrayref
-	    : varname reflist
+	    : arraybase reflist
 
      reflist
 	    : '[' val ']'
@@ -1178,10 +1223,8 @@ simplify_array_ref (expr, pre_p, post_p)
 
   VARRAY_GENERIC_PTR_INIT (dim_stack, 10, "dim_stack");
 
-  /* First find and simplify the base of the array.  While looking
-     for the base of the array, push all the dimensions along the
-     way, so that they can be simplified from left to right after the
-     base.  */
+  /* Create a stack with all the dimensions of the array so that they can
+     be simplified from left to right.  */
   base = expr;
   VARRAY_PUSH_GENERIC_PTR (dim_stack, (PTR)&(TREE_OPERAND (expr, 1)));
   while (TREE_CODE (TREE_OPERAND (base, 0)) == ARRAY_REF)
@@ -1192,12 +1235,11 @@ simplify_array_ref (expr, pre_p, post_p)
 
   /* After the loop above, 'base' contains the leftmost ARRAY_REF,
      and 'dim_stack' is a stack of pointers to all the dimensions in left
-     to right order (the leftmost dimension is at the top of the
-     stack).  */
-  TREE_OPERAND (base, 0) = simplify_expr (TREE_OPERAND (base, 0), pre_p,
-                                          post_p, is_simple_varname, 1);
+     to right order (the leftmost dimension is at the top of the stack).
 
-  /* Now simplify each of the dimensions from left to right.  */
+     Simplify each of the dimensions from left to right.  Note that the
+     base of the array is never simplified because that would break the
+     semantics of C arrays.  */
   while (VARRAY_ACTIVE_SIZE (dim_stack) > 0)
     {
       tree *dim_p = (tree *)VARRAY_TOP_GENERIC_PTR (dim_stack);
@@ -1345,7 +1387,15 @@ simplify_call_expr (expr, pre_p, post_p)
   if (TREE_CODE (expr) != CALL_EXPR)
     abort ();
 
+  /* Do not simplify calls to builtin functions as they may require
+     specific tree nodes (e.g., __builtin_stdarg_start).
+     FIXME: We should identify which builtins can be simplified safely.  */
+  id = get_callee_fndecl (expr);
+  if (id && DECL_BUILT_IN (id))
+    return expr;
+
   id = simplify_expr (TREE_OPERAND (expr, 0), pre_p, post_p, is_simple_id, 0);
+
   if (TREE_OPERAND (expr, 1))
     arglist = simplify_expr (TREE_OPERAND (expr, 1), pre_p, post_p,
   			     is_simple_arglist, 0);
@@ -1401,11 +1451,13 @@ simplify_tree_list (expr, pre_p, post_p)
 
     Convert the conditional expression EXPR '(p) ? a : b;' into
 
-    if (p)
-      t1 = a;
-    else
-      t1 = b;
-    t1;
+    if (p)			if (p)
+      t1 = a;			  a;
+    else		or	else
+      t1 = b;			  b;
+    t1;				(void)0;
+
+    The second form is used when EXPR is of type void.
 
     PRE_P points to the list where side effects that must happen before
 	EXPR should be stored.
@@ -1419,9 +1471,14 @@ simplify_cond_expr (expr, pre_p, post_p)
      tree *pre_p;
      tree *post_p;
 {
-  tree t_then, t_else, tmp, pred, tval, fval, new_if;
+  tree t_then, t_else, tmp, pred, tval, fval, new_if, expr_type;
 
-  tmp = create_tmp_var (TREE_TYPE (expr));
+  expr_type = TREE_TYPE (expr);
+
+  if (!VOID_TYPE_P (expr_type))
+    tmp = create_tmp_var (TREE_TYPE (expr));
+  else
+    tmp = void_zero_node;
 
   pred = simplify_expr (TREE_OPERAND (expr, 0), pre_p, post_p, is_simple_expr,
                         0);
@@ -1432,11 +1489,17 @@ simplify_cond_expr (expr, pre_p, post_p)
   fval = simplify_expr (TREE_OPERAND (expr, 2), pre_p, post_p, is_simple_expr,
                         0);
 
-  /* Build the THEN_CLAUSE 't1 = a;'.  */
-  t_then = build_stmt (EXPR_STMT, build_modify_expr (tmp, NOP_EXPR, tval));
+  /* Build the THEN_CLAUSE 't1 = a;' or 'a;'.  */
+  if (!VOID_TYPE_P (expr_type))
+    t_then = build_stmt (EXPR_STMT, build_modify_expr (tmp, NOP_EXPR, tval));
+  else
+    t_then = build_stmt (EXPR_STMT, tval);
 
-  /* Build the ELSE_CLAUSE 't1 = b;'.  */
-  t_else = build_stmt (EXPR_STMT, build_modify_expr (tmp, NOP_EXPR, fval));
+  /* Build the ELSE_CLAUSE 't1 = b;' or 'b;'.  */
+  if (!VOID_TYPE_P (expr_type))
+    t_else = build_stmt (EXPR_STMT, build_modify_expr (tmp, NOP_EXPR, fval));
+  else
+    t_else = build_stmt (EXPR_STMT, fval);
 
   /* Build a new IF_STMT, and insert it in the PRE_P chain.  */
   new_if = build_stmt (IF_STMT, pred, t_then, t_else);
@@ -1520,7 +1583,7 @@ simplify_modify_expr (expr, pre_p, post_
 	if (!T)
 	  T = b;
 
-    In both cases, the expression 'T' is returned.
+    In both cases, the expression 'T != 0' is returned.
 
 
     PRE_P points to the list where side effects that must happen before
@@ -1566,7 +1629,7 @@ simplify_boolean_expr (expr, pre_p, post
 
   add_tree (build_stmt (IF_STMT, if_cond, if_body, NULL_TREE), pre_p);
 
-  return t;
+  return build (NE_EXPR, TREE_TYPE (expr), t, integer_zero_node);
 }
 
 /* }}} */
@@ -1709,11 +1772,15 @@ simplify_save_expr (expr, pre_p, post_p,
                           needs_lvalue);
 
   for (op = *pre_p; op; op = TREE_CHAIN (op))
-    TREE_VALUE (op) = save_expr (TREE_VALUE (op));
+    if (!statement_code_p (TREE_CODE (TREE_VALUE (op))))
+      TREE_VALUE (op) = save_expr (TREE_VALUE (op));
 
   for (op = *post_p; op; op = TREE_CHAIN (op))
-    TREE_VALUE (op) = save_expr (TREE_VALUE (op));
+    if (!statement_code_p (TREE_CODE (TREE_VALUE (op))))
+      TREE_VALUE (op) = save_expr (TREE_VALUE (op));
 
+  /* simplify_expr() will never return a statement tree, so we can assume
+     that we can wrap EXPR_S inside a SAVE_EXPR node.  */
   return save_expr (expr_s);
 }
 
@@ -2165,7 +2232,10 @@ tree_last_decl (scope)
 {
   tree last;
 
-  /* Be sure that we get a scope.  */
+  /* Be sure that we get a scope.  Ignore FILE_STMT nodes.  */
+  while (TREE_CODE (scope) == FILE_STMT)
+    scope = TREE_CHAIN (scope);
+
   if (!SCOPE_BEGIN_P (scope))
     abort ();
 
Index: tree-simple.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-simple.c,v
retrieving revision 1.1.2.6
diff -d -p -d -u -p -r1.1.2.6 tree-simple.c
--- tree-simple.c	27 Apr 2002 22:54:22 -0000	1.1.2.6
+++ tree-simple.c	1 May 2002 00:09:40 -0000
@@ -174,9 +174,11 @@ Boston, MA 02111-1307, USA.  */
 	      | ID
 
       arrayref
-	      : varname reflist		=> Original grammar only allowed
-	                                   'ID reflist'.  This causes
-					   splits like k.d[2][3] into
+	      : arraybase reflist	=> 'arraybase' is any valid C array
+					   name.  Original grammar only
+					   allowed 'ID reflist'.  This
+					   causes splits like k.d[2][3]
+					   into
 					   
 					   	t1 = &(k.d[2])
   						t2 = *(&t1[3])
@@ -329,9 +331,16 @@ is_simple_compstmt (t)
       || !SCOPE_BEGIN_P (t))
     return 0;
 
-  /* Test all the declarations.  */
+  /* Test all the declarations.
+
+     ??? This allows initializers for read-only variables.  This is not
+         allowed in the original grammar, but I really see no other way
+	 around this.  If we simplify these declarations, we get warnings
+	 and if we change the read-only bit, we'll change the semantics of
+	 the variable.  */
   for (t = TREE_CHAIN (t); t && TREE_CODE (t) == DECL_STMT; t = TREE_CHAIN (t))
-    if (DECL_INITIAL (DECL_STMT_DECL (t)))
+    if (DECL_INITIAL (DECL_STMT_DECL (t))
+	&& !TREE_READONLY (DECL_STMT_DECL (t)))
       return 0;
 
   /* Test all the statements in the body.  */
@@ -367,9 +376,6 @@ int
 is_simple_expr (t)
      tree t;
 {
-  if (t == NULL_TREE)
-    abort ();
-
   return (is_simple_rhs (t) || is_simple_modify_expr (t));
 }
 
@@ -411,6 +417,13 @@ int
 is_simple_modify_expr (t)
      tree t;
 {
+  /* Additions to the original grammar.  Allow SAVE_EXPR, NON_LVALUE_EXPR
+     and EXPR_WITH_FILE_LOCATION wrappers.  */
+  if (TREE_CODE (t) == SAVE_EXPR
+      || TREE_CODE (t) == EXPR_WITH_FILE_LOCATION
+      || TREE_CODE (t) == NON_LVALUE_EXPR)
+    return is_simple_modify_expr (TREE_OPERAND (t, 0));
+
   return (TREE_CODE (t) == MODIFY_EXPR
 	  && is_simple_modify_expr_lhs (TREE_OPERAND (t, 0))
 	  && is_simple_rhs (TREE_OPERAND (t, 1)));
@@ -444,6 +457,13 @@ int
 is_simple_binary_expr (t)
      tree t;
 {
+  /* Additions to the original grammar.  Allow SAVE_EXPR, NON_LVALUE_EXPR
+     and EXPR_WITH_FILE_LOCATION wrappers.  */
+  if (TREE_CODE (t) == SAVE_EXPR
+      || TREE_CODE (t) == EXPR_WITH_FILE_LOCATION
+      || TREE_CODE (t) == NON_LVALUE_EXPR)
+    return is_simple_binary_expr (TREE_OPERAND (t, 0));
+
   return (TREE_CODE_CLASS (TREE_CODE (t)) == '2'
 	  && is_simple_val (TREE_OPERAND (t, 0))
 	  && is_simple_val (TREE_OPERAND (t, 1)));
@@ -463,8 +483,18 @@ int
 is_simple_condexpr (t)
      tree t;
 {
+  /* Additions to the original grammar.  Allow SAVE_EXPR, NON_LVALUE_EXPR
+     and EXPR_WITH_FILE_LOCATION wrappers.  */
+  if (TREE_CODE (t) == SAVE_EXPR
+      || TREE_CODE (t) == EXPR_WITH_FILE_LOCATION
+      || TREE_CODE (t) == NON_LVALUE_EXPR)
+    return is_simple_condexpr (TREE_OPERAND (t, 0));
+
   return (is_simple_val (t)
-	  || (TREE_CODE_CLASS (TREE_CODE (t)) == '<'
+	  || ((TREE_CODE_CLASS (TREE_CODE (t)) == '<'
+	       || TREE_CODE (t) == TRUTH_AND_EXPR
+	       || TREE_CODE (t) == TRUTH_OR_EXPR
+	       || TREE_CODE (t) == TRUTH_XOR_EXPR)
 	      && is_simple_val (TREE_OPERAND (t, 0))
 	      && is_simple_val (TREE_OPERAND (t, 1))));
 }
@@ -498,8 +528,12 @@ int
 is_simple_unary_expr (t)
      tree t;
 {
-  if (t == NULL_TREE)
-    abort ();
+  /* Additions to the original grammar.  Allow STMT_EXPR, SAVE_EXPR and
+     EXPR_WITH_FILE_LOCATION wrappers.  */
+  if (TREE_CODE (t) == SAVE_EXPR
+      || TREE_CODE (t) == EXPR_WITH_FILE_LOCATION
+      || TREE_CODE (t) == NON_LVALUE_EXPR)
+    return is_simple_unary_expr (TREE_OPERAND (t, 0));
 
   if (is_simple_varname (t) || is_simple_const (t))
     return 1;
@@ -523,16 +557,23 @@ is_simple_unary_expr (t)
   if (is_simple_cast (t))
     return 1;
 
-  /* Additions to the original grammar.  Allow STMT_EXPR, SAVE_EXPR and
-     EXPR_WITH_FILE_LOCATION.  */
+  /* Additions to the original grammar.  FIXME:  Statement-expressions should
+     really be expanded.  */
   if (TREE_CODE (t) == STMT_EXPR
       && is_simple_stmt (STMT_EXPR_STMT (t)))
     return 1;
 
-  if (TREE_CODE (t) == SAVE_EXPR
-      || TREE_CODE (t) == EXPR_WITH_FILE_LOCATION
-      || TREE_CODE (t) == NON_LVALUE_EXPR)
-    return is_simple_unary_expr (TREE_OPERAND (t, 0));
+  /* Addition to the original grammar.  Allow BIT_FIELD_REF nodes where
+     operand 0 is a SIMPLE identifier and operands 1 and 2 are SIMPLE
+     values.  */
+  if (TREE_CODE (t) == BIT_FIELD_REF)
+    return (is_simple_id (TREE_OPERAND (t, 0))
+	    && is_simple_val (TREE_OPERAND (t, 1))
+	    && is_simple_val (TREE_OPERAND (t, 2)));
+
+  /* Addition to the original grammar.  Allow VA_ARG_EXPR nodes.  */
+  if (TREE_CODE (t) == VA_ARG_EXPR)
+    return 1;
 
   return 0;
 }
@@ -554,9 +595,20 @@ int
 is_simple_call_expr (t)
      tree t;
 {
+  tree decl;
+
   if (TREE_CODE (t) != CALL_EXPR)
     return 0;
 
+  /* Consider that calls to builtin functions are in SIMPLE form already.
+
+     FIXME: The simplifier will not simplify these calls because some
+	    builtins need specific arguments (e.g., __builtin_stdarg_start
+	    wants one of the function arguments as its last parameters).  */
+  decl = get_callee_fndecl (t);
+  if (decl && DECL_BUILT_IN (decl))
+    return 1;
+
   return (is_simple_id (TREE_OPERAND (t, 0))
           && is_simple_arglist (TREE_OPERAND (t, 1)));
 }
@@ -666,7 +718,12 @@ is_simple_val (t)
     Return nonzero if T is an array reference of the form:
 
       arrayref
-	      : varname reflist
+	      : arraybase reflist	=> 'arraybase' is any valid C array
+					    name.  The original grammar
+					    allowed only ID here, but we
+					    cannot simplify array bases
+					    because we may get invalid
+					    code.
 
       reflist
 	      : '[' val ']'
@@ -677,7 +734,6 @@ is_simple_arrayref (t)
      tree t;
 {
   return (TREE_CODE (t) == ARRAY_REF
-	  && is_simple_varname (TREE_OPERAND (t, 0))
           && is_simple_val (TREE_OPERAND (t, 1)));
 }



More information about the Gcc-patches mailing list