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 volatile support


Most of this patch fixes volatile semantics on the tree-ssa branch:

Evaluating "i++ + 5" will only load from i once.
A statement consisting just of "i" will load from i.
A volatile variable is not a valid GIMPLE value; we need to copy it into a
 temporary before using it in an expression.  So a volatile reference can
 only appear as the full LHS or RHS of a MODIFY_EXPR, not as a
 subexpression.

This patch also changes the interaction of gimplify_return_expr and
gimplify_modify_expr: instead of suppressing use of the postqueue in
gimplify_modify_expr, gimplify_return_expr will look through the gimple
form to find the actual modification of the RESULT_DECL.  It's still not
especially elegant, but this should avoid a lot of gratuitous conflicts
caused by emitting an increment sooner than necessary.

Tested athlon-pc-linux-gnu, applied to tree-ssa.

2003-06-24  Jason Merrill  <jason@redhat.com>

	* gimplify.c (gimplify_self_mod_expr): Add want_value parm.
	For postfix ops, make sure it returns an rvalue.
	(gimplify_expr): Copy a volatile reference into a temp.
	(create_tmp_var): Require a complete type.
	(create_tmp_alias_var): Use TYPE_VOLATILE on types.
	* tree-simple.c (is_gimple_stmt): Flesh out a bit.
	(is_gimple_val): Don't allow volatiles.

	* c-simplify.c (gimplify_expr_stmt): Don't insert a null pointer.

	* gimplify.c (gimplify_return_expr): Search through the gimple
	form for the interesting MODIFY_EXPR.
	(gimplify_modify_expr): Don't suppress posteffects if want_value.

*** c-simplify.c.~1~	Tue Jun 17 13:19:19 2003
--- c-simplify.c	Wed Jun 25 00:34:19 2003
*************** gimplify_expr_stmt (stmt_p)
*** 484,491 ****
  	}
      }
  
!   if (stmts_are_full_exprs_p ())
      stmt = build1 (CLEANUP_POINT_EXPR, void_type_node, stmt);
    *stmt_p = stmt;
  }
  
--- 484,494 ----
  	}
      }
  
!   if (stmt == NULL_TREE)
!     stmt = build_empty_stmt ();
!   else if (stmts_are_full_exprs_p ())
      stmt = build1 (CLEANUP_POINT_EXPR, void_type_node, stmt);
+ 
    *stmt_p = stmt;
  }
  
*** gimplify.c.~1~	Mon Jun 23 15:55:30 2003
--- gimplify.c	Tue Jun 24 18:37:24 2003
*************** static void gimplify_modify_expr     PAR
*** 54,60 ****
  static void gimplify_compound_expr   PARAMS ((tree *, tree *));
  static void gimplify_save_expr       PARAMS ((tree *, tree *, tree *));
  static void gimplify_addr_expr       PARAMS ((tree *, tree *, tree *));
! static void gimplify_self_mod_expr   PARAMS ((tree *, tree *, tree *));
  static void gimplify_cond_expr       PARAMS ((tree *, tree *, tree));
  static void gimplify_boolean_expr    PARAMS ((tree *, tree *));
  static void gimplify_return_expr     PARAMS ((tree, tree *));
--- 54,60 ----
  static void gimplify_compound_expr   PARAMS ((tree *, tree *));
  static void gimplify_save_expr       PARAMS ((tree *, tree *, tree *));
  static void gimplify_addr_expr       PARAMS ((tree *, tree *, tree *));
! static void gimplify_self_mod_expr   PARAMS ((tree *, tree *, tree *, int));
  static void gimplify_cond_expr       PARAMS ((tree *, tree *, tree));
  static void gimplify_boolean_expr    PARAMS ((tree *, tree *));
  static void gimplify_return_expr     PARAMS ((tree, tree *));
*************** gimplify_expr (expr_p, pre_p, post_p, gi
*** 354,360 ****
       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.  */
    if (gimple_test_f != is_gimple_stmt && (*gimple_test_f) (*expr_p))
      return 1;
  
--- 354,364 ----
       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;
  
*************** gimplify_expr (expr_p, pre_p, post_p, gi
*** 408,414 ****
  	case POSTDECREMENT_EXPR:
  	case PREINCREMENT_EXPR:
  	case PREDECREMENT_EXPR:
! 	  gimplify_self_mod_expr (expr_p, pre_p, post_p);
  	  break;
  
  	case ARRAY_REF:
--- 412,418 ----
  	case POSTDECREMENT_EXPR:
  	case PREINCREMENT_EXPR:
  	case PREDECREMENT_EXPR:
! 	  gimplify_self_mod_expr (expr_p, pre_p, post_p, fallback != fb_none);
  	  break;
  
  	case ARRAY_REF:
*************** gimplify_expr (expr_p, pre_p, post_p, gi
*** 690,695 ****
--- 694,722 ----
    /* If we replaced *expr_p, gimplify again.  */
    while (*expr_p && *expr_p != save_expr);
  
+   if (fallback == fb_none && !is_gimple_stmt (*expr_p))
+     {
+       /* We aren't looking for a value, and we don't have a valid
+ 	 statement.  If it doesn't have side-effects, throw it away.  */
+       if (!TREE_SIDE_EFFECTS (*expr_p))
+ 	*expr_p = build_empty_stmt ();
+       else if (!TREE_THIS_VOLATILE (*expr_p))
+ 	/* We only handle volatiles here; anything else with side-effects
+ 	   must be converted to a valid statement before we get here.  */
+ 	abort ();
+       else if (COMPLETE_TYPE_P (TREE_TYPE (*expr_p)))
+ 	{
+ 	  /* Historically, the compiler has treated a bare
+ 	     reference to a volatile lvalue as forcing a load.  */
+ 	  tree tmp = create_tmp_var (TREE_TYPE (*expr_p), "vol");
+ 	  *expr_p = build (MODIFY_EXPR, TREE_TYPE (tmp), tmp, *expr_p);
+ 	}
+       else
+ 	/* We can't do anything useful with a volatile reference to
+ 	   incomplete type, so just throw it away.  */
+ 	*expr_p = build_empty_stmt ();
+     }
+ 
    /* If we are gimplifying at the statement level, we're done.  Tack
       everything together and replace the original statement with the
       gimplified form.  */
*************** gimplify_bind_expr (expr_p, pre_p)
*** 898,954 ****
     STMT should be stored.  */
  
  static void
! gimplify_return_expr (stmt, pre_p)
!      tree stmt;
!      tree *pre_p;
  {
    tree ret_expr = TREE_OPERAND (stmt, 0);
  
!   if (ret_expr)
      {
!       /* We need to pass the full MODIFY_EXPR down so that special handling
! 	 can replace it with something else.  FIXME this code is way too
! 	 complicated.  */
        if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
  	{
! 	  /* We are trying to return an expression in a void function; move
! 	     the expression to before the return.   Note that RET_EXPR
! 	     might be a POSTINCREMENT_EXPR or similar expression which
! 	     requires even more special handling.  Ugh.  */
! 	  gimplify_expr (&ret_expr, pre_p, NULL, is_gimple_stmt, fb_either);
! 	  add_tree (ret_expr, pre_p);
! 	  TREE_OPERAND (stmt, 0) = NULL_TREE;
! 	  return;
  	}
  
!       gimplify_expr (&ret_expr, pre_p, NULL, is_gimple_stmt, fb_none);
  
!       /* When compiling C++ code, RET_EXPR can be a RESULT_DECL, which
!          is a legitimate return value.  */
!       if (TREE_CODE (ret_expr) == RESULT_DECL)
! 	TREE_OPERAND (stmt, 0) = ret_expr;
!       else if (TREE_CODE (ret_expr) != MODIFY_EXPR)
  	{
! 	  /* We're returning a value that is not necessarily a bitwise
! 	     copy.  As in the previous case, move the expression to before
! 	     the return.  */
! 	  add_tree (ret_expr, pre_p);
! 	  TREE_OPERAND (stmt, 0) = NULL_TREE;
  	}
!       else
!         {
! 	  /* We want the RHS to be a value as that makes conversion
! 	     of TRY_FINALLY_EXPRs into TRY_CATCH_EXPRs gimple.  The
! 	     only RHS which needs special handling is CALL_EXPRs.
! 
! 	     Therefore, if the RHS is a CALL_EXPR, then gimplify the
! 	     RHS to a gimple_val.  Otherwise allow any gimple_rhs.  */
! 	  gimplify_expr (&TREE_OPERAND (ret_expr, 1), pre_p, NULL,
! 			 (TREE_CODE (TREE_OPERAND (ret_expr, 1)) == CALL_EXPR
! 			  ? is_gimple_val : is_gimple_rhs),
! 			 fb_rvalue);
! 	  TREE_OPERAND (stmt, 0) = ret_expr;
!         }
      }
  }
  
--- 925,996 ----
     STMT should be stored.  */
  
  static void
! gimplify_return_expr (tree stmt, tree *pre_p)
  {
    tree ret_expr = TREE_OPERAND (stmt, 0);
+   tree_stmt_iterator si;
  
!   if (ret_expr && TREE_CODE (ret_expr) != RESULT_DECL)
      {
!       tree result;
! 
        if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
+ 	result = NULL_TREE;
+       else
  	{
! 	  result = TREE_OPERAND (ret_expr, 0);
! #ifdef ENABLE_CHECKING
! 	  if ((TREE_CODE (ret_expr) != MODIFY_EXPR
! 	       && TREE_CODE (ret_expr) != INIT_EXPR)
! 	      || TREE_CODE (result) != RESULT_DECL)
! 	    abort ();
! #endif
  	}
  
!       /* We need to pass the full MODIFY_EXPR down so that special handling
! 	 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;
! 	  tree last = NULL_TREE;
! 
! 	  for (si = tsi_start (&ret_expr); !tsi_end_p (si); tsi_next (&si))
! 	    {
! 	      last = tsi_stmt (si);
! 	      if (TREE_CODE (last) == MODIFY_EXPR
! 		  && TREE_OPERAND (last, 0) == result)
! 		ret = last;
! 	      else if (ret)
! 		break;
! 	    }
! 
! 	  /* If there were posteffects after the MODIFY_EXPR, we need a
! 	     temporary.  We also copy the result of a CALL_EXPR into a
! 	     temporary; apparently this simplifies dealing with
! 	     TRY_FINALLY_EXPR somehow.  */
! 	  if (ret
! 	      && (ret != last
! 		  || TREE_CODE (TREE_OPERAND (ret, 1)) == CALL_EXPR))
! 	    {
! 	      tree tmp = create_tmp_var (TREE_TYPE (result), "retval");
! 	      TREE_OPERAND (ret, 0) = tmp;
! 	      ret = build (MODIFY_EXPR, TREE_TYPE (result), result, tmp);
! 	    }
! 
! 	  if (ret)
! 	    TREE_OPERAND (stmt, 0) = ret;
! 	  else
! 	    /* The return value must be set up some other way.  Just tell
! 	       expand_return that we're returning the RESULT_DECL.  */
! 	    TREE_OPERAND (stmt, 0) = result;
  	}
! 
!       add_tree (ret_expr, pre_p);
      }
  }
  
*************** gimplify_compound_lval (expr_p, pre_p, p
*** 1294,1309 ****
  	*EXPR_P should be stored.
  
      POST_P points to the list where side effects that must happen after
!         *EXPR_P should be stored.  */
  
  static void
! gimplify_self_mod_expr (expr_p, pre_p, post_p)
!      tree *expr_p;
!      tree *pre_p;
!      tree *post_p;
  {
    enum tree_code code;
    tree lhs, lvalue, rhs, t1;
  
    code = TREE_CODE (*expr_p);
  
--- 1336,1354 ----
  	*EXPR_P should be stored.
  
      POST_P points to the list where side effects that must happen after
!         *EXPR_P should be stored.
! 
!     WANT_VALUE is nonzero iff we want to use the value of this expression
!         in another expression.  */
  
  static void
! gimplify_self_mod_expr (tree *expr_p, tree *pre_p, tree *post_p,
! 			int want_value)
  {
    enum tree_code code;
    tree lhs, lvalue, rhs, t1;
+   bool postfix;
+   enum tree_code arith_code;
  
    code = TREE_CODE (*expr_p);
  
*************** gimplify_self_mod_expr (expr_p, pre_p, p
*** 1315,1362 ****
      abort ();
  #endif
  
    /* Gimplify the LHS into a GIMPLE lvalue.  */
    lvalue = TREE_OPERAND (*expr_p, 0);
    gimplify_expr (&lvalue, pre_p, post_p, is_gimple_modify_expr_lhs,
  		 fb_lvalue);
  
!   /* Extract the operands to the arithmetic operation, including an rvalue
!      version of our LHS.  */
    lhs = lvalue;
-   /* And reduce it to an ID.  */
-   gimplify_expr (&lhs, pre_p, post_p, is_gimple_id, fb_rvalue);
    rhs = TREE_OPERAND (*expr_p, 1);
-   gimplify_expr (&rhs, pre_p, post_p, is_gimple_val, fb_rvalue);
  
!   /* Determine whether we need to create a PLUS or a MINUS operation.  */
!   if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
!     t1 = build (PLUS_EXPR, TREE_TYPE (*expr_p), lhs, rhs);
!   else
!     t1 = build (MINUS_EXPR, TREE_TYPE (*expr_p), lhs, rhs);
! 
! #if defined ENABLE_CHECKING
!   if (!is_gimple_binary_expr (t1))
!     abort ();
! #endif
  
    t1 = build (MODIFY_EXPR, TREE_TYPE (lvalue), lvalue, t1);
-   if (TREE_LOCUS (*expr_p))
-     TREE_LOCUS (t1) = TREE_LOCUS (*expr_p);
-   else
-     annotate_with_file_line (t1, input_filename, input_line);
  
!   /* Determine whether the new assignment should go before or after
!      the gimplified expression.  */
!   if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
!     add_tree (t1, pre_p);
    else
!     add_tree (t1, post_p);
! 
!   /* Replace the original expression with the LHS of the assignment.  */
!   *expr_p = lvalue;
  }
  
- 
  /*  Gimplify the COMPONENT_REF node pointed by EXPR_P.
  
      PRE_P points to the list where side effects that must happen before
--- 1360,1407 ----
      abort ();
  #endif
  
+   /* Prefix or postfix?  */
+   if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
+     /* Faster to treat as prefix if result is not used.  */
+     postfix = want_value;
+   else
+     postfix = false;
+ 
+   /* Add or subtract?  */
+   if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
+     arith_code = PLUS_EXPR;
+   else
+     arith_code = MINUS_EXPR;
+ 
    /* Gimplify the LHS into a GIMPLE lvalue.  */
    lvalue = TREE_OPERAND (*expr_p, 0);
    gimplify_expr (&lvalue, pre_p, post_p, is_gimple_modify_expr_lhs,
  		 fb_lvalue);
  
!   /* Extract the operands to the arithmetic operation.  */
    lhs = lvalue;
    rhs = TREE_OPERAND (*expr_p, 1);
  
!   if (postfix)
!     /* We want to return the original value.  */
!     gimplify_expr (&lhs, pre_p, post_p, is_gimple_val, fb_rvalue);
  
+   t1 = build (arith_code, TREE_TYPE (*expr_p), lhs, rhs);
    t1 = build (MODIFY_EXPR, TREE_TYPE (lvalue), lvalue, t1);
  
!   if (postfix)
!     /* If this is a postfix operator, put the assignment in the postqueue
!        and replace the original expression with the (rvalue) LHS.  */
!     {
!       gimplify_stmt (&t1);
!       add_tree (t1, post_p);
!       *expr_p = lhs;
!     }
    else
!     /* Otherwise, just plug in the assignment and continue.  */
!     *expr_p = t1;
  }
  
  /*  Gimplify the COMPONENT_REF node pointed by EXPR_P.
  
      PRE_P points to the list where side effects that must happen before
*************** gimplify_cond_expr (expr_p, pre_p, targe
*** 1785,1802 ****
  	*EXPR_P should be stored.
  
      POST_P points to the list where side effects that must happen after
!         *EXPR_P should be stored.  */
  
  static void
! gimplify_modify_expr (expr_p, pre_p, post_p, want_value)
!      tree *expr_p;
!      tree *pre_p;
!      tree *post_p;
!      int want_value;
  {
    tree *from_p = &TREE_OPERAND (*expr_p, 1);
    tree *to_p = &TREE_OPERAND (*expr_p, 0);
    tree type = TREE_TYPE (*to_p);
    
  #if defined ENABLE_CHECKING
    if (TREE_CODE (*expr_p) != MODIFY_EXPR
--- 1830,1847 ----
  	*EXPR_P should be stored.
  
      POST_P points to the list where side effects that must happen after
!         *EXPR_P should be stored.
! 
!     WANT_VALUE is nonzero iff we want to use the value of this expression
!         in another expression.  */
  
  static void
! gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, int want_value)
  {
    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
*************** gimplify_modify_expr (expr_p, pre_p, pos
*** 1868,1886 ****
  	    }
  
  	  init = build (MODIFY_EXPR, TREE_TYPE (purpose), cref, value);
! 	  gimplify_expr (&init, pre_p, NULL, is_gimple_stmt, fb_none);
  	  add_tree (init, pre_p);
  	}
!       *expr_p = TREE_OPERAND (*expr_p, 0);
        return;
      }
  
-   /* If this is for a RETURN_EXPR, we can't have any posteffects.  */
-   if (!want_value)
-     post_p = NULL;
- 
-   gimplify_expr (from_p, pre_p, post_p, is_gimple_rhs, fb_rvalue);
- 
    /* If the RHS of the MODIFY_EXPR may throw and the LHS is a user
       variable, then we need to introduce a temporary.
       ie temp = RHS; LHS = temp.
--- 1913,1928 ----
  	    }
  
  	  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 and the LHS is a user
       variable, then we need to introduce a temporary.
       ie temp = RHS; LHS = temp.
*************** gimplify_modify_expr (expr_p, pre_p, pos
*** 1888,1908 ****
       This way the optimizers can determine that the user variable is
       only modified if evaluation of the RHS does not throw.
  
!      FIXME.  What to do about cases where the LHS can throw?  */
    if (flag_exceptions
        && ! (DECL_P (*to_p) && DECL_ARTIFICIAL (*to_p))
        && ((TREE_CODE (*from_p) == CALL_EXPR
  	   && ! (call_expr_flags (*from_p) & ECF_NOTHROW))
  	  || (flag_non_call_exceptions && could_trap_p (*from_p))))
!     {
!       tree tmp = get_initialized_tmp_var (*from_p, pre_p);
!       TREE_OPERAND (*expr_p, 1) = tmp;
!     }
  
    if (want_value)
      {
        add_tree (*expr_p, pre_p);
!       *expr_p = TREE_OPERAND (*expr_p, 0);
      }
  }
  
--- 1930,1951 ----
       This way the optimizers can determine that the user variable is
       only modified if evaluation of the RHS does not throw.
  
!      FIXME this should be handled by the is_gimple_rhs predicate.  */
    if (flag_exceptions
        && ! (DECL_P (*to_p) && DECL_ARTIFICIAL (*to_p))
        && ((TREE_CODE (*from_p) == CALL_EXPR
  	   && ! (call_expr_flags (*from_p) & ECF_NOTHROW))
  	  || (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)
      {
        add_tree (*expr_p, pre_p);
!       *expr_p = *to_p;
      }
  }
  
*************** create_tmp_var (type, prefix)
*** 2228,2233 ****
--- 2271,2278 ----
       frontend, something is wrong.  */
    if (TREE_CODE (type) == ARRAY_TYPE || TREE_ADDRESSABLE (type))
      abort ();
+   if (!COMPLETE_TYPE_P (type))
+     abort ();
  #endif
  
    /* Make the type of the variable writable.  */
*************** create_tmp_alias_var (type, prefix)
*** 2293,2299 ****
    DECL_CONTEXT (tmp_var) = current_function_decl;
    TREE_STATIC (tmp_var) = 0;
    TREE_USED (tmp_var) = 1;
!   TREE_THIS_VOLATILE (tmp_var) = TREE_THIS_VOLATILE (type);
  
  
    return tmp_var;
--- 2338,2344 ----
    DECL_CONTEXT (tmp_var) = current_function_decl;
    TREE_STATIC (tmp_var) = 0;
    TREE_USED (tmp_var) = 1;
!   TREE_THIS_VOLATILE (tmp_var) = TYPE_VOLATILE (type);
  
  
    return tmp_var;
*** tree-simple.c.~1~	Mon Jun 23 15:55:30 2003
--- tree-simple.c	Tue Jun 24 18:37:24 2003
*************** is_gimple_const (t)
*** 604,613 ****
  }
  
  int
! is_gimple_stmt (t)
!      tree t ATTRIBUTE_UNUSED;
  {
!   return 1;
  }
  
  /*  Return nonzero if T is a GIMPLE identifier.  */
--- 604,648 ----
  }
  
  int
! is_gimple_stmt (tree t)
  {
!   enum tree_code code = TREE_CODE (t);
!   char class = TREE_CODE_CLASS (code);
! 
!   if (IS_EMPTY_STMT (t))
!     return 1;
! 
!   switch (class)
!     {
!     case 'r':
!     case '1':
!     case '2':
!     case '<':
!     case 'd':
!     case 'c':
!       /* These should never appear at statement level.  */
!       return 0;
! 
!     case 'e':
!     case 's':
!       /* Might be OK.  */
!       break;
! 
!     default:
!       /* Not an expression?!?  */
!       abort ();
!     }
! 
!   switch (code)
!     {
!     case CALL_EXPR:
!     case MODIFY_EXPR:
!       return 1;
! 
!     default:
!       /* FIXME enumerate the acceptable codes and change this to 0.  */
!       return 1;
!     }
  }
  
  /*  Return nonzero if T is a GIMPLE identifier.  */
*************** is_gimple_id (t)
*** 643,654 ****
  /*  Return nonzero if T is an identifier or a constant.  */
  
  int
! is_gimple_val (t)
!      tree t;
  {
    if (t == NULL_TREE)
      return 1;
  
    return (is_gimple_id (t) || is_gimple_const (t));
  }
  
--- 678,693 ----
  /*  Return nonzero if T is an identifier or a constant.  */
  
  int
! is_gimple_val (tree t)
  {
    if (t == NULL_TREE)
      return 1;
  
+   /* A volatile decl or _REF is not a valid operand, because we can't reuse
+      it as needed.  We need to copy it into a temp first.  */
+   if (TREE_THIS_VOLATILE (t))
+     return 0;
+ 
    return (is_gimple_id (t) || is_gimple_const (t));
  }
  

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