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]

[tree-ssa] PATCH to avoid extra work when gimplifying


This patch fixes all the cases found by my previous patch whereby the
gimplifier was doing work on a second pass.  Most of these were cases of
the gimplifier working too hard on code that was already GIMPLE, but some
were cases of the second pass finding simplifications that the first pass
missed.

The most significant chunk is modifications to CONSTRUCTOR handling.  We
now always break down a CONSTRUCTOR used in an initialization, and are more
clever about it than we were before; I've copied much of the
store_constructor logic.

Booted and tested athlon-pc-linux-gnu, applied to tree-ssa branch.  expr.c,
tree.h, and stmt.c hunks also applied to trunk.

2003-07-30  Jason Merrill  <jason@redhat.com>

	Don't modify code that is already GIMPLE.
	* gimplify.c (gimplify_expr): Don't return early if the predicate 
	matches.
	Use a variable temp if the caller wants an lvalue.
	Don't call gimplify_constructor if we're on the rhs of a MODIFY_EXPR.
	(add_tree, add_stmt_to_compound): Do add an empty stmt if we 
	previously had nothing at all.
	(gimplify_return_expr): Don't mess with iterators if it was already
	gimple.
	(gimplify_cond_expr): Remove a COND_EXPR with two empty arms.
	(gimplify_call_expr): Try to simplify a builtin again after 
	gimplifying the args.
	(internal_get_tmp_var): Gimplify the new MODIFY_EXPR.
	(gimplify_expr, gimple_push_cleanup): Use boolean_false_node.
	(gimplify_init_constructor): New fn, broken out from...
	(gimplify_modify_expr): ...here.  Be smarter about zero-initialization.
	* tree-simple.c (is_gimple_rhs): Accept any CONSTRUCTOR.
	* tree-simple.h: Adjust add_tree prototype.
	* expr.c (mostly_zeros_p): No longer static.
	* tree.h: Declare it.
	* stmt.c (resolve_asm_operand_names): Don't copy the pattern
	unless we need to do substitutions.

*** expr.c.~1~	2003-07-30 14:20:42.000000000 -0400
--- expr.c	2003-07-24 19:29:55.000000000 -0400
*************** static tree clear_storage_libcall_fn (in
*** 151,157 ****
  static rtx compress_float_constant (rtx, rtx);
  static rtx get_subtarget (rtx);
  static int is_zeros_p (tree);
- static int mostly_zeros_p (tree);
  static void store_constructor_field (rtx, unsigned HOST_WIDE_INT,
  				     HOST_WIDE_INT, enum machine_mode,
  				     tree, tree, int, int);
--- 151,156 ----
*************** store_expr (tree exp, rtx target, int wa
*** 4771,4777 ****
      return target;
  }
  
! /* Return 1 if EXP just contains zeros.  */
  
  static int
  is_zeros_p (tree exp)
--- 4770,4776 ----
      return target;
  }
  
! /* Return 1 if EXP just contains zeros.  FIXME merge with initializer_zerop.  */
  
  static int
  is_zeros_p (tree exp)
*************** is_zeros_p (tree exp)
*** 4820,4826 ****
  
  /* Return 1 if EXP contains mostly (3/4)  zeros.  */
  
! static int
  mostly_zeros_p (tree exp)
  {
    if (TREE_CODE (exp) == CONSTRUCTOR)
--- 4819,4825 ----
  
  /* Return 1 if EXP contains mostly (3/4)  zeros.  */
  
! int
  mostly_zeros_p (tree exp)
  {
    if (TREE_CODE (exp) == CONSTRUCTOR)
*** gimplify.c.~1~	2003-07-30 14:20:42.000000000 -0400
--- gimplify.c	2003-07-30 14:07:46.000000000 -0400
*************** gimplify_expr (tree *expr_p, tree *pre_p
*** 350,369 ****
    /* Go ahead and strip type nops before we test our predicate.  */
    STRIP_MAIN_TYPE_NOPS (*expr_p);
  
!   /* Avoid gimplifying an expression that is already in gimple form
!      according to our predicate.
! 
!      Unfortunately the predicate is_gimple_stmt always returns
!      true, regardless of the structure of the underlying tree, so
!      if that is our predicate, then we bypass this test and
!      force gimplification of the expression.  FIXME, someone
!      should fix is_gimple_stmt.
! 
!      Actually, my (jason's) theory has been for gimplification to be
       idempotent, and for the predicates to only test for valid forms, not
!      whether they are fully simplified.  But we aren't there yet.  */
!   if (gimple_test_f != is_gimple_stmt && (*gimple_test_f) (*expr_p))
!     return 1;
  
    saved_input_filename = NULL;	/* [GIMPLE] Avoid uninitialized use warning.  */
    saved_lineno = -1;		/* [GIMPLE] Avoid uninitialized use warning.  */
--- 350,359 ----
    /* Go ahead and strip type nops before we test our predicate.  */
    STRIP_MAIN_TYPE_NOPS (*expr_p);
  
!   /* We used to check the predicate here and return immediately if it
!      succeeds.  This is wrong; the design is for gimplification to be
       idempotent, and for the predicates to only test for valid forms, not
!      whether they are fully simplified.  */
  
    saved_input_filename = NULL;	/* [GIMPLE] Avoid uninitialized use warning.  */
    saved_lineno = -1;		/* [GIMPLE] Avoid uninitialized use warning.  */
*************** gimplify_expr (tree *expr_p, tree *pre_p
*** 464,470 ****
  	case TRUTH_NOT_EXPR:
  	  tmp = gimple_boolify (TREE_OPERAND (*expr_p, 0));
  	  *expr_p = build (EQ_EXPR, TREE_TYPE (*expr_p), tmp,
! 			   convert (boolean_type_node, integer_zero_node));
  	  recalculate_side_effects (*expr_p);
  	  break;
  
--- 454,460 ----
  	case TRUTH_NOT_EXPR:
  	  tmp = gimple_boolify (TREE_OPERAND (*expr_p, 0));
  	  *expr_p = build (EQ_EXPR, TREE_TYPE (*expr_p), tmp,
! 			   boolean_false_node);
  	  recalculate_side_effects (*expr_p);
  	  break;
  
*************** gimplify_expr (tree *expr_p, tree *pre_p
*** 588,594 ****
  	  break;
  
  	case CONSTRUCTOR:
! 	  gimplify_constructor (*expr_p, pre_p, post_p);
  	  break;
  
  	  /* The following are special cases that are not handled by the
--- 578,587 ----
  	  break;
  
  	case CONSTRUCTOR:
! 	  if (gimple_test_f != is_gimple_rhs)
! 	    /* Don't reduce this yet if we're on the rhs of an assignment.
! 	       Let gimplify_init_constructor work its magic.  */
! 	    gimplify_constructor (*expr_p, pre_p, post_p);
  	  break;
  
  	  /* The following are special cases that are not handled by the
*************** gimplify_expr (tree *expr_p, tree *pre_p
*** 788,794 ****
        /* An rvalue will do.  Assign the gimplified expression into a new
  	 temporary TMP and replace the original expression with TMP.  */
  
!       if (internal_post)
  	/* The postqueue might change the value of the expression between
  	   the initialization and use of the temporary, so we can't use a
  	   formal temp.  FIXME do we care?  */
--- 781,787 ----
        /* An rvalue will do.  Assign the gimplified expression into a new
  	 temporary TMP and replace the original expression with TMP.  */
  
!       if (internal_post || (fallback & fb_lvalue))
  	/* The postqueue might change the value of the expression between
  	   the initialization and use of the temporary, so we can't use a
  	   formal temp.  FIXME do we care?  */
*************** gimplify_return_expr (tree stmt, tree *p
*** 951,961 ****
  	 can replace it with something else.  */
        gimplify_stmt (&ret_expr);
  
!       /* If there's still a MODIFY_EXPR of the RESULT_DECL after
! 	 gimplification, find it so we can put it in the RETURN_EXPR.  */
!       TREE_OPERAND (stmt, 0) = NULL_TREE;
!       if (result)
  	{
  	  tree ret = NULL_TREE;
  
  	  for (si = tsi_start (&ret_expr); !tsi_end_p (si); tsi_next (&si))
--- 944,958 ----
  	 can replace it with something else.  */
        gimplify_stmt (&ret_expr);
  
!       if (result == NULL_TREE)
! 	TREE_OPERAND (stmt, 0) = NULL_TREE;
!       else if (ret_expr == TREE_OPERAND (stmt, 0))
! 	/* It was already GIMPLE.  */
! 	return;
!       else
  	{
+ 	  /* If there's still a MODIFY_EXPR of the RESULT_DECL after
+ 	     gimplification, find it so we can put it in the RETURN_EXPR.  */
  	  tree ret = NULL_TREE;
  
  	  for (si = tsi_start (&ret_expr); !tsi_end_p (si); tsi_next (&si))
*************** gimplify_exit_expr (tree *expr_p)
*** 1132,1141 ****
    *expr_p = expr;
  }
  
! /* Gimplifies a CONSTRUCTOR node T.
! 
!    FIXME: Should dynamic initializations from a CONSTRUCTOR be broken
!    up into multiple assignments?  */
  
  static void
  gimplify_constructor (tree t, tree *pre_p, tree *post_p)
--- 1129,1135 ----
    *expr_p = expr;
  }
  
! /* Gimplifies a CONSTRUCTOR node at *EXPR_P.  */
  
  static void
  gimplify_constructor (tree t, tree *pre_p, tree *post_p)
*************** gimplify_constructor (tree t, tree *pre_
*** 1148,1153 ****
--- 1142,1235 ----
  		   is_gimple_constructor_elt, fb_rvalue);
  }
  
+ /* Break out elements of a constructor used as an initializer into separate
+    MODIFY_EXPRs.
+ 
+    Note that we still need to clear any elements that don't have explicit
+    initializers, so if not all elements are initialized we keep the
+    original MODIFY_EXPR, we just remove all of the constructor
+    elements.
+ 
+    FIXME should also handle vectors.  */
+ 
+ static int
+ gimplify_init_constructor (tree *expr_p, tree *pre_p, int want_value)
+ {
+   tree object = TREE_OPERAND (*expr_p, 0);
+   tree ctor = TREE_OPERAND (*expr_p, 1);
+   tree type = TREE_TYPE (ctor);
+ 
+   if (TREE_CODE (ctor) != CONSTRUCTOR)
+     return 0;
+ 
+   if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
+       || TREE_CODE (type) == QUAL_UNION_TYPE
+       || TREE_CODE (type) == ARRAY_TYPE)
+     {
+       tree elt_list = CONSTRUCTOR_ELTS (ctor);
+ 
+       if (elt_list)
+ 	{
+ 	  int cleared = 0;
+ 	  int len = list_length (elt_list);
+ 	  int i;
+ 
+ 	  if (mostly_zeros_p (ctor))
+ 	    cleared = 1;
+ 	  else if (TREE_CODE (type) == ARRAY_TYPE)
+ 	    {
+ 	      tree nelts = array_type_nelts (type);
+ 	      if (TREE_CODE (nelts) != INTEGER_CST
+ 		  || (unsigned)len != TREE_INT_CST_LOW (nelts)+1)
+ 		cleared = 1;
+ 	    }
+ 	  else if (len != fields_length (type))
+ 	    cleared = 1;
+ 
+ 	  if (cleared)
+ 	    {
+ 	      CONSTRUCTOR_ELTS (ctor) = NULL_TREE;
+ 	      add_tree (*expr_p, pre_p);
+ 	    }
+ 
+ 	  for (i = 0; elt_list; i++, elt_list = TREE_CHAIN (elt_list))
+ 	    {
+ 	      tree purpose, value, cref, init;
+ 
+ 	      purpose = TREE_PURPOSE (elt_list);
+ 	      value = TREE_VALUE (elt_list);
+ 
+ 	      if (cleared && initializer_zerop (value))
+ 		continue;
+ 
+ 	      if (TREE_CODE (type) == ARRAY_TYPE)
+ 		{
+ 		  tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (object)));
+ 		  cref = build (ARRAY_REF, type, object, build_int_2 (i, 0));
+ 		}
+ 	      else
+ 		{
+ 		  cref = build (COMPONENT_REF, TREE_TYPE (purpose), object, purpose);
+ 		}
+ 
+ 	      init = build (MODIFY_EXPR, TREE_TYPE (purpose), cref, value);
+ 	      /* Each member initialization is a full-expression.  */
+ 	      gimplify_stmt (&init);
+ 	      add_tree (init, pre_p);
+ 	    }
+ 	  if (want_value)
+ 	    *expr_p = object;
+ 	  else
+ 	    *expr_p = build_empty_stmt ();
+ 
+ 	  return 1;
+ 	}
+     }
+   else
+     gimplify_constructor (ctor, pre_p, NULL);
+   return 0;
+ }
+ 
  /*  Build an expression for the address of T.  Folds away INDIRECT_REF to
      avoid confusing the gimplify process.  */
  
*************** gimplify_call_expr (tree *expr_p, tree *
*** 1468,1474 ****
      }
  
    gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
! 		 is_gimple_id, fb_rvalue);
  
    if (PUSH_ARGS_REVERSED)
      TREE_OPERAND (*expr_p, 1) = nreverse (TREE_OPERAND (*expr_p, 1));
--- 1550,1556 ----
      }
  
    gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
! 		 is_gimple_val, fb_rvalue);
  
    if (PUSH_ARGS_REVERSED)
      TREE_OPERAND (*expr_p, 1) = nreverse (TREE_OPERAND (*expr_p, 1));
*************** gimplify_call_expr (tree *expr_p, tree *
*** 1477,1482 ****
--- 1559,1579 ----
    if (PUSH_ARGS_REVERSED)
      TREE_OPERAND (*expr_p, 1) = nreverse (TREE_OPERAND (*expr_p, 1));
  
+   /* Try this again in case gimplification exposed something.  */
+   if (decl && DECL_BUILT_IN (decl))
+     {
+       tree new = simplify_builtin (*expr_p, gimple_test_f == is_gimple_stmt);
+ 
+       if (new && new != *expr_p)
+ 	{
+ 	  /* There was a transformation of this call which computes the
+ 	     same value, but in a more efficient way.  Return and try
+ 	     again.  */
+ 	  *expr_p = new;
+ 	  return;
+ 	}
+     }
+ 
    /* If the function is "const", then clear TREE_SIDE_EFFECTS on its
       decl.  This allows us to eliminate redundant or useless
       calls to "const" functions.  */
*************** gimplify_cond_expr (tree *expr_p, tree *
*** 1766,1780 ****
    /* Make sure the condition has BOOLEAN_TYPE.  */
    TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
  
-   /* Rewrite "if (a); else b" to "if (!a) b"  */
-   if (!TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
-     {
-       TREE_OPERAND (expr, 0) = invert_truthvalue (TREE_OPERAND (expr, 0));
-       tmp = TREE_OPERAND (expr, 1);
-       TREE_OPERAND (expr, 1) = TREE_OPERAND (expr, 2);
-       TREE_OPERAND (expr, 2) = tmp;
-     }
- 
    /* Break apart && and || conditions.  */
    if (TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ANDIF_EXPR
        || TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ORIF_EXPR)
--- 1863,1868 ----
*************** gimplify_cond_expr (tree *expr_p, tree *
*** 1801,1806 ****
--- 1889,1911 ----
  
    gimple_pop_condition (pre_p);
  
+   if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
+     /* OK */;
+   else if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 2)))
+     /* Rewrite "if (a); else b" to "if (!a) b"  */
+     {
+       TREE_OPERAND (expr, 0) = invert_truthvalue (TREE_OPERAND (expr, 0));
+       gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL,
+ 		     is_gimple_condexpr, fb_rvalue);
+ 
+       tmp = TREE_OPERAND (expr, 1);
+       TREE_OPERAND (expr, 1) = TREE_OPERAND (expr, 2);
+       TREE_OPERAND (expr, 2) = tmp;
+     }
+   else
+     /* Both arms are empty; replace the COND_EXPR with its predicate.  */
+     *expr_p = TREE_OPERAND (expr, 0);
+ 
    *expr_p = expr;
  }
  
*************** gimplify_modify_expr (tree *expr_p, tree
*** 1820,1827 ****
  {
    tree *from_p = &TREE_OPERAND (*expr_p, 1);
    tree *to_p = &TREE_OPERAND (*expr_p, 0);
-   tree type = TREE_TYPE (*to_p);
-   int (*pred) (tree);
  
  #if defined ENABLE_CHECKING
    if (TREE_CODE (*expr_p) != MODIFY_EXPR
--- 1925,1930 ----
*************** gimplify_modify_expr (tree *expr_p, tree
*** 1857,1907 ****
    if (TREE_CODE (*expr_p) == INIT_EXPR)
      TREE_SET_CODE (*expr_p, MODIFY_EXPR);
  
!   /* Break out elements of a constructor into separate MODIFY_EXPRs.  FIXME
!      should also handle vectors.
! 
!      Note that we still need to clear any elements that don't have explicit
!      initializers, so we keep the original MODIFY_EXPR, we just remove all
!      of the constructor elements.  FIXME should try to avoid clearing
!      initialized elts, a la store_constructor.  */
!   if (TREE_CODE (*from_p) == CONSTRUCTOR
!       && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
! 	  || TREE_CODE (type) == QUAL_UNION_TYPE
! 	  || TREE_CODE (type) == ARRAY_TYPE))
!     {
!       tree elt_list = CONSTRUCTOR_ELTS (*from_p);
!       int i;
! 
!       CONSTRUCTOR_ELTS (*from_p) = NULL_TREE;
!       add_tree (*expr_p, pre_p);
! 
!       for (i = 0; elt_list; i++, elt_list = TREE_CHAIN (elt_list))
! 	{
! 	  tree purpose, value, cref, init;
! 
! 	  purpose = TREE_PURPOSE (elt_list);
! 	  value = TREE_VALUE (elt_list);
! 
! 	  if (TREE_CODE (type) == ARRAY_TYPE)
! 	    {
! 	      tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (*to_p)));
! 	      cref = build (ARRAY_REF, type, *to_p, build_int_2 (i, 0));
! 	    }
! 	  else
! 	    {
! 	      cref = build (COMPONENT_REF, TREE_TYPE (purpose), *to_p, purpose);
! 	    }
  
! 	  init = build (MODIFY_EXPR, TREE_TYPE (purpose), cref, value);
! 	  gimplify_stmt (&init);
! 	  add_tree (init, pre_p);
! 	}
!       if (want_value)
! 	*expr_p = *to_p;
!       else
! 	*expr_p = build_empty_stmt ();
!       return;
!     }
  
    /* If the RHS of the MODIFY_EXPR may throw or make a nonlocal goto and
       the LHS is a user variable, then we need to introduce a temporary.
--- 1960,1969 ----
    if (TREE_CODE (*expr_p) == INIT_EXPR)
      TREE_SET_CODE (*expr_p, MODIFY_EXPR);
  
!   gimplify_expr (from_p, pre_p, post_p, is_gimple_rhs, fb_rvalue);
  
!   if (gimplify_init_constructor (expr_p, pre_p, want_value))
!     return;
  
    /* If the RHS of the MODIFY_EXPR may throw or make a nonlocal goto and
       the LHS is a user variable, then we need to introduce a temporary.
*************** gimplify_modify_expr (tree *expr_p, tree
*** 1916,1926 ****
  	   && ((flag_exceptions && ! (call_expr_flags (*from_p) & ECF_NOTHROW))
  	       || FUNCTION_RECEIVES_NONLOCAL_GOTO (current_function_decl)))
  	  || (flag_non_call_exceptions && could_trap_p (*from_p))))
!     pred = is_gimple_val;
!   else
!     pred = is_gimple_rhs;
! 
!   gimplify_expr (from_p, pre_p, post_p, pred, fb_rvalue);
  
    if (want_value)
      {
--- 1978,1984 ----
  	   && ((flag_exceptions && ! (call_expr_flags (*from_p) & ECF_NOTHROW))
  	       || FUNCTION_RECEIVES_NONLOCAL_GOTO (current_function_decl)))
  	  || (flag_non_call_exceptions && could_trap_p (*from_p))))
!     gimplify_expr (from_p, pre_p, post_p, is_gimple_val, fb_rvalue);
  
    if (want_value)
      {
*************** annotate_all_with_file_line (tree *stmt_
*** 2205,2213 ****
  static tree
  add_stmt_to_compound (tree existing, tree stmt)
  {
    if (!stmt || !TREE_SIDE_EFFECTS (stmt))
      return existing;
!   else if (existing)
      return build (COMPOUND_EXPR, void_type_node, existing, stmt);
    else
      return stmt;
--- 2263,2274 ----
  static tree
  add_stmt_to_compound (tree existing, tree stmt)
  {
+   /* If we previously had nothing, allow an empty statement.  */
+   if (!existing && stmt && IS_EMPTY_STMT (stmt))
+     return stmt;
    if (!stmt || !TREE_SIDE_EFFECTS (stmt))
      return existing;
!   else if (existing && TREE_SIDE_EFFECTS (existing))
      return build (COMPOUND_EXPR, void_type_node, existing, stmt);
    else
      return stmt;
*************** add_stmt_to_compound (tree existing, tre
*** 2220,2233 ****
      Return the newly added list node or NULL_TREE if T was not added to
      LIST_P.  */
  
! tree
  add_tree (tree t, tree *list_p)
  {
-   if (t == NULL_TREE || !TREE_SIDE_EFFECTS (t))
-     return NULL_TREE;
- 
    *list_p = add_stmt_to_compound (*list_p, t);
-   return t;
  }
  
  
--- 2281,2290 ----
      Return the newly added list node or NULL_TREE if T was not added to
      LIST_P.  */
  
! void
  add_tree (tree t, tree *list_p)
  {
    *list_p = add_stmt_to_compound (*list_p, t);
  }
  
  
*************** internal_get_tmp_var (tree val, tree *pr
*** 2474,2479 ****
--- 2531,2538 ----
      TREE_LOCUS (mod) = TREE_LOCUS (val);
    else
      annotate_with_file_line (mod, input_filename, input_line);
+   /* gimplify_modify_expr might want to reduce this further.  */
+   gimplify_stmt (&mod);
    add_tree (mod, pre_p);
  
    return t;
*************** gimple_push_cleanup (tree cleanup, tree 
*** 2778,2786 ****
  
        tree flag = create_tmp_var (boolean_type_node, "cleanup");
        tree ffalse = build (MODIFY_EXPR, void_type_node, flag,
! 			   convert (boolean_type_node, integer_zero_node));
        tree ftrue = build (MODIFY_EXPR, void_type_node, flag,
! 			  convert (boolean_type_node, integer_one_node));
        cleanup = build (COND_EXPR, void_type_node, flag, cleanup,
  		       build_empty_stmt ());
        wce = build (WITH_CLEANUP_EXPR, void_type_node, NULL_TREE,
--- 2837,2845 ----
  
        tree flag = create_tmp_var (boolean_type_node, "cleanup");
        tree ffalse = build (MODIFY_EXPR, void_type_node, flag,
! 			   boolean_false_node);
        tree ftrue = build (MODIFY_EXPR, void_type_node, flag,
! 			  boolean_true_node);
        cleanup = build (COND_EXPR, void_type_node, flag, cleanup,
  		       build_empty_stmt ());
        wce = build (WITH_CLEANUP_EXPR, void_type_node, NULL_TREE,
*** stmt.c.~1~	2003-07-30 14:20:42.000000000 -0400
--- stmt.c	2003-07-30 14:17:54.000000000 -0400
*************** resolve_asm_operand_names (tree string, 
*** 2065,2077 ****
  {
    char *buffer;
    char *p;
    tree t;
  
    /* Substitute [<name>] in input constraint strings.  There should be no
       named operands in output constraints.  */
    for (t = inputs; t ; t = TREE_CHAIN (t))
      {
!       const char *c = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
        if (strchr (c, '[') != NULL)
  	{
  	  p = buffer = xstrdup (c);
--- 2065,2078 ----
  {
    char *buffer;
    char *p;
+   const char *c;
    tree t;
  
    /* Substitute [<name>] in input constraint strings.  There should be no
       named operands in output constraints.  */
    for (t = inputs; t ; t = TREE_CHAIN (t))
      {
!       c = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
        if (strchr (c, '[') != NULL)
  	{
  	  p = buffer = xstrdup (c);
*************** resolve_asm_operand_names (tree string, 
*** 2083,2113 ****
  	}
      }
  
!   if (strchr (TREE_STRING_POINTER (string), '[') == NULL)
!     return string;
! 
!   /* Assume that we will not need extra space to perform the substitution.
!      This because we get to remove '[' and ']', which means we cannot have
!      a problem until we have more than 999 operands.  */
! 
!   p = buffer = xstrdup (TREE_STRING_POINTER (string));
!   while ((p = strchr (p, '%')) != NULL)
!     {
!       if (p[1] == '[')
! 	p += 1;
!       else if (ISALPHA (p[1]) && p[2] == '[')
! 	p += 2;
        else
  	{
! 	  p += 1;
  	  continue;
  	}
- 
-       p = resolve_operand_name_1 (p, outputs, inputs);
      }
  
!   string = build_string (strlen (buffer), buffer);
!   free (buffer);
  
    return string;
  }
--- 2084,2131 ----
  	}
      }
  
!   /* Now check for any needed substitutions in the template.  */
!   c = TREE_STRING_POINTER (string);
!   while ((c = strchr (c, '%')) != NULL)
!     {
!       if (c[1] == '[')
! 	break;
!       else if (ISALPHA (c[1]) && c[2] == '[')
! 	break;
        else
  	{
! 	  c += 1;
  	  continue;
  	}
      }
  
!   if (c)
!     {
!       /* OK, we need to make a copy so we can perform the substitutions.
! 	 Assume that we will not need extra space--we get to remove '['
! 	 and ']', which means we cannot have a problem until we have more
! 	 than 999 operands.  */
!       buffer = xstrdup (TREE_STRING_POINTER (string));
!       p = buffer + (c - TREE_STRING_POINTER (string));
!       
!       while ((p = strchr (p, '%')) != NULL)
! 	{
! 	  if (p[1] == '[')
! 	    p += 1;
! 	  else if (ISALPHA (p[1]) && p[2] == '[')
! 	    p += 2;
! 	  else
! 	    {
! 	      p += 1;
! 	      continue;
! 	    }
! 
! 	  p = resolve_operand_name_1 (p, outputs, inputs);
! 	}
! 
!       string = build_string (strlen (buffer), buffer);
!       free (buffer);
!     }
  
    return string;
  }
*** tree.h.~1~	2003-07-30 14:20:42.000000000 -0400
--- tree.h	2003-07-30 15:09:16.000000000 -0400
*************** extern int fields_length (tree);
*** 2795,2800 ****
--- 2795,2802 ----
  
  extern bool initializer_zerop (tree);
  
+ extern int mostly_zeros_p (tree);
+ 
  /* add_var_to_bind_expr (bind_expr, var) binds var to bind_expr.  */
  
  extern void add_var_to_bind_expr (tree, tree);
*** tree-simple.c.~1~	2003-07-30 14:20:42.000000000 -0400
--- tree-simple.c	2003-07-26 00:07:18.000000000 -0400
*************** is_gimple_rhs (tree t)
*** 263,268 ****
--- 263,273 ----
    if (t == NULL_TREE)
      return 1;
  
+   if (TREE_CODE (t) == CONSTRUCTOR)
+     /* Accept any sort of CONSTRUCTOR for now; we'll reduce it further in
+        gimplify_init_constructor.  */
+     return 1;
+ 
    return (is_gimple_binary_expr (t)
            || is_gimple_unary_expr (t));
  }
*** tree-simple.h.~1~	2003-07-30 14:20:42.000000000 -0400
--- tree-simple.h	2003-07-24 19:32:45.000000000 -0400
*************** typedef void foreach_stmt_fn (tree *);
*** 77,83 ****
  void foreach_stmt (tree *, foreach_stmt_fn *);
  
  /* FIXME this needs a better name.  */
! tree add_tree (tree, tree *);
  
  /* FIXME we should deduce this from the predicate.  */
  typedef enum fallback_t {
--- 77,83 ----
  void foreach_stmt (tree *, foreach_stmt_fn *);
  
  /* FIXME this needs a better name.  */
! void add_tree (tree, tree *);
  
  /* FIXME we should deduce this from the predicate.  */
  typedef enum fallback_t {

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