This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa] Lowering of VLA's, second attempt
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);