[tree-ssa] Lowering of VLA's, second attempt

Zdenek Dvorak rakdver@atrey.karlin.mff.cuni.cz
Tue Aug 26 20:58:00 GMT 2003


Hello,

here is the second attempt.  STACK_ALLOC is builtin, no type changing
done.  Bootstrapped & regtested on i686.

Zdenek

	* builtins.c (expand_builtin): Handle STACK_ALLOC.
	* builtins.def (BUILT_IN_STACK_ALLOC): New.
	* c-simplify.c (gimplify_decl_stmt, c_gimplify_stmt,
	gimplify_compound_literal_expr): Arrange explicit stack allocation.
	* expr.c (expand_expr): Handle deferred variables.
	* stmt.c (expand_stack_alloc): New.
	* tree-simple.c (is_gimple_val): Prevent ADDR_EXPRs of vla's from
	being reduced.
	* tree.h (expand_stack_alloc): Declare.

Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.152.2.30
diff -c -3 -p -r1.152.2.30 builtins.c
*** builtins.c	20 Aug 2003 20:43:57 -0000	1.152.2.30
--- builtins.c	26 Aug 2003 17:49:47 -0000
*************** expand_builtin (tree exp, rtx target, rt
*** 5023,5028 ****
--- 5023,5033 ----
  	return target;
        break;
  
+     case BUILT_IN_STACK_ALLOC:
+       expand_stack_alloc (TREE_VALUE (arglist),
+ 			  TREE_VALUE (TREE_CHAIN (arglist)));
+       return NULL_RTX;
+ 
      case BUILT_IN_FFS:
      case BUILT_IN_FFSL:
      case BUILT_IN_FFSLL:
Index: builtins.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.def,v
retrieving revision 1.29.2.20
diff -c -3 -p -r1.29.2.20 builtins.def
*** builtins.def	20 Aug 2003 20:43:57 -0000	1.29.2.20
--- builtins.def	26 Aug 2003 17:49:48 -0000
*************** DEF_GCC_BUILTIN        (BUILT_IN_RETURN,
*** 317,322 ****
--- 317,323 ----
  DEF_GCC_BUILTIN        (BUILT_IN_RETURN_ADDRESS, "return_address", BT_FN_PTR_UNSIGNED, ATTR_NULL)
  DEF_GCC_BUILTIN        (BUILT_IN_SAVEREGS, "saveregs", BT_FN_PTR_VAR, ATTR_NULL)
  DEF_GCC_BUILTIN        (BUILT_IN_SETJMP, "setjmp", BT_FN_INT_PTR, ATTR_NULL)
+ DEF_GCC_BUILTIN        (BUILT_IN_STACK_ALLOC, "stack_alloc", BT_FN_VOID_PTR_SIZE, ATTR_NULL)
  DEF_GCC_BUILTIN        (BUILT_IN_STDARG_START, "stdarg_start", BT_FN_VOID_VALIST_REF_VAR, ATTR_NULL)
  DEF_EXT_LIB_BUILTIN    (BUILT_IN_STRFMON, "strfmon", BT_FN_SSIZE_STRING_SIZE_CONST_STRING_VAR, ATTR_FORMAT_STRFMON_3_4)
  DEF_LIB_BUILTIN        (BUILT_IN_STRFTIME, "strftime", BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_PTR, ATTR_FORMAT_STRFTIME_3_0)
Index: c-simplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/c-simplify.c,v
retrieving revision 1.1.4.68
diff -c -3 -p -r1.1.4.68 c-simplify.c
*** c-simplify.c	25 Aug 2003 20:52:18 -0000	1.1.4.68
--- c-simplify.c	26 Aug 2003 17:49:49 -0000
*************** Software Foundation, 59 Temple Place - S
*** 72,78 ****
  
  void c_gimplify_stmt (tree *);
  static void gimplify_expr_stmt (tree *);
! static void gimplify_decl_stmt (tree *, tree *);
  static void gimplify_for_stmt (tree *, tree *);
  static void gimplify_while_stmt (tree *);
  static void gimplify_do_stmt (tree *);
--- 72,78 ----
  
  void c_gimplify_stmt (tree *);
  static void gimplify_expr_stmt (tree *);
! static void gimplify_decl_stmt (tree *);
  static void gimplify_for_stmt (tree *, tree *);
  static void gimplify_while_stmt (tree *);
  static void gimplify_do_stmt (tree *);
*************** c_gimplify_stmt (tree *stmt_p)
*** 243,249 ****
  	  break;
  
  	case DECL_STMT:
! 	  gimplify_decl_stmt (&stmt, &next);
  	  break;
  
  	case LABEL_STMT:
--- 243,249 ----
  	  break;
  
  	case DECL_STMT:
! 	  gimplify_decl_stmt (&stmt);
  	  break;
  
  	case LABEL_STMT:
*************** mark_labels_r (tree *tp, int *walk_subtr
*** 812,818 ****
     different if the DECL_STMT is somehow embedded in an expression.  */
  
  static void
! gimplify_decl_stmt (tree *stmt_p, tree *next_p)
  {
    tree stmt = *stmt_p;
    tree decl = DECL_STMT_DECL (stmt);
--- 812,818 ----
     different if the DECL_STMT is somehow embedded in an expression.  */
  
  static void
! gimplify_decl_stmt (tree *stmt_p)
  {
    tree stmt = *stmt_p;
    tree decl = DECL_STMT_DECL (stmt);
*************** gimplify_decl_stmt (tree *stmt_p, tree *
*** 824,865 ****
  
        if (!TREE_CONSTANT (DECL_SIZE (decl)))
  	{
! 	  /* This is a variable-sized decl.  We need to wrap it in a new
! 	     block so that we can gimplify the expressions for calculating
! 	     its size, and so that any other local variables used in those
! 	     expressions will have been initialized.  */
! 
! 	  /* FIXME break the allocation out into a separate statement?  */
! 
! 	  tree usize = DECL_SIZE_UNIT (decl);
! 	  tree bind;
! 	  tree *p;
! 
! 	  usize = get_initialized_tmp_var (usize, &pre);
! 
! 	  /* Mark the unit size as being used in the VLA's declaration so
! 	     it will not be deleted by DCE.  */
! 	  set_has_hidden_use (usize);
! 
! 	  DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (TREE_TYPE (decl)) = usize;
! 
! 	  /* Prune this decl and any others after it out of the enclosing
! 	     block.  */
! 	  for (p = &BIND_EXPR_VARS (gimple_current_bind_expr ());
! 	       *p != decl; p = &TREE_CHAIN (*p))
! 	    /* search */;
! 	  *p = NULL_TREE;
! 	  if (BLOCK_VARS (BIND_EXPR_BLOCK (gimple_current_bind_expr ()))
! 	      == decl)
! 	    BLOCK_VARS (BIND_EXPR_BLOCK (gimple_current_bind_expr ()))
! 	      = NULL_TREE;
  
! 	  bind = c_build_bind_expr (decl, TREE_CHAIN (stmt));
  
! 	  add_tree (bind, &pre);
! 
! 	  if (next_p)
! 	    *next_p = NULL_TREE;
  	}
  
        if (init && init != error_mark_node)
--- 824,846 ----
  
        if (!TREE_CONSTANT (DECL_SIZE (decl)))
  	{
! 	  tree pt_type = build_pointer_type (TREE_TYPE (decl));
! 	  tree alloc;
  
! 	  /* This is a variable-sized decl.  Simplify its size and arrange
! 	     stack allocation.  */
  
! 	  DECL_SIZE_UNIT (decl)
! 	    = get_initialized_tmp_var (DECL_SIZE_UNIT (decl), &pre);
! 	  DECL_DEFER_OUTPUT (decl) = 1;
! 	  alloc = build_function_call_expr (
! 			implicit_built_in_decls[BUILT_IN_STACK_ALLOC],
! 			tree_cons (NULL_TREE,
! 				   build1 (ADDR_EXPR, pt_type, decl),
! 				   tree_cons (NULL_TREE,
! 					      DECL_SIZE_UNIT (decl),
! 					      NULL_TREE)));
! 	  add_tree (alloc, &pre);
  	}
  
        if (init && init != error_mark_node)
*************** gimplify_compound_literal_expr (tree *ex
*** 903,909 ****
    tree decl_s = COMPOUND_LITERAL_EXPR_DECL_STMT (*expr_p);
    tree decl = DECL_STMT_DECL (decl_s);
  
!   gimplify_decl_stmt (&decl_s, NULL);
    *expr_p = decl_s ? decl_s : decl;
  }
  
--- 884,890 ----
    tree decl_s = COMPOUND_LITERAL_EXPR_DECL_STMT (*expr_p);
    tree decl = DECL_STMT_DECL (decl_s);
  
!   gimplify_decl_stmt (&decl_s);
    *expr_p = decl_s ? decl_s : decl;
  }
  
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.467.2.44
diff -c -3 -p -r1.467.2.44 expr.c
*** expr.c	21 Aug 2003 07:44:56 -0000	1.467.2.44
--- expr.c	26 Aug 2003 17:50:34 -0000
*************** expand_expr (tree exp, rtx target, enum 
*** 7173,7178 ****
--- 7182,7198 ----
  
  	    if (DECL_EXTERNAL (var))
  	      continue;
+ 
+ 	    if (DECL_DEFER_OUTPUT (var))
+ 	      {
+ 		/* Prepare a mem & address for the decl.  */
+ 		rtx x = gen_rtx_MEM (DECL_MODE (var),
+ 				     gen_reg_rtx (Pmode));
+ 		set_mem_attributes (x, var, 1);
+ 		SET_DECL_RTL (var, x);
+ 
+ 		continue;
+ 	      }
  
  	    if (TREE_STATIC (var))
  	      /* If this is an inlined copy of a static local variable,
Index: stmt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stmt.c,v
retrieving revision 1.267.2.27
diff -c -3 -p -r1.267.2.27 stmt.c
*** stmt.c	20 Aug 2003 20:44:30 -0000	1.267.2.27
--- stmt.c	26 Aug 2003 17:51:24 -0000
*************** expand_decl (tree decl)
*** 4042,4047 ****
--- 4008,4058 ----
  #endif
        DECL_USER_ALIGN (decl) = 0;
      }
+ }
+ 
+ /* Emit code to allocate T_SIZE bytes of dynamic stack space for ALLOC.  */
+ void
+ expand_stack_alloc (tree alloc, tree t_size)
+ {
+   rtx address, dest, size;
+   tree var, type;
+ 
+   if (TREE_CODE (alloc) != ADDR_EXPR)
+     abort ();
+   var = TREE_OPERAND (alloc, 0);
+   if (TREE_CODE (var) != VAR_DECL)
+     abort ();
+ 
+   type = TREE_TYPE (var);
+ 
+   /* Record the stack pointer on entry to block, if have
+      not already done so.  */
+   do_pending_stack_adjust ();
+   save_stack_pointer ();
+ 
+   /* In function-at-a-time mode, variable_size doesn't expand this,
+      so do it now.  */
+   if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
+     expand_expr (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
+ 		 const0_rtx, VOIDmode, 0);
+ 
+   /* Compute the variable's size, in bytes.  */
+   size = expand_expr (t_size, NULL_RTX, VOIDmode, 0);
+   free_temp_slots ();
+ 
+   /* Allocate space on the stack for the variable.  */
+   address = XEXP (DECL_RTL (var), 0);
+   dest = allocate_dynamic_stack_space (size, address, TYPE_ALIGN (type));
+   if (dest != address)
+     emit_move_insn (address, dest);
+ 
+   /* Indicate the alignment we actually gave this variable.  */
+ #ifdef STACK_BOUNDARY
+   DECL_ALIGN (var) = STACK_BOUNDARY;
+ #else
+   DECL_ALIGN (var) = BIGGEST_ALIGNMENT;
+ #endif
+   DECL_USER_ALIGN (var) = 0;
  }
  
  /* Emit code to perform the initialization of a declaration DECL.  */
Index: tree-simple.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-simple.c,v
retrieving revision 1.1.4.51
diff -c -3 -p -r1.1.4.51 tree-simple.c
*** tree-simple.c	25 Aug 2003 20:52:18 -0000	1.1.4.51
--- tree-simple.c	26 Aug 2003 17:51:32 -0000
*************** is_gimple_val (tree t)
*** 472,477 ****
--- 472,485 ----
  	  ))
      return 1;
  
+   /* Allow address of vla, so that we do not replace it in the call_expr of
+      stack_alloc builtin.  */
+   if (TREE_CODE (t) == ADDR_EXPR
+       && TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL
+       && DECL_SIZE_UNIT (TREE_OPERAND (t, 0))
+       && !TREE_CONSTANT (DECL_SIZE_UNIT (TREE_OPERAND (t, 0))))
+     return 1;
+ 
    return (is_gimple_variable (t) || is_gimple_const (t));
  }
  
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.342.2.89
diff -c -3 -p -r1.342.2.89 tree.h
*** tree.h	21 Aug 2003 07:44:58 -0000	1.342.2.89
--- tree.h	26 Aug 2003 17:51:38 -0000
*************** extern int expand_exit_loop_if_false (st
*** 3064,3069 ****
--- 3064,3070 ----
  extern int expand_exit_loop_top_cond (struct nesting *, tree);
  extern int expand_exit_something (void);
  
+ extern void expand_stack_alloc (tree, tree);
  extern void expand_return (tree);
  extern int optimize_tail_recursion (tree, rtx);
  extern void expand_start_bindings_and_block (int, tree);



More information about the Gcc-patches mailing list