This is the mail archive of the 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][attn: fortran] propagate addresses of local variables

This was way more complicated than it should have been.

It's a mishmash of patches that both Diego and myself were working on.
When we discovered that we were working on the same thing, he kindly
dumped the whole lot off on me.  ;-)

I'll attempt to recreate the timeline of events leading to this monster:

(1) CCP, being a constant propagator, only wants to propagate constants.
    It quite sensibly used TREE_CONSTANT to find such things.

(2) Setting TREE_CONSTANT on addresses of local variables causes various
    bits of the compiler to think that it's valid to use them as static

    About half of this patch adds a new flag TREE_INVARIANT, which is a
    strict subset of TREE_CONSTANT which indicates that the value is
    constant across any one function frame.

(3) Next we modify the tree optimizers to use a new predicate
    gimple_min_invariant to determine what kinds of things are constants
    that should be propagated.

(4) Next we abort in get_expr_operands, because it's suddenly given all
    sorts of new constructs that it didn't know how to handle.

(5) Next we go back and make sure that all the optimizers fold expressions
    into which we have substituted constants.  This gets kind of interesting
    with things like *(&a + 8).  We actually fold this back to a[2], as
    appropriate for the type.

    This actually bootstraps and passes all the C tests.

(6) Next we discover than all fortran test cases fail.

    Fortran has, in my opinion, multiple problems with its types.

    The most promenant is that it generates ADDR_EXPR nodes where the
    type of the address is not a pointer to the addressed variable.
    I.e.  there's a missing NOP_EXPR.  I have, for the moment, hacked
    around this in the gimplifier, but this should be reverted.

    Second, the Fortran front end consistently un-biases its arrays,
    and flattens multi-dimensional arrays.  This confuses me.  I can
    guess that the reason behind this has to do with array slices
    somehow.  But really I don't think this should be happening for
    straightforward array usage.  Not for the least of reasons being
    that the debug info is going to be wrong, but also we no longer
    have the natural array accesses available for reblocking or
    vectorization or whatever.

(7) Finally, I go back and change the gimplifier and the folder to cope
    with arrays whose base index is not zero.

And after all that, there is still one fortran test regression.  It
turns out that the fortran front end is generating invalid code for
the SCALE intrinsic: clz is undefined for zero, and it isn't checking
for it.  Really I don't think this is something that the front end
should be expanding at all.  We should be invoking C99 scalbn, if known
to exist, and something in libgfortran if scalbn doesn't exist.  In
particular, various cpus may have tricks to accomplish this faster
than the expansion currently used.


2003-10-12  Richard Henderson  <>

        * tree.h (struct tree_common): Rename unused_1 to invariant_flag.
        (TREE_INVARIANT): New.
        * builtins.c (build_string_literal): Set TREE_INVARIANT.
        * c-common.c (fix_string_type): Likewise.
        * c-typeck.c (build_external_ref): Likewise.
        (build_c_cast, pop_init_level): Likewise.
        * fold-const.c (fold_convert, fold): Likewise.
        * tree.c (make_node, build_constructor): Likewise.
        (build, build1): Likewise.
        (staticp): Pass unknown component references to the language.
        (save_expr): Check TREE_INVARIANT instead of TREE_CONSTANT.
        (skip_simple_arithmetic): Likewise.
        (stabilize_reference_1): Likewise.
        * print-tree.c (print_node): Print TREE_INVARIANT.

        * c-common.c (pointer_int_sum): Rely on build to set TREE_CONSTANT.
        (finish_label_address_expr): Likewise.
        * c-typeck.c (default_function_array_conversion): Likewise.
        (parser_build_binary_op, pointer_diff): Likewise.
        (build_unary_op, build_binary_op): Likewise.
        * fold-const.c (non_lvalue): Likewise.

        * tree-pretty-print.c (dump_generic_node): Handle VIEW_CONVERT_EXPR.

        * call.c (call_builtin_trap): Use implicit_built_in_decls.
        * class.c (build_base_path): Set TREE_INVARIANT.
        (build_vtbl_ref_1, build_vtbl_initializer): Likewise.
        * decl.c (build_enumerator): Likewise.
        * init.c (build_zero_init): Likewise.
        * pt.c (push_inline_template_parms_recursive): Likewise.
        (build_template_parm_index, reduce_template_parm_level): Likewise.
        (process_template_parm): Likewise.
        * rtti.c (tinfo_base_init, generic_initializer): Likewise.
        (ptr_initializer, ptm_initializer, class_initializer): Likewise.
        * typeck.c (build_ptrmemfunc1): Likewise.
        * typeck2.c (process_init_constructor): Likewise.

        * calls.c (dfs_accumulate_vtbl_inits): Rely on build to set
        (build_vtbl_initializer): Likewise.
        * init.c (build_vtbl_address): Likewise.
        * rtti.c (tinfo_base_init): Likewise.
        * tree.c (make_ptrmem_cst): Likewise.
        * typeck.c (decay_conversion): Likewise.
        (get_member_function_from_ptrfunc, build_binary_op): Likewise.
        (pointer_diff, build_address, build_nop, build_unary_op): Likewise.

        * trans-array.c (gfc_trans_static_array_pointer): Set TREE_INVARIANT.
        (gfc_trans_array_constructor_value): Likewise.
        (gfc_conv_array_initializer): Likewise.
        * trans-stmt.c (gfc_trans_character_select): Likewise.

        * class.c (build_utf8_ref, get_dispatch_table): Set TREE_INVARIANT.
        (make_class_data, build_symbol_entry, emit_symbol_table): Likewise.
        * decl.c (java_init_decl_processing): Likewise.
        * except.c (prepare_eh_table_type): Likewise.
        * parse.y (patch_assignment, patch_binop): Likewise.
        (patch_string_cst, patch_new_array_init): Likewise.
        * resource.c (compile_resource_data): Likewise.

2003-10-12  Richard Henderson  <>
            Diego Novillo  <>

        * gimplify.c (gimplify_array_ref_to_plus): Subtract the array
        domain minimum index.
        (gimplify_addr_expr): Expand ARRAY_REFs.  Cope with Fortran
        missing cast wierdnesses.
        * tree-dfa.c (get_expr_operands): Handle (&v + c); abort on
        other address invariants that should have been folded.
        (vdefs_disappeared_p): New.
        (mark_new_vars_to_rename): Use it.  Move from ...
        * tree-ssa-dom.c: ... here.
        * tree-flow-inline.h (is_unchanging_value): Remove; use
        is_gimple_min_invariant everywhere instead.
        (phi_ssa_name_p): New.
        * tree-must-alias.c (find_addressable_vars): Process PHIs.
        * tree-simple.c (is_gimple_min_invariant): Rename from
        is_gimple_const; allow non-static variable addresses; update callers.
        (is_gimple_val): Remove ADDR_EXPR checks.
        * tree-simple.h: Update.
        * tree-ssa-ccp.c (replace_uses_in): Add replaced_address argument.
        (substitute_and_fold): Use that to mark_new_vars_to_rename.
        (fold_indirect_refs_r): New.
        (fold_stmt): Use it.  
        * tree-ssa-copyprop.c (copyprop_stmt): Call fold_stmt.
        * tree-ssa-dce.c (NECESSARY): Use asm_written_flag.
        (mark_necessary): Reject DECLs.
        * tree-ssa-live.c (register_ssa_partition): Use phi_ssa_name_p.
        * tree-ssa-pre.c (generate_expr_as_of_bb): Call fold_stmt if we
        replaced with constants.
        * tree-ssa.c (insert_copy_on_edge): Unwrap ADDR_EXPRs to set_is_used.
        (eliminate_build, coalesce_abnormal_edges, coalesce_vars): Use

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