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]

[PATCH] Make CONSTRUCTOR use VEC


Hello,

this patch makes the CONSTRUCTOR node interally use a VEC to store the
initializers instead of a TREE_LIST. This is representation is highly memory
efficient, because each intializer only takes 2 pointers in memory (a
pointer
to the actual data, and a pointer to the index or field for the intializer).
Before, we used to have a TREE_NODE for each intializer, so wasting a whole
sizeof(tree_common) worth of memory per initializer.

CONSTRUCTOR is now a node of type 'x'. It used to be a node of type 'e' but
it
was not using this property that much (only operand 0 was used, and it was
the
TREE_LIST of initializers). Converting it to type 'x' was straightforward
and
easy.

build_constructor() now takes a type and a VEC, and I introduced a new
function
build_constructor_from_list(), which takes a type and a TREE_LIST (and
internally converts the TREE_LIST to the VEC). Frontends have been updated
in
two different ways:

- Wherever it was easy and safe, the frontend code was modified to directly
build a VEC to store the initializers, and call build_constructor().
- In all other cases, the frontend code still builds a TREE_LIST like it has
always done, and then calls build_constructor_from_list(). This is of course
inefficient memory-wise, but can be cleaned up with follow-up patches from
FE
maintainers.

I think this matches the criteria of incremental updates: if I had to modify
all the frontend to directly build VECs, the patch would be much much larger
(and I am not sure I would have finished it ever).

The only exception to this rule was the C++ frontend, where large parts had
to
be rewritten. Specifically, I rewrote from scratch reshape_init(),
digest_init() and process_init_constructor(), because these functions were
relying on polymorphisms between constructor lists and items in the lists
(the
argument tree was either a TREE_LIST representing a list of initializers, or
a
single initializer). This could not work anymore because a list of
initializer
is now a VEC which is not a tree. Anyway, the functions ended up being much
simpler (there was much duplicate code between reshape_init and digest_init
for
the case of aggregates).

Open issues:

- C++: split_non_constant_init_1() is now worst-case quadratic, because it
removes the non-constant elements from the middle of the VEC. I have a
couple
of solutions in mind (building up a list of all non-constant elements in a
bitmap and then remove them in a single linear-time operation; or merge
split_non_constant_init within process_init_constructor), but they were too
complex for this patch. I promise to take care of this in a followup patch.
Suggestions welcome.

- Fortran: gfc_conv_array_initializer() does weird things. I opened PR 22210
about it. I managed to keep the code regression-free but I am not totally
sure
what it is going on there, and there might be latent bugs. Steven B. said he
would take care of this.

This patch was bootstrapped with all languges (including ObjC++, Ada,
Treelang)
on x86-linux, and there were no regressions. OK for mainline? I think it
would
help if frontend maintainers could approve the various FE bits.

Giovanni Bajo



        Make CONSTRUCTOR use VEC to store initializers.
        * c-common.c (complete_array_type): Update to cope with VEC in
        CONSTRUCTOR_ELTS.
        * c-pretty-print.c (pp_c_initializer_list): Use
pp_c_constructor_elts.
        (pp_c_constructor_elts): New function.
        * c-pretty-print.h (pp_c_constructor_elts): Declare.
        * c-typeck.c (build_function_call, build_c_cast, digest_init,
        struct constructor_stack, struct initializer_stack,
        constructor_elements, push_init_level, pop_init_level,
add_pending_init,
        find_init_member, output_init_element): Update to cope with VEC in
        CONSTRUCTOR_ELTS.
        * coverage.c (build_fn_info_value, build_ctr_info_value,
        build_gcov_info): Likewise.
        * expr.c (categorize_ctor_elements_1, store_constructor,
        expand_expr_real_1): Likewise.
        * fold-const.c (fold_ternary): Likewise.
        * gimplify.c (gimplify_init_ctor_preeval, zero_sized_field_decl,
        gimplify_init_constructor, gimplify_expr): Likewise.
        * tree-dump.c (dequeue_and_dump): Likewise.
        * tree-inline.c (copy_tree_r): Add code to duplicate a CONSTRUCTOR
        node.
        * tree-pretty-print.c (dump_generic_node): Update to cope with VEC
in
        CONSTRUCTOR_ELTS.
        * tree-sra.c (generate_element_init_1): Likewise.
        * tree-ssa-ccp.c (fold_const_aggregate_ref): Likewise.
        * tree-ssa-operands.c (get_expr_operands): Likewise.
        * tree-vect-generic.c (expand_vector_piecewise): Likewise.
        * tree-vect-transform.c (vect_get_vec_def_for_operand):
        (get_initial_def_for_reduction): Likewise.
        * tree-vn.c (set_value_handle, get_value_handle): CONSTURCTOR uses
        value handle in annotations.
        * tree.c (tree_node_kind, tree_code_size, make_node_stat,
        tree_node_structure): Add support for constr_kind.
        (build_vector_from_ctor, build_constructor_single,
        build_constructor_from_list): New functions.
        (build_constructor): Update to take a VEC instead of a TREE_LIST.
        (simple_cst_equal, iterative_hash_expr, initializer_zerop,
walk_tree):
        Update to cope with VEC in CONSTRUCTOR_ELTS.
        * tree.def (CONSTRUCTOR): Make it a tcc_exceptional node.
        * tree.h (FOR_EACH_CONSTRUCTOR_VALUE, FOR_EACH_CONSTRUCTOR_ELT,
        CONSTRUCTOR_APPEND_ELT): New macros.
        (struct constructor_elt, struct tree_constructor): New data types.
        (enum tree_node_structure_enum): New TS_CONSTRUCTOR tree structure.
        (union tree_node): Add tree_constructor field.
        * varasm.c (const_hash_1, compare_constant, copy_constant,
        compute_reloc_for_constant, output_addressed_constants,
        initializer_constant_valid_p, output_constant,
        array_size_for_constructor, output_constructor): Update to cope with
        VEC in CONSTRUCTOR_ELTS.
        * vec.h (VEC_empty, VEC_copy): New macros.

ada/
        Make CONSTRUCTOR use VEC to store initializers.
        * decl.c (gnat_to_gnu_entity): Update to cope with VEC in
        CONSTRUCTOR_ELTS.
        * trans.c (extract_values): Likewise.
        * utils.c (convert, remove_conversions): Likewise.
        * utils2.c (contains_save_expr_p, build_binary_op, build_unary_op,
        gnat_build_constructor): Likewise.

cp/
        Make CONSTRUCTOR use VEC to store initializers.
        * call.c (convert_default_arg): Update call to digest_init.
        * class.c (dump_class_hierarchy, dump_array): Update to cope with
VEC
        in CONSTRUCTOR_ELTS.
        * cp-tree.h (EMPTY_CONSTRUCTOR_P): Likewise.
        (finish_compound_literal, digest_init): Update declaration.
        * decl.c (struct reshape_iter): New data type.
        (reshape_init_array): Rename to...
        (reshape_init_array_1): Update to cope with VEC in CONSTRUCTOR_ELTS.
        (reshape_init): Rewrite from scratch. Split parts into...
        (reshape_init_array, reshape_init_vector, reshape_init_class,
        reshape_init_r): New functions.
        (check_initializer): Update call to reshape_init. Remove obsolete
code.
        (initialize_artificial_var, cp_complete_array_type): Update to cope
        with VEC in CONSTRUCTOR_ELTS.
        * decl2.c (grokfield): Update calls to digest_init.
        (mark_vtable_entries): Update to cope with VEC in CONSTRUCTOR_ELTS.
        * error.c (dump_expr_init_vec): New function.
        (dump_expr): Use dump_expr_init_vec.
        * init.c (build_zero_init, build_vec_init): Update to cope with VEC
in
        CONSTRUCTOR_ELTS.
        (expand_default_init): Update call to digest_init.
        * parser.c  (cp_parser_postfix_expression): Use a VEC for the
        initializers.
        (cp_parser_initializer_list): Build a VEC of initializers.
        * pt.c (tsubst_copy, tsubst_copy_and_build): Update to cope with VEC
in
        CONSTRUCTOR_ELTS.
        * rtti.c (tinfo_base_init, generic_initializer, ptr_initializer,
        ptm_initializer, class_initializer, get_pseudo_ti_init): Use
        build_constructor_from_list instead of build_constructor.
        * semantics.c (finish_compound_literal): Update call to digest_init.
        * tree.c (stabilize_init): Update to cope with VEC in
CONSTRUCTOR_ELTS.
        * typeck.c (build_ptrmemfunc1): Likewise.
        * typeck2.c: (cxx_incomplete_type_error, split_nonconstant_init_1):
        Likewise.
        (store_init_value): Use build_constructor_from_list and update call
to
        digest_init.
        (digest_init): Rewrite.
        (process_init_constructor): Rewrite from scratch. Split into...
        (process_init_constructor_array, picflag_from_initializer,
        process_init_constructor_record, process_init_constructor_union):
New
        functions.
        (PICFLAG_ERRONEOUS, PICFLAG_NOT_ALL_CONSTANT,
PICFLAG_NOT_ALL_SIMPLE):
        New macros.
        (build_functional_cast): Use build_constructor_from_list instead of
        build_constructor.


fortran/
        Make CONSTRUCTOR use VEC to store initializers.
        * trans-array.c (gfc_build_null_descriptor,
        gfc_trans_array_constructor_value, gfc_conv_array_initializer):
        Update to cope with VEC in CONSTRUCTOR_ELTS.
        * trans-common.c (create_common): Likewise.
        * trans-expr.c (gfc_conv_structure): Likewise.
        * trans-stmt.c (gfc_trans_character_select): Use
        build_constructor_from_list instead of build_constructor.

java/
        Make CONSTRUCTOR use VEC to store initializers.
        * check-init.c (check_init): Update to cope with VEC in
        CONSTRUCTOR_ELTS.
        * class.c (make_field_value, make_method_value, get_dispatch_table,
        make_class_data, emit_symbol_table, emit_catch_table,
        emit_assertion_table): Use build_constructor_from_list instead of
        build_constructor.
        * constants.c (build_constants_constructor): Likewise.
        * java-gimplify.c (java_gimplify_new_array_init): Update to cope
with
        VEC in CONSTRUCTOR_ELTS.
        * java-tree.h (START_RECORD_CONSTRUCTOR, PUSH_SUPER_VALUE,
        PUSH_FIELD_VALUE, FINISH_RECORD_CONSTRUCTOR): Create a VEC instead
        of a TREE_LIST.
        * jcf-write.c (generate_bytecode_insns): Update to cope with VEC in
        CONSTRUCTOR_ELTS.
        * parse.y (build_new_array_init): Use build_constructor_from_list
        instead of build_constructor.
        (patch_new_array_init): Update to cope with VEC in
        CONSTRUCTOR_ELTS.
        (array_constructor_check_entry): Likewise.

objc/
        Make CONSTRUCTOR use VEC to store initializers.
        * objc-act.c (objc_build_constructor): Use
build_constructor_from_list
        instead of build_constructor.

testsuite/
        Make CONSTRUCTOR use VEC to store initializers.
        * g++.dg/ext/complit3.C: Check for specific error messages.
        * g++.dg/init/brace2.C: Update error message.
        * g++.dg/warn/Wbraces2.C: Likewise.

Attachment: patch-constructor-vec.txt.gz
Description: application/compressed


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