This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tuples] gimplify CALL_EXPR
- From: Diego Novillo <dnovillo at google dot com>
- To: gcc-patches at gcc dot gnu dot org, Aldy Hernandez <aldyh at redhat dot com>, Christopher Matthews <chrismatthews at google dot com>
- Date: Tue, 26 Jun 2007 15:45:04 -0400
- Subject: [tuples] gimplify CALL_EXPR
This patch adds the basics for getting GS_CALL generated. It converts
the various CALL_EXPRs found during libgcc builds, but we fail early
enough that it's still not possible to tell what's missing.
Will add a few more tests as I find bugs.
I removed the call to debug_gimple_seq in the gimplifier so that 'make
check-gcc RUNTESTFLAGS=gimple.exp'. Perhaps we should do this with
-fdump-tree-gimple-details. I'll add a check for TDF_DETAILS at the end
of gimplification.
We are currently failing gcc.dg/gimple/constructors.c. Aldy says it
works for him, so it must've been something I broke. I'll check it out.
2007-06-26 Diego Novillo <dnovillo@google.com>
* gimple-pretty-print.c (dump_gs_assign, dump_gs_return,
dump_gs_call): New functions.
(dump_gimple_stmt): Call them.
* gimple-ir.c (gs_build_call_1): Factor out of gs_build_call.
(gs_build_call): Call it.
(gs_build_call_vec): New function.
* gimple-ir.h (struct gimple_statement_call): Change type of
field 'nargs' to size_t. Update all users.
(gs_build_call_vec): Declare.
(gs_call_set_fn): Remove.
(gs_call_set_nargs): Remove.
* gimplify.c: Include "vec.h"
(gimplify_return_expr): Fix formatting
(gimplify_call_expr): Call gs_build_call_vec.
(gimplify_expr): Do not try to test if NULL expressions
are in GIMPLE form.
(gimplify_function_tree): Do not call debug_gimple_seq.
* Makefile.in (gimplify.o): Include vec.h
testsuite/ChangeLog:
* testsuite/gcc.dg/gimple/gimple.exp: Use -O2.
Index: testsuite/gcc.dg/gimple/gimple.exp
===================================================================
--- testsuite/gcc.dg/gimple/gimple.exp (revision 126029)
+++ testsuite/gcc.dg/gimple/gimple.exp (working copy)
@@ -21,7 +21,7 @@ load_lib gcc-dg.exp
# If a testcase doesn't have special options, use these.
global DEFAULT_CFLAGS
if ![info exists DEFAULT_CFLAGS] then {
- set DEFAULT_CFLAGS " -ansi -pedantic-errors"
+ set DEFAULT_CFLAGS "-O2"
}
# Initialize `dg'.
Index: gimple-pretty-print.c
===================================================================
--- gimple-pretty-print.c (revision 126029)
+++ gimple-pretty-print.c (working copy)
@@ -92,6 +92,88 @@ print_gimple_stmt (FILE *file, gimple g,
pp_flush (&buffer);
}
+
+/* Dump the gimple assignment GS. BUFFER, SPC and FLAGS are as in
+ dump_gimple_stmt. */
+
+static void
+dump_gs_assign (pretty_printer *buffer, gimple gs, int spc, int flags)
+{
+ enum gimple_statement_structure_enum gss;
+
+ dump_generic_node (buffer, gs_assign_lhs (gs), spc, flags, false);
+ pp_space (buffer);
+ pp_character (buffer, '=');
+ pp_space (buffer);
+
+ gss = gss_for_assign (GS_SUBCODE_FLAGS (gs));
+ switch (gss)
+ {
+ case GSS_ASSIGN_BINARY:
+ dump_generic_node (buffer, gs_assign_binary_rhs1 (gs), spc,
+ flags, false);
+ pp_space (buffer);
+ pp_string (buffer, op_symbol_code (GS_SUBCODE_FLAGS (gs)));
+ pp_space (buffer);
+ dump_generic_node (buffer, gs_assign_binary_rhs2 (gs), spc,
+ flags, false);
+ break;
+
+ case GSS_ASSIGN_UNARY_REG:
+ case GSS_ASSIGN_UNARY_MEM:
+ dump_generic_node (buffer, gs_assign_unary_rhs (gs), spc, flags, false);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+
+/* Dump the return statement GS. BUFFER, SPC and FLAGS are as in
+ dump_gimple_stmt. */
+
+static void
+dump_gs_return (pretty_printer *buffer, gimple gs, int spc, int flags)
+{
+ tree t;
+
+ pp_string (buffer, "return");
+ t = gs_return_retval (gs);
+ if (t)
+ {
+ pp_space (buffer);
+ if (TREE_CODE (t) == GIMPLE_MODIFY_STMT)
+ dump_generic_node (buffer, GIMPLE_STMT_OPERAND (t, 1),
+ spc, flags, false);
+ else
+ dump_generic_node (buffer, t, spc, flags, false);
+ }
+}
+
+
+/* Dump the call statement GS. BUFFER, SPC and FLAGS are as in
+ dump_gimple_stmt. */
+
+static void
+dump_gs_call (pretty_printer *buffer, gimple gs, int spc, int flags)
+{
+ size_t i;
+
+ dump_generic_node (buffer, gs_call_fn (gs), spc, flags, false);
+ pp_string (buffer, " (");
+
+ for (i = 0; i < gs_call_nargs (gs); i++)
+ {
+ dump_generic_node (buffer, gs_call_arg (gs, i), 0, flags, false);
+ if (i < gs_call_nargs (gs) - 1)
+ pp_string (buffer, ", ");
+ }
+
+ pp_string (buffer, ")");
+}
+
+
/* Dump the gimple statement GS on the pretty_printer BUFFER, SPC
spaces of indent. FLAGS specifies details to show in the dump (see
TDF_* in tree.h). */
@@ -99,64 +181,26 @@ print_gimple_stmt (FILE *file, gimple g,
void
dump_gimple_stmt (pretty_printer *buffer, gimple gs, int spc, int flags)
{
- tree t;
-
if (!gs)
return;
switch (GS_CODE (gs))
{
case GS_ASSIGN:
- {
- enum gimple_statement_structure_enum gss;
-
- dump_generic_node (buffer, gs_assign_lhs (gs), spc, flags,
- false);
- pp_space (buffer);
- pp_character (buffer, '=');
- pp_space (buffer);
-
- gss = gss_for_assign (GS_SUBCODE_FLAGS (gs));
- switch (gss)
- {
- case GSS_ASSIGN_BINARY:
- dump_generic_node (buffer, gs_assign_binary_rhs1 (gs), spc,
- flags, false);
- pp_space (buffer);
- pp_string (buffer, op_symbol_code (GS_SUBCODE_FLAGS (gs)));
- pp_space (buffer);
- dump_generic_node (buffer, gs_assign_binary_rhs2 (gs), spc,
- flags, false);
- break;
- case GSS_ASSIGN_UNARY_REG:
- case GSS_ASSIGN_UNARY_MEM:
- dump_generic_node (buffer, gs_assign_unary_rhs (gs), spc,
- flags, false);
- break;
- default:
- gcc_unreachable ();
- }
+ dump_gs_assign (buffer, gs, spc, flags);
+ break;
- break;
- }
case GS_RETURN:
- pp_string (buffer, "return");
- t = gs_return_retval (gs);
- if (t)
- {
- pp_space (buffer);
- if (TREE_CODE (t) == GIMPLE_MODIFY_STMT)
- dump_generic_node (buffer, GIMPLE_STMT_OPERAND (t, 1),
- spc, flags, false);
- else
- dump_generic_node (buffer, t, spc, flags, false);
- }
+ dump_gs_return (buffer, gs, spc, flags);
+ break;
+
+ case GS_CALL:
+ dump_gs_call (buffer, gs, spc, flags);
break;
default:
GS_NIY;
}
- pp_semicolon (buffer);
pp_write_text_to_stream (buffer);
}
Index: gimple-ir.c
===================================================================
--- gimple-ir.c (revision 126029)
+++ gimple-ir.c (working copy)
@@ -53,33 +53,60 @@ gs_build_return (bool result_decl_p, tre
return p;
}
-/* Construct a GS_CALL statement.
+/* Helper for gs_build_call and gs_build_call_vec. Build the basic
+ components of a GS_CALL statement to function FN with NARGS
+ arguments. */
- FUNC is the function decl.
- NARGS is the number of arguments.
- The ... are the arguments. */
+static inline
+gimple gs_build_call_1 (tree fn, size_t nargs)
+{
+ gimple gs = ggc_alloc_cleared (sizeof (struct gimple_statement_call)
+ + sizeof (tree) * (nargs - 1));
+
+ GS_CODE (gs) = GS_CALL;
+ GS_SUBCODE_FLAGS (gs) = 0;
+ gs->gs_call.nargs = nargs;
+ gs->gs_call.fn = fn;
+
+ return gs;
+}
+
+
+/* Build a GS_CALL statement to function FN with the arguments
+ specified in vector ARGS. */
gimple
-gs_build_call (tree func, int nargs, ...)
+gs_build_call_vec (tree fn, VEC(tree, gc) *args)
{
- va_list ap;
- gimple p;
- int i;
+ size_t i;
+ size_t nargs = VEC_length (tree, args);
+ gimple call = gs_build_call_1 (fn, nargs);
- p = ggc_alloc_cleared (sizeof (struct gimple_statement_call)
- + sizeof (tree) * (nargs - 1));
+ for (i = 0; i < nargs; i++)
+ gs_call_set_arg (call, i, VEC_index (tree, args, i));
- GS_CODE (p) = GS_CALL;
- GS_SUBCODE_FLAGS (p) = 0;
- gs_call_set_nargs (p, nargs);
- gs_call_set_fn (p, func);
+ return call;
+}
+
+
+/* Build a GS_CALL statement to function FN. NARGS is the number of
+ arguments. The ... are the arguments. */
+
+gimple
+gs_build_call (tree fn, size_t nargs, ...)
+{
+ va_list ap;
+ gimple call;
+ size_t i;
+
+ call = gs_build_call_1 (fn, nargs);
va_start (ap, nargs);
- for (i = 0; i < nargs; ++i)
- gs_call_set_arg (p, i, va_arg (ap, tree));
+ for (i = 0; i < nargs; i++)
+ gs_call_set_arg (call, i, va_arg (ap, tree));
va_end (ap);
- return p;
+ return call;
}
/* Construct a GS_ASSIGN statement.
Index: gimple-ir.h
===================================================================
--- gimple-ir.h (revision 126029)
+++ gimple-ir.h (working copy)
@@ -39,7 +39,6 @@ enum gs_code {
&& GS_LOCUS ((G)).line == 0)
/* A sequences of gimple statements. */
-
struct gs_sequence
{
gimple first;
@@ -250,7 +249,7 @@ struct gimple_statement_call GTY(())
tree lhs;
tree fn;
tree chain;
- unsigned long nargs;
+ size_t nargs;
tree GTY ((length ("%h.nargs"))) args[1];
};
@@ -369,7 +368,8 @@ union gimple_statement_d GTY ((desc ("gi
extern gimple gs_build_return (bool, tree);
extern gimple gs_build_assign (tree, tree);
-extern gimple gs_build_call (tree, int, ...);
+extern gimple gs_build_call_vec (tree, VEC(tree, gc) *);
+extern gimple gs_build_call (tree, size_t, ...);
extern gimple gs_build_cond (enum gs_cond, tree, tree, tree, tree);
extern gimple gs_build_label (tree label);
extern gimple gs_build_goto (tree dest);
@@ -575,13 +575,6 @@ gs_call_fn (gimple gs)
return gs->gs_call.fn;
}
-static inline void
-gs_call_set_fn (gimple gs, tree fn)
-{
- GS_CHECK (gs, GS_CALL);
- gs->gs_call.fn = fn;
-}
-
static inline tree
gs_call_lhs (gimple gs)
{
@@ -617,13 +610,6 @@ gs_call_nargs (gimple gs)
return gs->gs_call.nargs;
}
-static inline void
-gs_call_set_nargs (gimple gs, unsigned long nargs)
-{
- GS_CHECK (gs, GS_CALL);
- gs->gs_call.nargs = nargs;
-}
-
static inline tree
gs_call_arg (gimple gs, int index)
{
Index: gimplify.c
===================================================================
--- gimplify.c (revision 126029)
+++ gimplify.c (working copy)
@@ -51,6 +51,7 @@ Software Foundation, 51 Franklin Street,
#include "pointer-set.h"
#include "splay-tree.h"
#include "gimple-ir.h"
+#include "vec.h"
enum gimplify_omp_var_data
@@ -1141,7 +1142,8 @@ gimplify_return_expr (tree stmt, gs_seq
tree ret_expr = TREE_OPERAND (stmt, 0);
tree result_decl, result;
- if (!ret_expr || TREE_CODE (ret_expr) == RESULT_DECL
+ if (!ret_expr
+ || TREE_CODE (ret_expr) == RESULT_DECL
|| ret_expr == error_mark_node)
{
gs_add (gs_build_return (TREE_CODE (ret_expr) == RESULT_DECL, ret_expr),
@@ -1206,6 +1208,7 @@ gimplify_return_expr (tree stmt, gs_seq
ret_expr = result;
else
ret_expr = build_gimple_modify_stmt (result_decl, result);
+
gs_add (gs_build_return (result == result_decl, ret_expr), pre_p);
return GS_ALL_DONE;
@@ -2067,6 +2070,7 @@ gimplify_call_expr (tree *expr_p, gs_seq
tree decl;
enum gimplify_status ret;
int i, nargs;
+ VEC(tree, gc) *args = NULL;
gcc_assert (TREE_CODE (*expr_p) == CALL_EXPR);
@@ -2140,6 +2144,8 @@ gimplify_call_expr (tree *expr_p, gs_seq
if (t == GS_ERROR)
ret = GS_ERROR;
+
+ VEC_safe_push (tree, gc, args, CALL_EXPR_ARG (*expr_p, i));
}
/* Try this again in case gimplification exposed something. */
@@ -2164,6 +2170,9 @@ gimplify_call_expr (tree *expr_p, gs_seq
&& (call_expr_flags (*expr_p) & (ECF_CONST | ECF_PURE)))
TREE_SIDE_EFFECTS (*expr_p) = 0;
+ gs_add (gs_build_call_vec (decl, args), pre_p);
+ *expr_p = NULL_TREE;
+
return ret;
}
@@ -5575,6 +5584,7 @@ gimplify_expr (tree *expr_p, gs_seq pre_
case CALL_EXPR:
ret = gimplify_call_expr (expr_p, pre_p, fallback != fb_none);
+
/* C99 code may assign to an array in a structure returned
from a function, and this has undefined behavior only on
execution, so create a temporary if an lvalue is
@@ -6093,7 +6103,6 @@ gimplify_expr (tree *expr_p, gs_seq pre_
/* EXPR_P should be a gimple statement, so the tree is meaningless;
do nothing with it. */
-
annotate_all_with_locus (pre_p, input_location);
goto out;
}
@@ -6136,7 +6145,8 @@ gimplify_expr (tree *expr_p, gs_seq pre_
/* If it's sufficiently simple already, we're done. Unless we are
handling some post-effects internally; if that's the case, we need to
copy into a temp before adding the post-effects to the tree. */
- if (gs_seq_empty_p (&internal_post) && (*gimple_test_f) (*expr_p))
+ if (gs_seq_empty_p (&internal_post)
+ && (*expr_p == NULL_TREE || (*gimple_test_f) (*expr_p)))
goto out;
/* Otherwise, we need to create a new temporary for the gimplified
@@ -6539,7 +6549,6 @@ gimplify_function_tree (tree fndecl)
gs_seq_init (&seq);
gimplify_body (&DECL_SAVED_TREE (fndecl), &seq, fndecl, true);
- debug_gimple_seq (&seq);
exit (0);
/* If we're instrumenting function entry/exit, then prepend the call to
Index: Makefile.in
===================================================================
--- Makefile.in (revision 126029)
+++ Makefile.in (working copy)
@@ -2146,7 +2146,7 @@ gimplify.o : gimplify.c $(CONFIG_H) $(SY
$(LANGHOOKS_DEF_H) $(TREE_FLOW_H) $(CGRAPH_H) $(TIMEVAR_H) $(TM_H) \
coretypes.h except.h $(FLAGS_H) $(RTL_H) $(FUNCTION_H) $(EXPR_H) output.h \
$(GGC_H) gt-gimplify.h $(HASHTAB_H) $(TARGET_H) toplev.h $(OPTABS_H) \
- $(REAL_H) $(SPLAY_TREE_H)
+ $(REAL_H) $(SPLAY_TREE_H) vec.h
gimple-low.o : gimple-low.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
$(DIAGNOSTIC_H) $(TREE_GIMPLE_H) $(TREE_INLINE_H) $(VARRAY_H) langhooks.h \
$(LANGHOOKS_DEF_H) $(TREE_FLOW_H) $(TIMEVAR_H) $(TM_H) coretypes.h \