mirror of git://gcc.gnu.org/git/gcc.git
re PR middle-end/42834 (memcpy folding overeager)
2010-07-01 Richard Guenther <rguenther@suse.de> PR middle-end/42834 PR middle-end/44468 * doc/gimple.texi (is_gimple_mem_ref_addr): Document. * doc/generic.texi (References to storage): Document MEM_REF. * tree-pretty-print.c (dump_generic_node): Handle MEM_REF. (print_call_name): Likewise. * tree.c (recompute_tree_invariant_for_addr_expr): Handle MEM_REF. (build_simple_mem_ref_loc): New function. (mem_ref_offset): Likewise. * tree.h (build_simple_mem_ref_loc): Declare. (build_simple_mem_ref): Define. (mem_ref_offset): Declare. * fold-const.c: Include tree-flow.h. (operand_equal_p): Handle MEM_REF. (build_fold_addr_expr_with_type_loc): Likewise. (fold_comparison): Likewise. (fold_unary_loc): Fold VIEW_CONVERT_EXPR <T1, MEM_REF <T2, ...>> to MEM_REF <T1, ...>. (fold_binary_loc): Fold MEM[&MEM[p, CST1], CST2] to MEM[p, CST1 + CST2], fold MEM[&a.b, CST2] to MEM[&a, offsetof (a, b) + CST2]. * tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Handle MEM_REF. (ptr_deref_may_alias_ref_p_1): Likewise. (ao_ref_base_alias_set): Properly differentiate base object for offset and TBAA. (ao_ref_init_from_ptr_and_size): Use MEM_REF. (indirect_ref_may_alias_decl_p): Handle MEM_REFs properly. (indirect_refs_may_alias_p): Likewise. (refs_may_alias_p_1): Likewise. Remove pointer SSA name def chasing code. (ref_maybe_used_by_call_p_1): Handle MEM_REF. (call_may_clobber_ref_p_1): Likewise. * dwarf2out.c (loc_list_from_tree): Handle MEM_REF. * expr.c (expand_assignment): Handle MEM_REF. (store_expr): Handle MEM_REFs from STRING_CSTs. (store_field): If expanding a MEM_REF of a non-addressable decl use bitfield operations. (get_inner_reference): Handle MEM_REF. (expand_expr_addr_expr_1): Likewise. (expand_expr_real_1): Likewise. * tree-eh.c (tree_could_trap_p): Handle MEM_REF. * alias.c (ao_ref_from_mem): Handle MEM_REF. (get_alias_set): Likewise. Properly handle VIEW_CONVERT_EXPRs. * tree-data-ref.c (dr_analyze_innermost): Handle MEM_REF. (dr_analyze_indices): Likewise. (dr_analyze_alias): Likewise. (object_address_invariant_in_loop_p): Likewise. * gimplify.c (mark_addressable): Handle MEM_REF. (gimplify_cond_expr): Build MEM_REFs. (gimplify_modify_expr_to_memcpy): Likewise. (gimplify_init_ctor_preeval_1): Handle MEM_REF. (gimple_fold_indirect_ref): Adjust. (gimplify_expr): Handle MEM_REF. Gimplify INDIRECT_REF to MEM_REF. * tree.def (MEM_REF): New tree code. * tree-dfa.c: Include toplev.h. (get_ref_base_and_extent): Handle MEM_REF. (get_addr_base_and_unit_offset): New function. * emit-rtl.c (set_mem_attributes_minus_bitpos): Handle MEM_REF. * gimple-fold.c (may_propagate_address_into_dereference): Handle MEM_REF. (maybe_fold_offset_to_array_ref): Allow possibly out-of bounds accesses if the array has just one dimension. Remove always true parameter. Do not require type compatibility here. (maybe_fold_offset_to_component_ref): Remove. (maybe_fold_stmt_indirect): Remove. (maybe_fold_reference): Remove INDIRECT_REF handling. Fold back to non-MEM_REF. (maybe_fold_offset_to_address): Simplify. Deal with type mismatches here. (maybe_fold_reference): Likewise. (maybe_fold_stmt_addition): Likewise. Also handle &ARRAY + I in addition to &ARRAY[0] + I. (fold_gimple_assign): Handle ADDR_EXPR of MEM_REFs. (gimple_get_relevant_ref_binfo): Handle MEM_REF. * cfgexpand.c (expand_debug_expr): Handle MEM_REF. * tree-ssa.c (useless_type_conversion_p): Make most pointer conversions useless. (warn_uninitialized_var): Handle MEM_REF. (maybe_rewrite_mem_ref_base): New function. (execute_update_addresses_taken): Implement re-writing of MEM_REFs to SSA form. * tree-inline.c (remap_gimple_op_r): Handle MEM_REF, remove INDIRECT_REF handling. (copy_tree_body_r): Handle MEM_REF. * gimple.c (is_gimple_addressable): Adjust. (is_gimple_address): Likewise. (is_gimple_invariant_address): ADDR_EXPRs of MEM_REFs with invariant base are invariant. (is_gimple_min_lval): Adjust. (is_gimple_mem_ref_addr): New function. (get_base_address): Handle MEM_REF. (count_ptr_derefs): Likewise. (get_base_loadstore): Likewise. * gimple.h (is_gimple_mem_ref_addr): Declare. (gimple_call_fndecl): Handle invariant MEM_REF addresses. * tree-cfg.c (verify_address): New function, split out from ... (verify_expr): ... here. Use for verifying ADDR_EXPRs and the address operand of MEM_REFs. Verify MEM_REFs. Reject INDIRECT_REFs. (verify_types_in_gimple_min_lval): Handle MEM_REF. Disallow INDIRECT_REF. Allow conversions. (verify_types_in_gimple_reference): Verify VIEW_CONVERT_EXPR of a register does not change its size. (verify_types_in_gimple_reference): Verify MEM_REF. (verify_gimple_assign_single): Disallow INDIRECT_REF. Handle MEM_REF. * tree-ssa-operands.c (opf_non_addressable, opf_not_non_addressable): New. (mark_address_taken): Handle MEM_REF. (get_indirect_ref_operands): Pass through opf_not_non_addressable. (get_asm_expr_operands): Pass opf_not_non_addressable. (get_expr_operands): Handle opf_[not_]non_addressable. Handle MEM_REF. Remove INDIRECT_REF handling. * tree-vrp.c: (check_array_ref): Handle MEM_REF. (search_for_addr_array): Likewise. (check_array_bounds): Likewise. (vrp_stmt_computes_nonzero): Adjust for MEM_REF. * tree-ssa-loop-im.c (for_each_index): Handle MEM_REF. (ref_always_accessed_p): Likewise. (gen_lsm_tmp_name): Likewise. Handle ADDR_EXPR. * tree-complex.c (extract_component): Do not handle INDIRECT_REF. Handle MEM_REF. * cgraphbuild.c (mark_load): Properly check for NULL result from get_base_address. (mark_store): Likewise. * tree-ssa-loop-niter.c (array_at_struct_end_p): Handle MEM_REF. * tree-loop-distribution.c (generate_builtin): Exchange INDIRECT_REF handling for MEM_REF. * tree-scalar-evolution.c (follow_ssa_edge_expr): Handle &MEM[ptr + CST] similar to POINTER_PLUS_EXPR. * builtins.c (stabilize_va_list_loc): Use the function ABI valist type if we couldn't canonicalize the argument type. Always dereference with the canonical va-list type. (maybe_emit_free_warning): Handle MEM_REF. (fold_builtin_memory_op): Simplify and handle MEM_REFs in folding memmove to memcpy. * builtins.c (fold_builtin_memory_op): Use ref-all types for all memcpy foldings. * omp-low.c (build_receiver_ref): Adjust for MEM_REF. (build_outer_var_ref): Likewise. (scan_omp_1_op): Likewise. (lower_rec_input_clauses): Likewise. (lower_lastprivate_clauses): Likewise. (lower_reduction_clauses): Likewise. (lower_copyprivate_clauses): Likewise. (expand_omp_atomic_pipeline): Likewise. (expand_omp_atomic_mutex): Likewise. (create_task_copyfn): Likewise. * tree-ssa-sccvn.c (copy_reference_ops_from_ref): Handle MEM_REF. Remove old union trick. Initialize constant offsets. (ao_ref_init_from_vn_reference): Likewise. Do not handle INDIRECT_REF. Init base_alias_set properly. (vn_reference_lookup_3): Replace INDIRECT_REF handling with MEM_REF. (vn_reference_fold_indirect): Adjust for MEM_REFs. (valueize_refs): Fold MEM_REFs. Re-evaluate constant offset for ARRAY_REFs. (may_insert): Remove. (visit_reference_op_load): Do not test may_insert. (run_scc_vn): Remove parameter, do not fiddle with may_insert. * tree-ssa-sccvn.h (struct vn_reference_op_struct): Add a field to store the constant offset this op applies. (run_scc_vn): Adjust prototype. * cgraphunit.c (thunk_adjust): Adjust for MEM_REF. * tree-ssa-ccp.c (ccp_fold): Replace INDIRECT_REF folding with MEM_REF. Propagate &foo + CST as &MEM[&foo, CST]. Do not bother about volatile qualifiers on pointers. (fold_const_aggregate_ref): Handle MEM_REF, do not handle INDIRECT_REF. * tree-ssa-loop-ivopts.c * tree-ssa-loop-ivopts.c (determine_base_object): Adjust for MEM_REF. (strip_offset_1): Likewise. (find_interesting_uses_address): Replace INDIRECT_REF handling with MEM_REF handling. (get_computation_cost_at): Likewise. * ipa-pure-const.c (check_op): Handle MEM_REF. * tree-stdarg.c (check_all_va_list_escapes): Adjust for MEM_REF. * tree-ssa-sink.c (is_hidden_global_store): Handle MEM_REF and constants. * ipa-inline.c (likely_eliminated_by_inlining_p): Handle MEM_REF. * tree-parloops.c (take_address_of): Adjust for MEM_REF. (eliminate_local_variables_1): Likewise. (create_call_for_reduction_1): Likewise. (create_loads_for_reductions): Likewise. (create_loads_and_stores_for_name): Likewise. * matrix-reorg.c (may_flatten_matrices_1): Sanitize. (ssa_accessed_in_tree): Handle MEM_REF. (ssa_accessed_in_assign_rhs): Likewise. (update_type_size): Likewise. (analyze_accesses_for_call_stmt): Likewise. (analyze_accesses_for_assign_stmt): Likewise. (transform_access_sites): Likewise. (transform_allocation_sites): Likewise. * tree-affine.c (tree_to_aff_combination): Handle MEM_REF. * tree-vect-data-refs.c (vect_create_addr_base_for_vector_ref): Do not handle INDIRECT_REF. * tree-ssa-phiopt.c (add_or_mark_expr): Handle MEM_REF. (cond_store_replacement): Likewise. * tree-ssa-pre.c (create_component_ref_by_pieces_1): Handle MEM_REF, no not handle INDIRECT_REFs. (insert_into_preds_of_block): Properly initialize avail. (phi_translate_1): Fold MEM_REFs. Re-evaluate constant offset for ARRAY_REFs. Properly handle reference lookups that require a bit re-interpretation. (can_PRE_operation): Do not handle INDIRECT_REF. Handle MEM_REF. * tree-sra.c * tree-sra.c (build_access_from_expr_1): Handle MEM_REF. (build_ref_for_offset_1): Remove. (build_ref_for_offset): Build MEM_REFs. (gate_intra_sra): Disable for now. (sra_ipa_modify_expr): Handle MEM_REF. (ipa_early_sra_gate): Disable for now. * tree-sra.c (create_access): Swap INDIRECT_REF handling for MEM_REF handling. (disqualify_base_of_expr): Likewise. (ptr_parm_has_direct_uses): Swap INDIRECT_REF handling for MEM_REF handling. (sra_ipa_modify_expr): Remove INDIRECT_REF handling. Use mem_ref_offset. Remove bogus folding. (build_access_from_expr_1): Properly handle MEM_REF for non IPA-SRA. (make_fancy_name_1): Add support for MEM_REF. * tree-predcom.c (ref_at_iteration): Handle MEM_REFs. * tree-mudflap.c (mf_xform_derefs_1): Adjust for MEM_REF. * ipa-prop.c (compute_complex_assign_jump_func): Handle MEM_REF. (compute_complex_ancestor_jump_func): Likewise. (ipa_analyze_virtual_call_uses): Likewise. * tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Replace INDIRECT_REF folding with more generalized MEM_REF folding. (tree_ssa_forward_propagate_single_use_vars): Adjust accordingly. (forward_propagate_addr_into_variable_array_index): Also handle &ARRAY + I in addition to &ARRAY[0] + I. * tree-ssa-dce.c (ref_may_be_aliased): Handle MEM_REF. * tree-ssa-ter.c (find_replaceable_in_bb): Avoid TER if that creates assignments with overlap. * tree-nested.c (get_static_chain): Adjust for MEM_REF. (get_frame_field): Likewise. (get_nonlocal_debug_decl): Likewise. (convert_nonlocal_reference_op): Likewise. (struct nesting_info): Add mem_refs pointer-set. (create_nesting_tree): Allocate it. (convert_local_reference_op): Insert to be folded mem-refs. (fold_mem_refs): New function. (finalize_nesting_tree_1): Perform defered folding of mem-refs (free_nesting_tree): Free the pointer-set. * tree-vect-stmts.c (vectorizable_store): Adjust for MEM_REF. (vectorizable_load): Likewise. * tree-ssa-phiprop.c (phiprop_insert_phi): Adjust for MEM_REF. (propagate_with_phi): Likewise. * tree-object-size.c (addr_object_size): Handle MEM_REFs instead of INDIRECT_REFs. (compute_object_offset): Handle MEM_REF. (plus_stmt_object_size): Handle MEM_REF. (collect_object_sizes_for): Dispatch to plus_stmt_object_size for &MEM_REF. * tree-flow.h (get_addr_base_and_unit_offset): Declare. (symbol_marked_for_renaming): Likewise. * Makefile.in (tree-dfa.o): Add $(TOPLEV_H). (fold-const.o): Add $(TREE_FLOW_H). * tree-ssa-structalias.c (get_constraint_for_1): Handle MEM_REF. (find_func_clobbers): Likewise. * ipa-struct-reorg.c (decompose_indirect_ref_acc): Handle MEM_REF. (decompose_access): Likewise. (replace_field_acc): Likewise. (replace_field_access_stmt): Likewise. (insert_new_var_in_stmt): Likewise. (get_stmt_accesses): Likewise. (reorg_structs_drive): Disable. * config/i386/i386.c (ix86_va_start): Adjust for MEM_REF. (ix86_canonical_va_list_type): Likewise. cp/ * cp-gimplify.c (cp_gimplify_expr): Open-code the rhs predicate we are looking for, allow non-gimplified INDIRECT_REFs. testsuite/ * gcc.c-torture/execute/20100316-1.c: New testcase. * gcc.c-torture/execute/pr44468.c: Likewise. * gcc.c-torture/compile/20100609-1.c: Likewise. * gcc.dg/volatile2.c: Adjust. * gcc.dg/plugin/selfassign.c: Likewise. * gcc.dg/pr36902.c: Likewise. * gcc.dg/tree-ssa/foldaddr-2.c: Remove. * gcc.dg/tree-ssa/foldaddr-3.c: Likewise. * gcc.dg/tree-ssa/forwprop-8.c: Adjust. * gcc.dg/tree-ssa/pr17141-1.c: Likewise. * gcc.dg/tree-ssa/ssa-fre-13.c: Likewise. * gcc.dg/tree-ssa/ssa-fre-14.c: Likewise. * gcc.dg/tree-ssa/ssa-ccp-21.c: Likewise. * gcc.dg/tree-ssa/pta-ptrarith-1.c: Likewise. * gcc.dg/tree-ssa/20030807-7.c: Likewise. * gcc.dg/tree-ssa/forwprop-10.c: Likewise. * gcc.dg/tree-ssa/ssa-fre-1.c: Likewise. * gcc.dg/tree-ssa/pta-ptrarith-2.c: Likewise. * gcc.dg/tree-ssa/ssa-ccp-23.c: Likewise. * gcc.dg/tree-ssa/forwprop-1.c: Likewise. * gcc.dg/tree-ssa/forwprop-2.c: Likewise. * gcc.dg/tree-ssa/struct-aliasing-1.c: Likewise. * gcc.dg/tree-ssa/ssa-ccp-25.c: Likewise. * gcc.dg/tree-ssa/ssa-pre-26.c: Likewise. * gcc.dg/tree-ssa/struct-aliasing-2.c: Likewise. * gcc.dg/tree-ssa/ssa-ccp-26.c: Likewise. * gcc.dg/tree-ssa/ssa-sccvn-4.c: Likewise. * gcc.dg/tree-ssa/ssa-pre-7.c: Likewise. * gcc.dg/tree-ssa/forwprop-5.c: Likewise. * gcc.dg/struct/w_prof_two_strs.c: XFAIL. * gcc.dg/struct/wo_prof_escape_arg_to_local.c: Likewise. * gcc.dg/struct/wo_prof_global_var.c: Likewise. * gcc.dg/struct/wo_prof_malloc_size_var.c: Likewise. * gcc.dg/struct/w_prof_local_array.c: Likewise. * gcc.dg/struct/w_prof_single_str_global.c: Likewise. * gcc.dg/struct/wo_prof_escape_str_init.c: Likewise. * gcc.dg/struct/wo_prof_array_through_pointer.c: Likewise. * gcc.dg/struct/w_prof_global_array.c: Likewise. * gcc.dg/struct/wo_prof_array_field.c: Likewise. * gcc.dg/struct/wo_prof_single_str_local.c: Likewise. * gcc.dg/struct/w_prof_local_var.c: Likewise. * gcc.dg/struct/wo_prof_two_strs.c: Likewise. * gcc.dg/struct/wo_prof_empty_str.c: Likewise. * gcc.dg/struct/wo_prof_local_array.c: Likewise. * gcc.dg/struct/w_prof_global_var.c: Likewise. * gcc.dg/struct/wo_prof_single_str_global.c: Likewise. * gcc.dg/struct/wo_prof_escape_substr_value.c: Likewise. * gcc.dg/struct/wo_prof_global_array.c: Likewise. * gcc.dg/struct/wo_prof_escape_return.c: Likewise. * gcc.dg/struct/wo_prof_escape_substr_array.c: Likewise. * gcc.dg/struct/wo_prof_double_malloc.c: Likewise. * gcc.dg/struct/w_ratio_cold_str.c: Likewise. * gcc.dg/struct/wo_prof_escape_substr_pointer.c: Likewise. * gcc.dg/struct/wo_prof_local_var.c: Likewise. * gcc.dg/tree-prof/stringop-1.c: Adjust. * g++.dg/tree-ssa/pr31146.C: Likewise. * g++.dg/tree-ssa/copyprop-1.C: Likewise. * g++.dg/tree-ssa/pr33604.C: Likewise. * g++.dg/plugin/selfassign.c: Likewise. * gfortran.dg/array_memcpy_3.f90: Likewise. * gfortran.dg/array_memcpy_4.f90: Likewise. * c-c++-common/torture/pr42834.c: New testcase. From-SVN: r161655
This commit is contained in:
parent
952b984e86
commit
70f348148c
272
gcc/ChangeLog
272
gcc/ChangeLog
|
|
@ -1,3 +1,275 @@
|
|||
2010-07-01 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/42834
|
||||
PR middle-end/44468
|
||||
* doc/gimple.texi (is_gimple_mem_ref_addr): Document.
|
||||
* doc/generic.texi (References to storage): Document MEM_REF.
|
||||
* tree-pretty-print.c (dump_generic_node): Handle MEM_REF.
|
||||
(print_call_name): Likewise.
|
||||
* tree.c (recompute_tree_invariant_for_addr_expr): Handle MEM_REF.
|
||||
(build_simple_mem_ref_loc): New function.
|
||||
(mem_ref_offset): Likewise.
|
||||
* tree.h (build_simple_mem_ref_loc): Declare.
|
||||
(build_simple_mem_ref): Define.
|
||||
(mem_ref_offset): Declare.
|
||||
* fold-const.c: Include tree-flow.h.
|
||||
(operand_equal_p): Handle MEM_REF.
|
||||
(build_fold_addr_expr_with_type_loc): Likewise.
|
||||
(fold_comparison): Likewise.
|
||||
(fold_unary_loc): Fold
|
||||
VIEW_CONVERT_EXPR <T1, MEM_REF <T2, ...>> to MEM_REF <T1, ...>.
|
||||
(fold_binary_loc): Fold MEM[&MEM[p, CST1], CST2] to MEM[p, CST1 + CST2],
|
||||
fold MEM[&a.b, CST2] to MEM[&a, offsetof (a, b) + CST2].
|
||||
* tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Handle MEM_REF.
|
||||
(ptr_deref_may_alias_ref_p_1): Likewise.
|
||||
(ao_ref_base_alias_set): Properly differentiate base object for
|
||||
offset and TBAA.
|
||||
(ao_ref_init_from_ptr_and_size): Use MEM_REF.
|
||||
(indirect_ref_may_alias_decl_p): Handle MEM_REFs properly.
|
||||
(indirect_refs_may_alias_p): Likewise.
|
||||
(refs_may_alias_p_1): Likewise. Remove pointer SSA name def
|
||||
chasing code.
|
||||
(ref_maybe_used_by_call_p_1): Handle MEM_REF.
|
||||
(call_may_clobber_ref_p_1): Likewise.
|
||||
* dwarf2out.c (loc_list_from_tree): Handle MEM_REF.
|
||||
* expr.c (expand_assignment): Handle MEM_REF.
|
||||
(store_expr): Handle MEM_REFs from STRING_CSTs.
|
||||
(store_field): If expanding a MEM_REF of a non-addressable
|
||||
decl use bitfield operations.
|
||||
(get_inner_reference): Handle MEM_REF.
|
||||
(expand_expr_addr_expr_1): Likewise.
|
||||
(expand_expr_real_1): Likewise.
|
||||
* tree-eh.c (tree_could_trap_p): Handle MEM_REF.
|
||||
* alias.c (ao_ref_from_mem): Handle MEM_REF.
|
||||
(get_alias_set): Likewise. Properly handle VIEW_CONVERT_EXPRs.
|
||||
* tree-data-ref.c (dr_analyze_innermost): Handle MEM_REF.
|
||||
(dr_analyze_indices): Likewise.
|
||||
(dr_analyze_alias): Likewise.
|
||||
(object_address_invariant_in_loop_p): Likewise.
|
||||
* gimplify.c (mark_addressable): Handle MEM_REF.
|
||||
(gimplify_cond_expr): Build MEM_REFs.
|
||||
(gimplify_modify_expr_to_memcpy): Likewise.
|
||||
(gimplify_init_ctor_preeval_1): Handle MEM_REF.
|
||||
(gimple_fold_indirect_ref): Adjust.
|
||||
(gimplify_expr): Handle MEM_REF. Gimplify INDIRECT_REF to MEM_REF.
|
||||
* tree.def (MEM_REF): New tree code.
|
||||
* tree-dfa.c: Include toplev.h.
|
||||
(get_ref_base_and_extent): Handle MEM_REF.
|
||||
(get_addr_base_and_unit_offset): New function.
|
||||
* emit-rtl.c (set_mem_attributes_minus_bitpos): Handle MEM_REF.
|
||||
* gimple-fold.c (may_propagate_address_into_dereference): Handle
|
||||
MEM_REF.
|
||||
(maybe_fold_offset_to_array_ref): Allow possibly out-of bounds
|
||||
accesses if the array has just one dimension. Remove always true
|
||||
parameter. Do not require type compatibility here.
|
||||
(maybe_fold_offset_to_component_ref): Remove.
|
||||
(maybe_fold_stmt_indirect): Remove.
|
||||
(maybe_fold_reference): Remove INDIRECT_REF handling.
|
||||
Fold back to non-MEM_REF.
|
||||
(maybe_fold_offset_to_address): Simplify. Deal with type
|
||||
mismatches here.
|
||||
(maybe_fold_reference): Likewise.
|
||||
(maybe_fold_stmt_addition): Likewise. Also handle
|
||||
&ARRAY + I in addition to &ARRAY[0] + I.
|
||||
(fold_gimple_assign): Handle ADDR_EXPR of MEM_REFs.
|
||||
(gimple_get_relevant_ref_binfo): Handle MEM_REF.
|
||||
* cfgexpand.c (expand_debug_expr): Handle MEM_REF.
|
||||
* tree-ssa.c (useless_type_conversion_p): Make most pointer
|
||||
conversions useless.
|
||||
(warn_uninitialized_var): Handle MEM_REF.
|
||||
(maybe_rewrite_mem_ref_base): New function.
|
||||
(execute_update_addresses_taken): Implement re-writing of MEM_REFs
|
||||
to SSA form.
|
||||
* tree-inline.c (remap_gimple_op_r): Handle MEM_REF, remove
|
||||
INDIRECT_REF handling.
|
||||
(copy_tree_body_r): Handle MEM_REF.
|
||||
* gimple.c (is_gimple_addressable): Adjust.
|
||||
(is_gimple_address): Likewise.
|
||||
(is_gimple_invariant_address): ADDR_EXPRs of MEM_REFs with
|
||||
invariant base are invariant.
|
||||
(is_gimple_min_lval): Adjust.
|
||||
(is_gimple_mem_ref_addr): New function.
|
||||
(get_base_address): Handle MEM_REF.
|
||||
(count_ptr_derefs): Likewise.
|
||||
(get_base_loadstore): Likewise.
|
||||
* gimple.h (is_gimple_mem_ref_addr): Declare.
|
||||
(gimple_call_fndecl): Handle invariant MEM_REF addresses.
|
||||
* tree-cfg.c (verify_address): New function, split out from ...
|
||||
(verify_expr): ... here. Use for verifying ADDR_EXPRs and
|
||||
the address operand of MEM_REFs. Verify MEM_REFs. Reject
|
||||
INDIRECT_REFs.
|
||||
(verify_types_in_gimple_min_lval): Handle MEM_REF. Disallow
|
||||
INDIRECT_REF. Allow conversions.
|
||||
(verify_types_in_gimple_reference): Verify VIEW_CONVERT_EXPR of
|
||||
a register does not change its size.
|
||||
(verify_types_in_gimple_reference): Verify MEM_REF.
|
||||
(verify_gimple_assign_single): Disallow INDIRECT_REF.
|
||||
Handle MEM_REF.
|
||||
* tree-ssa-operands.c (opf_non_addressable, opf_not_non_addressable):
|
||||
New.
|
||||
(mark_address_taken): Handle MEM_REF.
|
||||
(get_indirect_ref_operands): Pass through opf_not_non_addressable.
|
||||
(get_asm_expr_operands): Pass opf_not_non_addressable.
|
||||
(get_expr_operands): Handle opf_[not_]non_addressable.
|
||||
Handle MEM_REF. Remove INDIRECT_REF handling.
|
||||
* tree-vrp.c: (check_array_ref): Handle MEM_REF.
|
||||
(search_for_addr_array): Likewise.
|
||||
(check_array_bounds): Likewise.
|
||||
(vrp_stmt_computes_nonzero): Adjust for MEM_REF.
|
||||
* tree-ssa-loop-im.c (for_each_index): Handle MEM_REF.
|
||||
(ref_always_accessed_p): Likewise.
|
||||
(gen_lsm_tmp_name): Likewise. Handle ADDR_EXPR.
|
||||
* tree-complex.c (extract_component): Do not handle INDIRECT_REF.
|
||||
Handle MEM_REF.
|
||||
* cgraphbuild.c (mark_load): Properly check for NULL result
|
||||
from get_base_address.
|
||||
(mark_store): Likewise.
|
||||
* tree-ssa-loop-niter.c (array_at_struct_end_p): Handle MEM_REF.
|
||||
* tree-loop-distribution.c (generate_builtin): Exchange INDIRECT_REF
|
||||
handling for MEM_REF.
|
||||
* tree-scalar-evolution.c (follow_ssa_edge_expr): Handle
|
||||
&MEM[ptr + CST] similar to POINTER_PLUS_EXPR.
|
||||
* builtins.c (stabilize_va_list_loc): Use the function ABI
|
||||
valist type if we couldn't canonicalize the argument type.
|
||||
Always dereference with the canonical va-list type.
|
||||
(maybe_emit_free_warning): Handle MEM_REF.
|
||||
(fold_builtin_memory_op): Simplify and handle MEM_REFs in folding
|
||||
memmove to memcpy.
|
||||
* builtins.c (fold_builtin_memory_op): Use ref-all types
|
||||
for all memcpy foldings.
|
||||
* omp-low.c (build_receiver_ref): Adjust for MEM_REF.
|
||||
(build_outer_var_ref): Likewise.
|
||||
(scan_omp_1_op): Likewise.
|
||||
(lower_rec_input_clauses): Likewise.
|
||||
(lower_lastprivate_clauses): Likewise.
|
||||
(lower_reduction_clauses): Likewise.
|
||||
(lower_copyprivate_clauses): Likewise.
|
||||
(expand_omp_atomic_pipeline): Likewise.
|
||||
(expand_omp_atomic_mutex): Likewise.
|
||||
(create_task_copyfn): Likewise.
|
||||
* tree-ssa-sccvn.c (copy_reference_ops_from_ref): Handle MEM_REF.
|
||||
Remove old union trick. Initialize constant offsets.
|
||||
(ao_ref_init_from_vn_reference): Likewise. Do not handle
|
||||
INDIRECT_REF. Init base_alias_set properly.
|
||||
(vn_reference_lookup_3): Replace INDIRECT_REF handling with
|
||||
MEM_REF.
|
||||
(vn_reference_fold_indirect): Adjust for MEM_REFs.
|
||||
(valueize_refs): Fold MEM_REFs. Re-evaluate constant offset
|
||||
for ARRAY_REFs.
|
||||
(may_insert): Remove.
|
||||
(visit_reference_op_load): Do not test may_insert.
|
||||
(run_scc_vn): Remove parameter, do not fiddle with may_insert.
|
||||
* tree-ssa-sccvn.h (struct vn_reference_op_struct): Add
|
||||
a field to store the constant offset this op applies.
|
||||
(run_scc_vn): Adjust prototype.
|
||||
* cgraphunit.c (thunk_adjust): Adjust for MEM_REF.
|
||||
* tree-ssa-ccp.c (ccp_fold): Replace INDIRECT_REF folding with
|
||||
MEM_REF. Propagate &foo + CST as &MEM[&foo, CST]. Do not
|
||||
bother about volatile qualifiers on pointers.
|
||||
(fold_const_aggregate_ref): Handle MEM_REF, do not handle INDIRECT_REF.
|
||||
* tree-ssa-loop-ivopts.c
|
||||
* tree-ssa-loop-ivopts.c (determine_base_object): Adjust
|
||||
for MEM_REF.
|
||||
(strip_offset_1): Likewise.
|
||||
(find_interesting_uses_address): Replace INDIRECT_REF handling with
|
||||
MEM_REF handling.
|
||||
(get_computation_cost_at): Likewise.
|
||||
* ipa-pure-const.c (check_op): Handle MEM_REF.
|
||||
* tree-stdarg.c (check_all_va_list_escapes): Adjust for MEM_REF.
|
||||
* tree-ssa-sink.c (is_hidden_global_store): Handle MEM_REF
|
||||
and constants.
|
||||
* ipa-inline.c (likely_eliminated_by_inlining_p): Handle MEM_REF.
|
||||
* tree-parloops.c (take_address_of): Adjust for MEM_REF.
|
||||
(eliminate_local_variables_1): Likewise.
|
||||
(create_call_for_reduction_1): Likewise.
|
||||
(create_loads_for_reductions): Likewise.
|
||||
(create_loads_and_stores_for_name): Likewise.
|
||||
* matrix-reorg.c (may_flatten_matrices_1): Sanitize.
|
||||
(ssa_accessed_in_tree): Handle MEM_REF.
|
||||
(ssa_accessed_in_assign_rhs): Likewise.
|
||||
(update_type_size): Likewise.
|
||||
(analyze_accesses_for_call_stmt): Likewise.
|
||||
(analyze_accesses_for_assign_stmt): Likewise.
|
||||
(transform_access_sites): Likewise.
|
||||
(transform_allocation_sites): Likewise.
|
||||
* tree-affine.c (tree_to_aff_combination): Handle MEM_REF.
|
||||
* tree-vect-data-refs.c (vect_create_addr_base_for_vector_ref): Do
|
||||
not handle INDIRECT_REF.
|
||||
* tree-ssa-phiopt.c (add_or_mark_expr): Handle MEM_REF.
|
||||
(cond_store_replacement): Likewise.
|
||||
* tree-ssa-pre.c (create_component_ref_by_pieces_1): Handle
|
||||
MEM_REF, no not handle INDIRECT_REFs.
|
||||
(insert_into_preds_of_block): Properly initialize avail.
|
||||
(phi_translate_1): Fold MEM_REFs. Re-evaluate constant offset
|
||||
for ARRAY_REFs. Properly handle reference lookups that
|
||||
require a bit re-interpretation.
|
||||
(can_PRE_operation): Do not handle INDIRECT_REF. Handle MEM_REF.
|
||||
* tree-sra.c
|
||||
* tree-sra.c (build_access_from_expr_1): Handle MEM_REF.
|
||||
(build_ref_for_offset_1): Remove.
|
||||
(build_ref_for_offset): Build MEM_REFs.
|
||||
(gate_intra_sra): Disable for now.
|
||||
(sra_ipa_modify_expr): Handle MEM_REF.
|
||||
(ipa_early_sra_gate): Disable for now.
|
||||
* tree-sra.c (create_access): Swap INDIRECT_REF handling for
|
||||
MEM_REF handling.
|
||||
(disqualify_base_of_expr): Likewise.
|
||||
(ptr_parm_has_direct_uses): Swap INDIRECT_REF handling for
|
||||
MEM_REF handling.
|
||||
(sra_ipa_modify_expr): Remove INDIRECT_REF handling.
|
||||
Use mem_ref_offset. Remove bogus folding.
|
||||
(build_access_from_expr_1): Properly handle MEM_REF for
|
||||
non IPA-SRA.
|
||||
(make_fancy_name_1): Add support for MEM_REF.
|
||||
* tree-predcom.c (ref_at_iteration): Handle MEM_REFs.
|
||||
* tree-mudflap.c (mf_xform_derefs_1): Adjust for MEM_REF.
|
||||
* ipa-prop.c (compute_complex_assign_jump_func): Handle MEM_REF.
|
||||
(compute_complex_ancestor_jump_func): Likewise.
|
||||
(ipa_analyze_virtual_call_uses): Likewise.
|
||||
* tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Replace
|
||||
INDIRECT_REF folding with more generalized MEM_REF folding.
|
||||
(tree_ssa_forward_propagate_single_use_vars): Adjust accordingly.
|
||||
(forward_propagate_addr_into_variable_array_index): Also handle
|
||||
&ARRAY + I in addition to &ARRAY[0] + I.
|
||||
* tree-ssa-dce.c (ref_may_be_aliased): Handle MEM_REF.
|
||||
* tree-ssa-ter.c (find_replaceable_in_bb): Avoid TER if that
|
||||
creates assignments with overlap.
|
||||
* tree-nested.c (get_static_chain): Adjust for MEM_REF.
|
||||
(get_frame_field): Likewise.
|
||||
(get_nonlocal_debug_decl): Likewise.
|
||||
(convert_nonlocal_reference_op): Likewise.
|
||||
(struct nesting_info): Add mem_refs pointer-set.
|
||||
(create_nesting_tree): Allocate it.
|
||||
(convert_local_reference_op): Insert to be folded mem-refs.
|
||||
(fold_mem_refs): New function.
|
||||
(finalize_nesting_tree_1): Perform defered folding of mem-refs
|
||||
(free_nesting_tree): Free the pointer-set.
|
||||
* tree-vect-stmts.c (vectorizable_store): Adjust for MEM_REF.
|
||||
(vectorizable_load): Likewise.
|
||||
* tree-ssa-phiprop.c (phiprop_insert_phi): Adjust for MEM_REF.
|
||||
(propagate_with_phi): Likewise.
|
||||
* tree-object-size.c (addr_object_size): Handle MEM_REFs
|
||||
instead of INDIRECT_REFs.
|
||||
(compute_object_offset): Handle MEM_REF.
|
||||
(plus_stmt_object_size): Handle MEM_REF.
|
||||
(collect_object_sizes_for): Dispatch to plus_stmt_object_size
|
||||
for &MEM_REF.
|
||||
* tree-flow.h (get_addr_base_and_unit_offset): Declare.
|
||||
(symbol_marked_for_renaming): Likewise.
|
||||
* Makefile.in (tree-dfa.o): Add $(TOPLEV_H).
|
||||
(fold-const.o): Add $(TREE_FLOW_H).
|
||||
* tree-ssa-structalias.c (get_constraint_for_1): Handle MEM_REF.
|
||||
(find_func_clobbers): Likewise.
|
||||
* ipa-struct-reorg.c (decompose_indirect_ref_acc): Handle MEM_REF.
|
||||
(decompose_access): Likewise.
|
||||
(replace_field_acc): Likewise.
|
||||
(replace_field_access_stmt): Likewise.
|
||||
(insert_new_var_in_stmt): Likewise.
|
||||
(get_stmt_accesses): Likewise.
|
||||
(reorg_structs_drive): Disable.
|
||||
* config/i386/i386.c (ix86_va_start): Adjust for MEM_REF.
|
||||
(ix86_canonical_va_list_type): Likewise.
|
||||
|
||||
2010-06-30 Joern Rennecke <joern.rennecke@embecosm.com>
|
||||
|
||||
PR other/44566
|
||||
|
|
|
|||
|
|
@ -2510,7 +2510,7 @@ tree-dfa.o : tree-dfa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
|
|||
$(TREE_INLINE_H) $(HASHTAB_H) pointer-set.h $(FLAGS_H) $(FUNCTION_H) \
|
||||
$(TIMEVAR_H) convert.h $(TM_H) coretypes.h langhooks.h $(TREE_DUMP_H) \
|
||||
$(TREE_PASS_H) $(PARAMS_H) $(CGRAPH_H) $(BASIC_BLOCK_H) $(GIMPLE_H) \
|
||||
tree-pretty-print.h
|
||||
tree-pretty-print.h $(TOPLEV_H)
|
||||
tree-ssa-operands.o : tree-ssa-operands.c $(TREE_FLOW_H) $(CONFIG_H) \
|
||||
$(SYSTEM_H) $(TREE_H) $(GGC_H) $(DIAGNOSTIC_H) $(TREE_INLINE_H) \
|
||||
$(FLAGS_H) $(FUNCTION_H) $(TM_H) $(TIMEVAR_H) $(TREE_PASS_H) $(TOPLEV_H) \
|
||||
|
|
@ -2789,7 +2789,7 @@ tree-diagnostic.o : tree-diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
|
|||
fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(TREE_H) $(FLAGS_H) $(TOPLEV_H) $(HASHTAB_H) $(EXPR_H) $(RTL_H) \
|
||||
$(GGC_H) $(TM_P_H) langhooks.h $(MD5_H) intl.h $(TARGET_H) \
|
||||
$(GIMPLE_H) realmpfr.h
|
||||
$(GIMPLE_H) realmpfr.h $(TREE_FLOW_H)
|
||||
diagnostic.o : diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
|
||||
version.h $(INPUT_H) intl.h $(DIAGNOSTIC_H) diagnostic.def
|
||||
opts.o : opts.c opts.h options.h $(TOPLEV_H) $(CONFIG_H) $(SYSTEM_H) \
|
||||
|
|
|
|||
38
gcc/alias.c
38
gcc/alias.c
|
|
@ -279,7 +279,8 @@ ao_ref_from_mem (ao_ref *ref, const_rtx mem)
|
|||
|
||||
/* If this is a pointer dereference of a non-SSA_NAME punt.
|
||||
??? We could replace it with a pointer to anything. */
|
||||
if (INDIRECT_REF_P (base)
|
||||
if ((INDIRECT_REF_P (base)
|
||||
|| TREE_CODE (base) == MEM_REF)
|
||||
&& TREE_CODE (TREE_OPERAND (base, 0)) != SSA_NAME)
|
||||
return false;
|
||||
|
||||
|
|
@ -293,10 +294,7 @@ ao_ref_from_mem (ao_ref *ref, const_rtx mem)
|
|||
void *namep;
|
||||
namep = pointer_map_contains (cfun->gimple_df->decls_to_pointers, base);
|
||||
if (namep)
|
||||
{
|
||||
ref->base_alias_set = get_alias_set (base);
|
||||
ref->base = build1 (INDIRECT_REF, TREE_TYPE (base), *(tree *)namep);
|
||||
}
|
||||
ref->base = build_simple_mem_ref (*(tree *)namep);
|
||||
}
|
||||
|
||||
ref->ref_alias_set = MEM_ALIAS_SET (mem);
|
||||
|
|
@ -648,8 +646,8 @@ get_alias_set (tree t)
|
|||
{
|
||||
tree inner;
|
||||
|
||||
/* Remove any nops, then give the language a chance to do
|
||||
something with this tree before we look at it. */
|
||||
/* Give the language a chance to do something with this tree
|
||||
before we look at it. */
|
||||
STRIP_NOPS (t);
|
||||
set = lang_hooks.get_alias_set (t);
|
||||
if (set != -1)
|
||||
|
|
@ -659,21 +657,41 @@ get_alias_set (tree t)
|
|||
if (TREE_CODE (t) == TARGET_MEM_REF)
|
||||
t = TMR_ORIGINAL (t);
|
||||
|
||||
/* First see if the actual object referenced is an INDIRECT_REF from a
|
||||
restrict-qualified pointer or a "void *". */
|
||||
/* Get the base object of the reference. */
|
||||
inner = t;
|
||||
while (handled_component_p (inner))
|
||||
{
|
||||
/* If there is a VIEW_CONVERT_EXPR in the chain we cannot use
|
||||
the type of any component references that wrap it to
|
||||
determine the alias-set. */
|
||||
if (TREE_CODE (inner) == VIEW_CONVERT_EXPR)
|
||||
t = TREE_OPERAND (inner, 0);
|
||||
inner = TREE_OPERAND (inner, 0);
|
||||
STRIP_NOPS (inner);
|
||||
}
|
||||
|
||||
/* Handle pointer dereferences here, they can override the
|
||||
alias-set. */
|
||||
if (INDIRECT_REF_P (inner))
|
||||
{
|
||||
set = get_deref_alias_set_1 (TREE_OPERAND (inner, 0));
|
||||
if (set != -1)
|
||||
return set;
|
||||
}
|
||||
else if (TREE_CODE (inner) == MEM_REF)
|
||||
{
|
||||
set = get_deref_alias_set_1 (TREE_OPERAND (inner, 1));
|
||||
if (set != -1)
|
||||
return set;
|
||||
}
|
||||
|
||||
/* If the innermost reference is a MEM_REF that has a
|
||||
conversion embedded treat it like a VIEW_CONVERT_EXPR above,
|
||||
using the memory access type for determining the alias-set. */
|
||||
if (TREE_CODE (inner) == MEM_REF
|
||||
&& (TYPE_MAIN_VARIANT (TREE_TYPE (inner))
|
||||
!= TYPE_MAIN_VARIANT
|
||||
(TREE_TYPE (TREE_TYPE (TREE_OPERAND (inner, 1))))))
|
||||
return get_deref_alias_set (TREE_OPERAND (inner, 1));
|
||||
|
||||
/* Otherwise, pick up the outermost object that we could have a pointer
|
||||
to, processing conversions as above. */
|
||||
|
|
|
|||
180
gcc/builtins.c
180
gcc/builtins.c
|
|
@ -4455,7 +4455,10 @@ stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue)
|
|||
{
|
||||
tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist));
|
||||
|
||||
gcc_assert (vatype != NULL_TREE);
|
||||
/* The current way of determining the type of valist is completely
|
||||
bogus. We should have the information on the va builtin instead. */
|
||||
if (!vatype)
|
||||
vatype = targetm.fn_abi_va_list (cfun->decl);
|
||||
|
||||
if (TREE_CODE (vatype) == ARRAY_TYPE)
|
||||
{
|
||||
|
|
@ -4474,21 +4477,21 @@ stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue)
|
|||
}
|
||||
else
|
||||
{
|
||||
tree pt;
|
||||
tree pt = build_pointer_type (vatype);
|
||||
|
||||
if (! needs_lvalue)
|
||||
{
|
||||
if (! TREE_SIDE_EFFECTS (valist))
|
||||
return valist;
|
||||
|
||||
pt = build_pointer_type (vatype);
|
||||
valist = fold_build1_loc (loc, ADDR_EXPR, pt, valist);
|
||||
TREE_SIDE_EFFECTS (valist) = 1;
|
||||
}
|
||||
|
||||
if (TREE_SIDE_EFFECTS (valist))
|
||||
valist = save_expr (valist);
|
||||
valist = build_fold_indirect_ref_loc (loc, valist);
|
||||
valist = fold_build2_loc (loc, MEM_REF,
|
||||
vatype, valist, build_int_cst (pt, 0));
|
||||
}
|
||||
|
||||
return valist;
|
||||
|
|
@ -8346,6 +8349,7 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
|
|||
{
|
||||
tree srctype, desttype;
|
||||
int src_align, dest_align;
|
||||
tree off0;
|
||||
|
||||
if (endp == 3)
|
||||
{
|
||||
|
|
@ -8371,37 +8375,26 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
|
|||
}
|
||||
|
||||
/* If *src and *dest can't overlap, optimize into memcpy as well. */
|
||||
srcvar = build_fold_indirect_ref_loc (loc, src);
|
||||
destvar = build_fold_indirect_ref_loc (loc, dest);
|
||||
if (srcvar
|
||||
&& !TREE_THIS_VOLATILE (srcvar)
|
||||
&& destvar
|
||||
&& !TREE_THIS_VOLATILE (destvar))
|
||||
if (TREE_CODE (src) == ADDR_EXPR
|
||||
&& TREE_CODE (dest) == ADDR_EXPR)
|
||||
{
|
||||
tree src_base, dest_base, fn;
|
||||
HOST_WIDE_INT src_offset = 0, dest_offset = 0;
|
||||
HOST_WIDE_INT size = -1;
|
||||
HOST_WIDE_INT maxsize = -1;
|
||||
|
||||
src_base = srcvar;
|
||||
if (handled_component_p (src_base))
|
||||
src_base = get_ref_base_and_extent (src_base, &src_offset,
|
||||
&size, &maxsize);
|
||||
dest_base = destvar;
|
||||
if (handled_component_p (dest_base))
|
||||
dest_base = get_ref_base_and_extent (dest_base, &dest_offset,
|
||||
&size, &maxsize);
|
||||
srcvar = TREE_OPERAND (src, 0);
|
||||
src_base = get_ref_base_and_extent (srcvar, &src_offset,
|
||||
&size, &maxsize);
|
||||
destvar = TREE_OPERAND (dest, 0);
|
||||
dest_base = get_ref_base_and_extent (destvar, &dest_offset,
|
||||
&size, &maxsize);
|
||||
if (host_integerp (len, 1))
|
||||
{
|
||||
maxsize = tree_low_cst (len, 1);
|
||||
if (maxsize
|
||||
> INTTYPE_MAXIMUM (HOST_WIDE_INT) / BITS_PER_UNIT)
|
||||
maxsize = -1;
|
||||
else
|
||||
maxsize *= BITS_PER_UNIT;
|
||||
}
|
||||
maxsize = tree_low_cst (len, 1);
|
||||
else
|
||||
maxsize = -1;
|
||||
src_offset /= BITS_PER_UNIT;
|
||||
dest_offset /= BITS_PER_UNIT;
|
||||
if (SSA_VAR_P (src_base)
|
||||
&& SSA_VAR_P (dest_base))
|
||||
{
|
||||
|
|
@ -8410,13 +8403,25 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
|
|||
dest_offset, maxsize))
|
||||
return NULL_TREE;
|
||||
}
|
||||
else if (TREE_CODE (src_base) == INDIRECT_REF
|
||||
&& TREE_CODE (dest_base) == INDIRECT_REF)
|
||||
else if (TREE_CODE (src_base) == MEM_REF
|
||||
&& TREE_CODE (dest_base) == MEM_REF)
|
||||
{
|
||||
double_int off;
|
||||
if (! operand_equal_p (TREE_OPERAND (src_base, 0),
|
||||
TREE_OPERAND (dest_base, 0), 0)
|
||||
|| ranges_overlap_p (src_offset, maxsize,
|
||||
dest_offset, maxsize))
|
||||
TREE_OPERAND (dest_base, 0), 0))
|
||||
return NULL_TREE;
|
||||
off = double_int_add (mem_ref_offset (src_base),
|
||||
shwi_to_double_int (src_offset));
|
||||
if (!double_int_fits_in_shwi_p (off))
|
||||
return NULL_TREE;
|
||||
src_offset = off.low;
|
||||
off = double_int_add (mem_ref_offset (dest_base),
|
||||
shwi_to_double_int (dest_offset));
|
||||
if (!double_int_fits_in_shwi_p (off))
|
||||
return NULL_TREE;
|
||||
dest_offset = off.low;
|
||||
if (ranges_overlap_p (src_offset, maxsize,
|
||||
dest_offset, maxsize))
|
||||
return NULL_TREE;
|
||||
}
|
||||
else
|
||||
|
|
@ -8472,12 +8477,12 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
|
|||
dest = build1 (NOP_EXPR, build_pointer_type (desttype), dest);
|
||||
}
|
||||
if (!srctype || !desttype
|
||||
|| TREE_ADDRESSABLE (srctype)
|
||||
|| TREE_ADDRESSABLE (desttype)
|
||||
|| !TYPE_SIZE_UNIT (srctype)
|
||||
|| !TYPE_SIZE_UNIT (desttype)
|
||||
|| TREE_CODE (TYPE_SIZE_UNIT (srctype)) != INTEGER_CST
|
||||
|| TREE_CODE (TYPE_SIZE_UNIT (desttype)) != INTEGER_CST
|
||||
|| TYPE_VOLATILE (srctype)
|
||||
|| TYPE_VOLATILE (desttype))
|
||||
|| TREE_CODE (TYPE_SIZE_UNIT (desttype)) != INTEGER_CST)
|
||||
return NULL_TREE;
|
||||
|
||||
src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
|
||||
|
|
@ -8489,97 +8494,44 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
|
|||
if (!ignore)
|
||||
dest = builtin_save_expr (dest);
|
||||
|
||||
srcvar = NULL_TREE;
|
||||
if (tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
|
||||
{
|
||||
srcvar = build_fold_indirect_ref_loc (loc, src);
|
||||
if (TREE_THIS_VOLATILE (srcvar))
|
||||
return NULL_TREE;
|
||||
else if (!tree_int_cst_equal (tree_expr_size (srcvar), len))
|
||||
srcvar = NULL_TREE;
|
||||
/* With memcpy, it is possible to bypass aliasing rules, so without
|
||||
this check i.e. execute/20060930-2.c would be misoptimized,
|
||||
because it use conflicting alias set to hold argument for the
|
||||
memcpy call. This check is probably unnecessary with
|
||||
-fno-strict-aliasing. Similarly for destvar. See also
|
||||
PR29286. */
|
||||
else if (!var_decl_component_p (srcvar))
|
||||
srcvar = NULL_TREE;
|
||||
}
|
||||
/* Build accesses at offset zero with a ref-all character type. */
|
||||
off0 = build_int_cst (build_pointer_type_for_mode (char_type_node,
|
||||
ptr_mode, true), 0);
|
||||
|
||||
destvar = NULL_TREE;
|
||||
if (tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
|
||||
{
|
||||
destvar = build_fold_indirect_ref_loc (loc, dest);
|
||||
if (TREE_THIS_VOLATILE (destvar))
|
||||
return NULL_TREE;
|
||||
else if (!tree_int_cst_equal (tree_expr_size (destvar), len))
|
||||
destvar = NULL_TREE;
|
||||
else if (!var_decl_component_p (destvar))
|
||||
destvar = NULL_TREE;
|
||||
}
|
||||
destvar = dest;
|
||||
STRIP_NOPS (destvar);
|
||||
if (TREE_CODE (destvar) == ADDR_EXPR
|
||||
&& var_decl_component_p (TREE_OPERAND (destvar, 0))
|
||||
&& tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
|
||||
destvar = fold_build2 (MEM_REF, desttype, destvar, off0);
|
||||
else
|
||||
destvar = NULL_TREE;
|
||||
|
||||
srcvar = src;
|
||||
STRIP_NOPS (srcvar);
|
||||
if (TREE_CODE (srcvar) == ADDR_EXPR
|
||||
&& var_decl_component_p (TREE_OPERAND (srcvar, 0))
|
||||
&& tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
|
||||
srcvar = fold_build2 (MEM_REF, destvar ? desttype : srctype,
|
||||
srcvar, off0);
|
||||
else
|
||||
srcvar = NULL_TREE;
|
||||
|
||||
if (srcvar == NULL_TREE && destvar == NULL_TREE)
|
||||
return NULL_TREE;
|
||||
|
||||
if (srcvar == NULL_TREE)
|
||||
{
|
||||
tree srcptype;
|
||||
if (TREE_ADDRESSABLE (TREE_TYPE (destvar)))
|
||||
return NULL_TREE;
|
||||
|
||||
srctype = build_qualified_type (desttype, 0);
|
||||
if (src_align < (int) TYPE_ALIGN (srctype))
|
||||
{
|
||||
if (AGGREGATE_TYPE_P (srctype)
|
||||
|| SLOW_UNALIGNED_ACCESS (TYPE_MODE (srctype), src_align))
|
||||
return NULL_TREE;
|
||||
|
||||
srctype = build_variant_type_copy (srctype);
|
||||
TYPE_ALIGN (srctype) = src_align;
|
||||
TYPE_USER_ALIGN (srctype) = 1;
|
||||
TYPE_PACKED (srctype) = 1;
|
||||
}
|
||||
srcptype = build_pointer_type_for_mode (srctype, ptr_mode, true);
|
||||
src = fold_convert_loc (loc, srcptype, src);
|
||||
srcvar = build_fold_indirect_ref_loc (loc, src);
|
||||
STRIP_NOPS (src);
|
||||
srcvar = fold_build2 (MEM_REF, desttype, src, off0);
|
||||
}
|
||||
else if (destvar == NULL_TREE)
|
||||
{
|
||||
tree destptype;
|
||||
if (TREE_ADDRESSABLE (TREE_TYPE (srcvar)))
|
||||
return NULL_TREE;
|
||||
|
||||
desttype = build_qualified_type (srctype, 0);
|
||||
if (dest_align < (int) TYPE_ALIGN (desttype))
|
||||
{
|
||||
if (AGGREGATE_TYPE_P (desttype)
|
||||
|| SLOW_UNALIGNED_ACCESS (TYPE_MODE (desttype), dest_align))
|
||||
return NULL_TREE;
|
||||
|
||||
desttype = build_variant_type_copy (desttype);
|
||||
TYPE_ALIGN (desttype) = dest_align;
|
||||
TYPE_USER_ALIGN (desttype) = 1;
|
||||
TYPE_PACKED (desttype) = 1;
|
||||
}
|
||||
destptype = build_pointer_type_for_mode (desttype, ptr_mode, true);
|
||||
dest = fold_convert_loc (loc, destptype, dest);
|
||||
destvar = build_fold_indirect_ref_loc (loc, dest);
|
||||
STRIP_NOPS (dest);
|
||||
destvar = fold_build2 (MEM_REF, srctype, dest, off0);
|
||||
}
|
||||
|
||||
if (srctype == desttype
|
||||
|| (gimple_in_ssa_p (cfun)
|
||||
&& useless_type_conversion_p (desttype, srctype)))
|
||||
expr = srcvar;
|
||||
else if ((INTEGRAL_TYPE_P (TREE_TYPE (srcvar))
|
||||
|| POINTER_TYPE_P (TREE_TYPE (srcvar)))
|
||||
&& (INTEGRAL_TYPE_P (TREE_TYPE (destvar))
|
||||
|| POINTER_TYPE_P (TREE_TYPE (destvar))))
|
||||
expr = fold_convert_loc (loc, TREE_TYPE (destvar), srcvar);
|
||||
else
|
||||
expr = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
|
||||
TREE_TYPE (destvar), srcvar);
|
||||
expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, expr);
|
||||
expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, srcvar);
|
||||
}
|
||||
|
||||
if (ignore)
|
||||
|
|
@ -12068,7 +12020,7 @@ maybe_emit_free_warning (tree exp)
|
|||
return;
|
||||
|
||||
arg = get_base_address (TREE_OPERAND (arg, 0));
|
||||
if (arg == NULL || INDIRECT_REF_P (arg))
|
||||
if (arg == NULL || INDIRECT_REF_P (arg) || TREE_CODE (arg) == MEM_REF)
|
||||
return;
|
||||
|
||||
if (SSA_VAR_P (arg))
|
||||
|
|
|
|||
|
|
@ -2438,6 +2438,11 @@ expand_debug_expr (tree exp)
|
|||
return op0;
|
||||
}
|
||||
|
||||
case MEM_REF:
|
||||
/* ??? FIXME. */
|
||||
if (!integer_zerop (TREE_OPERAND (exp, 1)))
|
||||
return NULL;
|
||||
/* Fallthru. */
|
||||
case INDIRECT_REF:
|
||||
case ALIGN_INDIRECT_REF:
|
||||
case MISALIGNED_INDIRECT_REF:
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t,
|
|||
void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
t = get_base_address (t);
|
||||
if (TREE_CODE (t) == VAR_DECL
|
||||
if (t && TREE_CODE (t) == VAR_DECL
|
||||
&& (TREE_STATIC (t) || DECL_EXTERNAL (t)))
|
||||
{
|
||||
struct varpool_node *vnode = varpool_node (t);
|
||||
|
|
@ -300,7 +300,7 @@ mark_store (gimple stmt ATTRIBUTE_UNUSED, tree t,
|
|||
void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
t = get_base_address (t);
|
||||
if (TREE_CODE (t) == VAR_DECL
|
||||
if (t && TREE_CODE (t) == VAR_DECL
|
||||
&& (TREE_STATIC (t) || DECL_EXTERNAL (t)))
|
||||
{
|
||||
struct varpool_node *vnode = varpool_node (t);
|
||||
|
|
|
|||
|
|
@ -1364,8 +1364,7 @@ thunk_adjust (gimple_stmt_iterator * bsi,
|
|||
vtabletmp2 = create_tmp_var (TREE_TYPE (TREE_TYPE (vtabletmp)),
|
||||
"vtableaddr");
|
||||
stmt = gimple_build_assign (vtabletmp2,
|
||||
build1 (INDIRECT_REF,
|
||||
TREE_TYPE (vtabletmp2), vtabletmp));
|
||||
build_simple_mem_ref (vtabletmp));
|
||||
gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
|
||||
mark_symbols_for_renaming (stmt);
|
||||
find_referenced_vars_in (stmt);
|
||||
|
|
@ -1384,9 +1383,7 @@ thunk_adjust (gimple_stmt_iterator * bsi,
|
|||
vtabletmp3 = create_tmp_var (TREE_TYPE (TREE_TYPE (vtabletmp2)),
|
||||
"vcalloffset");
|
||||
stmt = gimple_build_assign (vtabletmp3,
|
||||
build1 (INDIRECT_REF,
|
||||
TREE_TYPE (vtabletmp3),
|
||||
vtabletmp2));
|
||||
build_simple_mem_ref (vtabletmp2));
|
||||
gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
|
||||
mark_symbols_for_renaming (stmt);
|
||||
find_referenced_vars_in (stmt);
|
||||
|
|
|
|||
|
|
@ -6025,7 +6025,7 @@ alpha_stdarg_optimize_hook (struct stdarg_info *si, const_gimple stmt)
|
|||
rhs = gimple_assign_rhs1 (stmt);
|
||||
while (handled_component_p (rhs))
|
||||
rhs = TREE_OPERAND (rhs, 0);
|
||||
if (TREE_CODE (rhs) != INDIRECT_REF
|
||||
if (TREE_CODE (rhs) != MEM_REF
|
||||
|| TREE_CODE (TREE_OPERAND (rhs, 0)) != SSA_NAME)
|
||||
return false;
|
||||
|
||||
|
|
|
|||
|
|
@ -7093,11 +7093,17 @@ ix86_va_start (tree valist, rtx nextarg)
|
|||
f_ovf = TREE_CHAIN (f_fpr);
|
||||
f_sav = TREE_CHAIN (f_ovf);
|
||||
|
||||
valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
|
||||
gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
|
||||
fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
|
||||
ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
|
||||
sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
|
||||
valist = build_simple_mem_ref (valist);
|
||||
TREE_TYPE (valist) = TREE_TYPE (sysv_va_list_type_node);
|
||||
/* The following should be folded into the MEM_REF offset. */
|
||||
gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), unshare_expr (valist),
|
||||
f_gpr, NULL_TREE);
|
||||
fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), unshare_expr (valist),
|
||||
f_fpr, NULL_TREE);
|
||||
ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), unshare_expr (valist),
|
||||
f_ovf, NULL_TREE);
|
||||
sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), unshare_expr (valist),
|
||||
f_sav, NULL_TREE);
|
||||
|
||||
/* Count number of gp and fp argument registers used. */
|
||||
words = crtl->args.info.words;
|
||||
|
|
@ -30619,10 +30625,12 @@ ix86_canonical_va_list_type (tree type)
|
|||
tree wtype, htype;
|
||||
|
||||
/* Resolve references and pointers to va_list type. */
|
||||
if (INDIRECT_REF_P (type))
|
||||
if (TREE_CODE (type) == MEM_REF)
|
||||
type = TREE_TYPE (type);
|
||||
else if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE(type)))
|
||||
type = TREE_TYPE (type);
|
||||
else if (POINTER_TYPE_P (type) && TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE)
|
||||
type = TREE_TYPE (type);
|
||||
|
||||
if (TARGET_64BIT)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13682,7 +13682,7 @@ rs6000_check_sdmode (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
|
|||
case RESULT_DECL:
|
||||
case SSA_NAME:
|
||||
case REAL_CST:
|
||||
case INDIRECT_REF:
|
||||
case MEM_REF:
|
||||
case ALIGN_INDIRECT_REF:
|
||||
case MISALIGNED_INDIRECT_REF:
|
||||
case VIEW_CONVERT_EXPR:
|
||||
|
|
|
|||
|
|
@ -7886,7 +7886,7 @@ sh_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
|
|||
lab_false = create_artificial_label (UNKNOWN_LOCATION);
|
||||
lab_over = create_artificial_label (UNKNOWN_LOCATION);
|
||||
|
||||
valist = build1 (INDIRECT_REF, ptr_type_node, addr);
|
||||
valist = build_simple_mem_ref (addr);
|
||||
|
||||
if (pass_as_float)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4171,7 +4171,7 @@ spu_gimplify_va_arg_expr (tree valist, tree type, gimple_seq * pre_p,
|
|||
f_args = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
|
||||
f_skip = TREE_CHAIN (f_args);
|
||||
|
||||
valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
|
||||
valist = build_simple_mem_ref (valist);
|
||||
args =
|
||||
build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE);
|
||||
skip =
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
2010-07-01 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
* cp-gimplify.c (cp_gimplify_expr): Open-code the rhs
|
||||
predicate we are looking for, allow non-gimplified
|
||||
INDIRECT_REFs.
|
||||
|
||||
2010-06-30 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
|
||||
PR c++/44628
|
||||
|
|
|
|||
|
|
@ -575,7 +575,7 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
|
|||
TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR,
|
||||
TREE_TYPE (op0), op1);
|
||||
|
||||
else if ((rhs_predicate_for (op0)) (op1)
|
||||
else if ((is_gimple_lvalue (op1) || INDIRECT_REF_P (op1))
|
||||
&& !(TREE_CODE (op1) == CALL_EXPR
|
||||
&& CALL_EXPR_RETURN_SLOT_OPT (op1))
|
||||
&& is_really_empty_class (TREE_TYPE (op0)))
|
||||
|
|
|
|||
|
|
@ -1116,6 +1116,7 @@ target system bytes are not the same width as host system bytes.
|
|||
@subsection References to storage
|
||||
@tindex ADDR_EXPR
|
||||
@tindex INDIRECT_REF
|
||||
@tindex MEM_REF
|
||||
@tindex ARRAY_REF
|
||||
@tindex ARRAY_RANGE_REF
|
||||
@tindex TARGET_MEM_REF
|
||||
|
|
@ -1176,6 +1177,13 @@ These nodes are used to represent the object pointed to by a pointer.
|
|||
The operand is the pointer being dereferenced; it will always have
|
||||
pointer or reference type.
|
||||
|
||||
@item MEM_REF
|
||||
These nodes are used to represent the object pointed to by a pointer
|
||||
offset by a constant.
|
||||
The first operand is the pointer being dereferenced; it will always have
|
||||
pointer or reference type. The second operand is a pointer constant.
|
||||
Its type is specifying the type to be used for type-based alias analysis.
|
||||
|
||||
@item COMPONENT_REF
|
||||
These nodes represent non-static data member accesses. The first
|
||||
operand is the object (rather than a pointer to it); the second operand
|
||||
|
|
|
|||
|
|
@ -452,8 +452,8 @@ becomes
|
|||
|
||||
The same rule holds for arguments to a @code{GIMPLE_CALL}.
|
||||
|
||||
The target of an assignment is usually a variable, but can also be an
|
||||
@code{INDIRECT_REF} or a compound lvalue as described below.
|
||||
The target of an assignment is usually a variable, but can also be a
|
||||
@code{MEM_REF} or a compound lvalue as described below.
|
||||
|
||||
@menu
|
||||
* Compound Expressions::
|
||||
|
|
@ -664,6 +664,11 @@ Return true if t is a valid expression to use as the function
|
|||
called by a @code{GIMPLE_CALL}.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {GIMPLE function} is_gimple_mem_ref_addr (tree t)
|
||||
Return true if t is a valid expression to use as first operand
|
||||
of a @code{MEM_REF} expression.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {GIMPLE function} is_gimple_constant (tree t)
|
||||
Return true if t is a valid gimple constant.
|
||||
@end deftypefn
|
||||
|
|
|
|||
|
|
@ -15160,6 +15160,11 @@ loc_list_from_tree (tree loc, int want_address)
|
|||
}
|
||||
break;
|
||||
|
||||
case MEM_REF:
|
||||
/* ??? FIXME. */
|
||||
if (!integer_zerop (TREE_OPERAND (loc, 1)))
|
||||
return 0;
|
||||
/* Fallthru. */
|
||||
case INDIRECT_REF:
|
||||
case ALIGN_INDIRECT_REF:
|
||||
case MISALIGNED_INDIRECT_REF:
|
||||
|
|
|
|||
|
|
@ -1614,6 +1614,35 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
|
|||
|| TREE_CODE (t) == ALIGN_INDIRECT_REF
|
||||
|| TYPE_ALIGN_OK (type))
|
||||
align = MAX (align, TYPE_ALIGN (type));
|
||||
else if (TREE_CODE (t) == MEM_REF)
|
||||
{
|
||||
HOST_WIDE_INT aoff = BITS_PER_UNIT;
|
||||
if (host_integerp (TREE_OPERAND (t, 1), 1))
|
||||
{
|
||||
HOST_WIDE_INT ioff = TREE_INT_CST_LOW (TREE_OPERAND (t, 1));
|
||||
aoff = (ioff & -ioff) * BITS_PER_UNIT;
|
||||
}
|
||||
if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
|
||||
&& DECL_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
|
||||
align = MAX (align,
|
||||
DECL_ALIGN (TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
|
||||
else if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
|
||||
&& CONSTANT_CLASS_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
|
||||
{
|
||||
align = TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
|
||||
#ifdef CONSTANT_ALIGNMENT
|
||||
align = CONSTANT_ALIGNMENT (TREE_OPERAND (TREE_OPERAND (t, 0), 0), align);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
/* This technically isn't correct. We can't really derive
|
||||
alignment information from types. */
|
||||
align = MAX (align,
|
||||
TYPE_ALIGN (TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 1)))));
|
||||
if (!integer_zerop (TREE_OPERAND (t, 1))
|
||||
&& aoff < align)
|
||||
align = aoff;
|
||||
}
|
||||
else
|
||||
if (TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
|
||||
{
|
||||
|
|
@ -1654,6 +1683,9 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
|
|||
|| TREE_CODE (base) == BIT_FIELD_REF)
|
||||
base = TREE_OPERAND (base, 0);
|
||||
|
||||
if (TREE_CODE (base) == MEM_REF
|
||||
&& TREE_CODE (TREE_OPERAND (base, 0)) == ADDR_EXPR)
|
||||
base = TREE_OPERAND (TREE_OPERAND (base, 0), 0);
|
||||
if (DECL_P (base))
|
||||
{
|
||||
if (CODE_CONTAINS_STRUCT (TREE_CODE (base), TS_DECL_WITH_VIS))
|
||||
|
|
@ -1774,7 +1806,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
|
|||
}
|
||||
|
||||
/* If this is an indirect reference, record it. */
|
||||
else if (TREE_CODE (t) == INDIRECT_REF
|
||||
else if (TREE_CODE (t) == MEM_REF
|
||||
|| TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
|
||||
{
|
||||
expr = t;
|
||||
|
|
@ -1784,7 +1816,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
|
|||
}
|
||||
|
||||
/* If this is an indirect reference, record it. */
|
||||
else if (TREE_CODE (t) == INDIRECT_REF
|
||||
else if (TREE_CODE (t) == MEM_REF
|
||||
|| TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
|
||||
{
|
||||
expr = t;
|
||||
|
|
|
|||
152
gcc/expr.c
152
gcc/expr.c
|
|
@ -4213,6 +4213,10 @@ expand_assignment (tree to, tree from, bool nontemporal)
|
|||
an array element in an unaligned packed structure field, has the same
|
||||
problem. */
|
||||
if (handled_component_p (to)
|
||||
/* ??? We only need to handle MEM_REF here if the access is not
|
||||
a full access of the base object. */
|
||||
|| (TREE_CODE (to) == MEM_REF
|
||||
&& TREE_CODE (TREE_OPERAND (to, 0)) == ADDR_EXPR)
|
||||
|| TREE_CODE (TREE_TYPE (to)) == ARRAY_TYPE)
|
||||
{
|
||||
enum machine_mode mode1;
|
||||
|
|
@ -4686,6 +4690,51 @@ store_expr (tree exp, rtx target, int call_param_p, bool nontemporal)
|
|||
BLOCK_OP_NORMAL);
|
||||
return NULL_RTX;
|
||||
}
|
||||
else if (TREE_CODE (exp) == MEM_REF
|
||||
&& TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
|
||||
&& TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == STRING_CST
|
||||
&& integer_zerop (TREE_OPERAND (exp, 1))
|
||||
&& !nontemporal && !call_param_p
|
||||
&& TYPE_MODE (TREE_TYPE (exp)) == BLKmode)
|
||||
{
|
||||
/* Optimize initialization of an array with a STRING_CST. */
|
||||
HOST_WIDE_INT exp_len, str_copy_len;
|
||||
rtx dest_mem;
|
||||
tree str = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
|
||||
|
||||
exp_len = int_expr_size (exp);
|
||||
if (exp_len <= 0)
|
||||
goto normal_expr;
|
||||
|
||||
str_copy_len = strlen (TREE_STRING_POINTER (str));
|
||||
if (str_copy_len < TREE_STRING_LENGTH (str) - 1)
|
||||
goto normal_expr;
|
||||
|
||||
str_copy_len = TREE_STRING_LENGTH (str);
|
||||
if ((STORE_MAX_PIECES & (STORE_MAX_PIECES - 1)) == 0)
|
||||
{
|
||||
str_copy_len += STORE_MAX_PIECES - 1;
|
||||
str_copy_len &= ~(STORE_MAX_PIECES - 1);
|
||||
}
|
||||
str_copy_len = MIN (str_copy_len, exp_len);
|
||||
if (!can_store_by_pieces (str_copy_len, builtin_strncpy_read_str,
|
||||
CONST_CAST(char *, TREE_STRING_POINTER (str)),
|
||||
MEM_ALIGN (target), false))
|
||||
goto normal_expr;
|
||||
|
||||
dest_mem = target;
|
||||
|
||||
dest_mem = store_by_pieces (dest_mem,
|
||||
str_copy_len, builtin_strncpy_read_str,
|
||||
CONST_CAST(char *, TREE_STRING_POINTER (str)),
|
||||
MEM_ALIGN (target), false,
|
||||
exp_len > str_copy_len ? 1 : 0);
|
||||
if (exp_len > str_copy_len)
|
||||
clear_storage (adjust_address (dest_mem, BLKmode, 0),
|
||||
GEN_INT (exp_len - str_copy_len),
|
||||
BLOCK_OP_NORMAL);
|
||||
return NULL_RTX;
|
||||
}
|
||||
else
|
||||
{
|
||||
rtx tmp_target;
|
||||
|
|
@ -5852,7 +5901,15 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
|
|||
operations. */
|
||||
|| (bitsize >= 0
|
||||
&& TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST
|
||||
&& compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) != 0))
|
||||
&& compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) != 0)
|
||||
/* If we are expanding a MEM_REF of a non-BLKmode non-addressable
|
||||
decl we must use bitfield operations. */
|
||||
|| (bitsize >= 0
|
||||
&& TREE_CODE (exp) == MEM_REF
|
||||
&& TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
|
||||
&& DECL_P (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
|
||||
&& !TREE_ADDRESSABLE (TREE_OPERAND (TREE_OPERAND (exp, 0),0 ))
|
||||
&& DECL_MODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) != BLKmode))
|
||||
{
|
||||
rtx temp;
|
||||
gimple nop_def;
|
||||
|
|
@ -6113,6 +6170,24 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
|
|||
goto done;
|
||||
break;
|
||||
|
||||
case MEM_REF:
|
||||
/* Hand back the decl for MEM[&decl, off]. */
|
||||
if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR)
|
||||
{
|
||||
tree off = TREE_OPERAND (exp, 1);
|
||||
if (!integer_zerop (off))
|
||||
{
|
||||
double_int boff, coff = mem_ref_offset (exp);
|
||||
boff = double_int_lshift (coff,
|
||||
BITS_PER_UNIT == 8
|
||||
? 3 : exact_log2 (BITS_PER_UNIT),
|
||||
HOST_BITS_PER_DOUBLE_INT, true);
|
||||
bit_offset = double_int_add (bit_offset, boff);
|
||||
}
|
||||
exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
|
||||
}
|
||||
goto done;
|
||||
|
||||
default:
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -6873,6 +6948,16 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
|
|||
/* This case will happen via recursion for &a->b. */
|
||||
return expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
|
||||
|
||||
case MEM_REF:
|
||||
{
|
||||
tree tem = TREE_OPERAND (exp, 0);
|
||||
if (!integer_zerop (TREE_OPERAND (exp, 1)))
|
||||
tem = build2 (POINTER_PLUS_EXPR, TREE_TYPE (TREE_OPERAND (exp, 1)),
|
||||
tem,
|
||||
double_int_to_tree (sizetype, mem_ref_offset (exp)));
|
||||
return expand_expr (tem, target, tmode, modifier);
|
||||
}
|
||||
|
||||
case CONST_DECL:
|
||||
/* Expand the initializer like constants above. */
|
||||
return XEXP (expand_expr_constant (DECL_INITIAL (exp), 0, modifier), 0);
|
||||
|
|
@ -8684,6 +8769,71 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|
|||
}
|
||||
return temp;
|
||||
|
||||
case MEM_REF:
|
||||
{
|
||||
addr_space_t as
|
||||
= TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 1))));
|
||||
enum machine_mode address_mode;
|
||||
tree base = TREE_OPERAND (exp, 0);
|
||||
/* Handle expansion of non-aliased memory with non-BLKmode. That
|
||||
might end up in a register. */
|
||||
if (TREE_CODE (base) == ADDR_EXPR)
|
||||
{
|
||||
HOST_WIDE_INT offset = mem_ref_offset (exp).low;
|
||||
tree bit_offset;
|
||||
base = TREE_OPERAND (base, 0);
|
||||
if (!DECL_P (base))
|
||||
{
|
||||
HOST_WIDE_INT off;
|
||||
base = get_addr_base_and_unit_offset (base, &off);
|
||||
gcc_assert (base);
|
||||
offset += off;
|
||||
}
|
||||
/* If we are expanding a MEM_REF of a non-BLKmode non-addressable
|
||||
decl we must use bitfield operations. */
|
||||
if (DECL_P (base)
|
||||
&& !TREE_ADDRESSABLE (base)
|
||||
&& DECL_MODE (base) != BLKmode
|
||||
&& DECL_RTL_SET_P (base)
|
||||
&& !MEM_P (DECL_RTL (base)))
|
||||
{
|
||||
tree bftype;
|
||||
if (offset == 0
|
||||
&& host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
|
||||
&& (GET_MODE_BITSIZE (DECL_MODE (base))
|
||||
== TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp)))))
|
||||
return expand_expr (build1 (VIEW_CONVERT_EXPR,
|
||||
TREE_TYPE (exp), base),
|
||||
target, tmode, modifier);
|
||||
bit_offset = bitsize_int (offset * BITS_PER_UNIT);
|
||||
bftype = TREE_TYPE (base);
|
||||
if (TYPE_MODE (TREE_TYPE (exp)) != BLKmode)
|
||||
bftype = TREE_TYPE (exp);
|
||||
return expand_expr (build3 (BIT_FIELD_REF, bftype,
|
||||
base,
|
||||
TYPE_SIZE (TREE_TYPE (exp)),
|
||||
bit_offset),
|
||||
target, tmode, modifier);
|
||||
}
|
||||
}
|
||||
address_mode = targetm.addr_space.address_mode (as);
|
||||
op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, address_mode,
|
||||
EXPAND_NORMAL);
|
||||
if (!integer_zerop (TREE_OPERAND (exp, 1)))
|
||||
{
|
||||
rtx off;
|
||||
off = immed_double_int_const (mem_ref_offset (exp), address_mode);
|
||||
op0 = simplify_gen_binary (PLUS, address_mode, op0, off);
|
||||
}
|
||||
op0 = memory_address_addr_space (mode, op0, as);
|
||||
temp = gen_rtx_MEM (mode, op0);
|
||||
set_mem_attributes (temp, exp, 0);
|
||||
set_mem_addr_space (temp, as);
|
||||
if (TREE_THIS_VOLATILE (exp))
|
||||
MEM_VOLATILE_P (temp) = 1;
|
||||
return temp;
|
||||
}
|
||||
|
||||
case ARRAY_REF:
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "langhooks.h"
|
||||
#include "md5.h"
|
||||
#include "gimple.h"
|
||||
#include "tree-flow.h"
|
||||
|
||||
/* Nonzero if we are folding constants inside an initializer; zero
|
||||
otherwise. */
|
||||
|
|
@ -2591,6 +2592,17 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
|
|||
case IMAGPART_EXPR:
|
||||
return OP_SAME (0);
|
||||
|
||||
case MEM_REF:
|
||||
/* Require equal access sizes. We can have incomplete types
|
||||
for array references of variable-sized arrays from the
|
||||
Fortran frontent though. */
|
||||
return ((TYPE_SIZE (TREE_TYPE (arg0)) == TYPE_SIZE (TREE_TYPE (arg1))
|
||||
|| (TYPE_SIZE (TREE_TYPE (arg0))
|
||||
&& TYPE_SIZE (TREE_TYPE (arg1))
|
||||
&& operand_equal_p (TYPE_SIZE (TREE_TYPE (arg0)),
|
||||
TYPE_SIZE (TREE_TYPE (arg1)), flags)))
|
||||
&& OP_SAME (0) && OP_SAME (1));
|
||||
|
||||
case ARRAY_REF:
|
||||
case ARRAY_RANGE_REF:
|
||||
/* Operands 2 and 3 may be null.
|
||||
|
|
@ -7596,6 +7608,9 @@ build_fold_addr_expr_with_type_loc (location_t loc, tree t, tree ptrtype)
|
|||
SET_EXPR_LOCATION (t, loc);
|
||||
}
|
||||
}
|
||||
else if (TREE_CODE (t) == MEM_REF
|
||||
&& integer_zerop (TREE_OPERAND (t, 1)))
|
||||
return TREE_OPERAND (t, 0);
|
||||
else if (TREE_CODE (t) == VIEW_CONVERT_EXPR)
|
||||
{
|
||||
t = build_fold_addr_expr_loc (loc, TREE_OPERAND (t, 0));
|
||||
|
|
@ -8014,6 +8029,9 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
|
|||
if (TREE_CODE (op0) == VIEW_CONVERT_EXPR)
|
||||
return fold_build1_loc (loc, VIEW_CONVERT_EXPR,
|
||||
type, TREE_OPERAND (op0, 0));
|
||||
if (TREE_CODE (op0) == MEM_REF)
|
||||
return fold_build2_loc (loc, MEM_REF, type,
|
||||
TREE_OPERAND (op0, 0), TREE_OPERAND (op0, 1));
|
||||
|
||||
/* For integral conversions with the same precision or pointer
|
||||
conversions use a NOP_EXPR instead. */
|
||||
|
|
@ -8665,6 +8683,11 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
|
|||
else if (TREE_CODE (arg0) == POINTER_PLUS_EXPR)
|
||||
{
|
||||
base0 = TREE_OPERAND (arg0, 0);
|
||||
if (TREE_CODE (base0) == ADDR_EXPR)
|
||||
{
|
||||
base0 = TREE_OPERAND (base0, 0);
|
||||
indirect_base0 = true;
|
||||
}
|
||||
offset0 = TREE_OPERAND (arg0, 1);
|
||||
}
|
||||
|
||||
|
|
@ -8682,6 +8705,11 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
|
|||
else if (TREE_CODE (arg1) == POINTER_PLUS_EXPR)
|
||||
{
|
||||
base1 = TREE_OPERAND (arg1, 0);
|
||||
if (TREE_CODE (base1) == ADDR_EXPR)
|
||||
{
|
||||
base1 = TREE_OPERAND (base1, 0);
|
||||
indirect_base1 = true;
|
||||
}
|
||||
offset1 = TREE_OPERAND (arg1, 1);
|
||||
}
|
||||
|
||||
|
|
@ -9524,6 +9552,36 @@ fold_binary_loc (location_t loc,
|
|||
|
||||
switch (code)
|
||||
{
|
||||
case MEM_REF:
|
||||
/* MEM[&MEM[p, CST1], CST2] -> MEM[p, CST1 + CST2]. */
|
||||
if (TREE_CODE (arg0) == ADDR_EXPR
|
||||
&& TREE_CODE (TREE_OPERAND (arg0, 0)) == MEM_REF)
|
||||
{
|
||||
tree iref = TREE_OPERAND (arg0, 0);
|
||||
return fold_build2 (MEM_REF, type,
|
||||
TREE_OPERAND (iref, 0),
|
||||
int_const_binop (PLUS_EXPR, arg1,
|
||||
TREE_OPERAND (iref, 1), 0));
|
||||
}
|
||||
|
||||
/* MEM[&a.b, CST2] -> MEM[&a, offsetof (a, b) + CST2]. */
|
||||
if (TREE_CODE (arg0) == ADDR_EXPR
|
||||
&& handled_component_p (TREE_OPERAND (arg0, 0)))
|
||||
{
|
||||
tree base;
|
||||
HOST_WIDE_INT coffset;
|
||||
base = get_addr_base_and_unit_offset (TREE_OPERAND (arg0, 0),
|
||||
&coffset);
|
||||
if (!base)
|
||||
return NULL_TREE;
|
||||
return fold_build2 (MEM_REF, type,
|
||||
build_fold_addr_expr (base),
|
||||
int_const_binop (PLUS_EXPR, arg1,
|
||||
size_int (coffset), 0));
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
|
||||
case POINTER_PLUS_EXPR:
|
||||
/* 0 +p index -> (type)index */
|
||||
if (integer_zerop (arg0))
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ get_symbol_constant_value (tree sym)
|
|||
bool
|
||||
may_propagate_address_into_dereference (tree addr, tree deref)
|
||||
{
|
||||
gcc_assert (INDIRECT_REF_P (deref)
|
||||
gcc_assert (TREE_CODE (deref) == MEM_REF
|
||||
&& TREE_CODE (addr) == ADDR_EXPR);
|
||||
|
||||
/* Don't propagate if ADDR's operand has incomplete type. */
|
||||
|
|
@ -108,15 +108,12 @@ may_propagate_address_into_dereference (tree addr, tree deref)
|
|||
|
||||
|
||||
/* A subroutine of fold_stmt. Attempts to fold *(A+O) to A[X].
|
||||
BASE is an array type. OFFSET is a byte displacement. ORIG_TYPE
|
||||
is the desired result type.
|
||||
BASE is an array type. OFFSET is a byte displacement.
|
||||
|
||||
LOC is the location of the original expression. */
|
||||
|
||||
static tree
|
||||
maybe_fold_offset_to_array_ref (location_t loc, tree base, tree offset,
|
||||
tree orig_type,
|
||||
bool allow_negative_idx)
|
||||
maybe_fold_offset_to_array_ref (location_t loc, tree base, tree offset)
|
||||
{
|
||||
tree min_idx, idx, idx_type, elt_offset = integer_zero_node;
|
||||
tree array_type, elt_type, elt_size;
|
||||
|
|
@ -145,8 +142,6 @@ maybe_fold_offset_to_array_ref (location_t loc, tree base, tree offset,
|
|||
if (TREE_CODE (array_type) != ARRAY_TYPE)
|
||||
return NULL_TREE;
|
||||
elt_type = TREE_TYPE (array_type);
|
||||
if (!useless_type_conversion_p (orig_type, elt_type))
|
||||
return NULL_TREE;
|
||||
|
||||
/* Use signed size type for intermediate computation on the index. */
|
||||
idx_type = ssizetype;
|
||||
|
|
@ -219,34 +214,22 @@ maybe_fold_offset_to_array_ref (location_t loc, tree base, tree offset,
|
|||
char *(c[4]);
|
||||
c[3][2];
|
||||
should not be simplified into (*c)[14] or tree-vrp will
|
||||
give false warnings. The same is true for
|
||||
struct A { long x; char d[0]; } *a;
|
||||
(char *)a - 4;
|
||||
which should be not folded to &a->d[-8]. */
|
||||
if (domain_type
|
||||
&& TYPE_MAX_VALUE (domain_type)
|
||||
&& TREE_CODE (TYPE_MAX_VALUE (domain_type)) == INTEGER_CST)
|
||||
give false warnings.
|
||||
This is only an issue for multi-dimensional arrays. */
|
||||
if (TREE_CODE (elt_type) == ARRAY_TYPE
|
||||
&& domain_type)
|
||||
{
|
||||
tree up_bound = TYPE_MAX_VALUE (domain_type);
|
||||
|
||||
if (tree_int_cst_lt (up_bound, idx)
|
||||
/* Accesses after the end of arrays of size 0 (gcc
|
||||
extension) and 1 are likely intentional ("struct
|
||||
hack"). */
|
||||
&& compare_tree_int (up_bound, 1) > 0)
|
||||
if (TYPE_MAX_VALUE (domain_type)
|
||||
&& TREE_CODE (TYPE_MAX_VALUE (domain_type)) == INTEGER_CST
|
||||
&& tree_int_cst_lt (TYPE_MAX_VALUE (domain_type), idx))
|
||||
return NULL_TREE;
|
||||
else if (TYPE_MIN_VALUE (domain_type)
|
||||
&& TREE_CODE (TYPE_MIN_VALUE (domain_type)) == INTEGER_CST
|
||||
&& tree_int_cst_lt (idx, TYPE_MIN_VALUE (domain_type)))
|
||||
return NULL_TREE;
|
||||
else if (compare_tree_int (idx, 0) < 0)
|
||||
return NULL_TREE;
|
||||
}
|
||||
if (domain_type
|
||||
&& TYPE_MIN_VALUE (domain_type))
|
||||
{
|
||||
if (!allow_negative_idx
|
||||
&& TREE_CODE (TYPE_MIN_VALUE (domain_type)) == INTEGER_CST
|
||||
&& tree_int_cst_lt (idx, TYPE_MIN_VALUE (domain_type)))
|
||||
return NULL_TREE;
|
||||
}
|
||||
else if (!allow_negative_idx
|
||||
&& compare_tree_int (idx, 0) < 0)
|
||||
return NULL_TREE;
|
||||
|
||||
{
|
||||
tree t = build4 (ARRAY_REF, elt_type, base, idx, NULL_TREE, NULL_TREE);
|
||||
|
|
@ -256,340 +239,55 @@ maybe_fold_offset_to_array_ref (location_t loc, tree base, tree offset,
|
|||
}
|
||||
|
||||
|
||||
/* Attempt to fold *(S+O) to S.X.
|
||||
BASE is a record type. OFFSET is a byte displacement. ORIG_TYPE
|
||||
is the desired result type.
|
||||
|
||||
LOC is the location of the original expression. */
|
||||
|
||||
static tree
|
||||
maybe_fold_offset_to_component_ref (location_t loc, tree record_type,
|
||||
tree base, tree offset, tree orig_type)
|
||||
{
|
||||
tree f, t, field_type, tail_array_field, field_offset;
|
||||
tree ret;
|
||||
tree new_base;
|
||||
|
||||
if (TREE_CODE (record_type) != RECORD_TYPE
|
||||
&& TREE_CODE (record_type) != UNION_TYPE
|
||||
&& TREE_CODE (record_type) != QUAL_UNION_TYPE)
|
||||
return NULL_TREE;
|
||||
|
||||
/* Short-circuit silly cases. */
|
||||
if (useless_type_conversion_p (record_type, orig_type))
|
||||
return NULL_TREE;
|
||||
|
||||
tail_array_field = NULL_TREE;
|
||||
for (f = TYPE_FIELDS (record_type); f ; f = TREE_CHAIN (f))
|
||||
{
|
||||
int cmp;
|
||||
|
||||
if (TREE_CODE (f) != FIELD_DECL)
|
||||
continue;
|
||||
if (DECL_BIT_FIELD (f))
|
||||
continue;
|
||||
|
||||
if (!DECL_FIELD_OFFSET (f))
|
||||
continue;
|
||||
field_offset = byte_position (f);
|
||||
if (TREE_CODE (field_offset) != INTEGER_CST)
|
||||
continue;
|
||||
|
||||
/* ??? Java creates "interesting" fields for representing base classes.
|
||||
They have no name, and have no context. With no context, we get into
|
||||
trouble with nonoverlapping_component_refs_p. Skip them. */
|
||||
if (!DECL_FIELD_CONTEXT (f))
|
||||
continue;
|
||||
|
||||
/* The previous array field isn't at the end. */
|
||||
tail_array_field = NULL_TREE;
|
||||
|
||||
/* Check to see if this offset overlaps with the field. */
|
||||
cmp = tree_int_cst_compare (field_offset, offset);
|
||||
if (cmp > 0)
|
||||
continue;
|
||||
|
||||
field_type = TREE_TYPE (f);
|
||||
|
||||
/* Here we exactly match the offset being checked. If the types match,
|
||||
then we can return that field. */
|
||||
if (cmp == 0
|
||||
&& useless_type_conversion_p (orig_type, field_type))
|
||||
{
|
||||
t = fold_build3 (COMPONENT_REF, field_type, base, f, NULL_TREE);
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Don't care about offsets into the middle of scalars. */
|
||||
if (!AGGREGATE_TYPE_P (field_type))
|
||||
continue;
|
||||
|
||||
/* Check for array at the end of the struct. This is often
|
||||
used as for flexible array members. We should be able to
|
||||
turn this into an array access anyway. */
|
||||
if (TREE_CODE (field_type) == ARRAY_TYPE)
|
||||
tail_array_field = f;
|
||||
|
||||
/* Check the end of the field against the offset. */
|
||||
if (!DECL_SIZE_UNIT (f)
|
||||
|| TREE_CODE (DECL_SIZE_UNIT (f)) != INTEGER_CST)
|
||||
continue;
|
||||
t = int_const_binop (MINUS_EXPR, offset, field_offset, 1);
|
||||
if (!tree_int_cst_lt (t, DECL_SIZE_UNIT (f)))
|
||||
continue;
|
||||
|
||||
/* If we matched, then set offset to the displacement into
|
||||
this field. */
|
||||
new_base = fold_build3 (COMPONENT_REF, field_type, base, f, NULL_TREE);
|
||||
SET_EXPR_LOCATION (new_base, loc);
|
||||
|
||||
/* Recurse to possibly find the match. */
|
||||
ret = maybe_fold_offset_to_array_ref (loc, new_base, t, orig_type,
|
||||
f == TYPE_FIELDS (record_type));
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = maybe_fold_offset_to_component_ref (loc, field_type, new_base, t,
|
||||
orig_type);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!tail_array_field)
|
||||
return NULL_TREE;
|
||||
|
||||
f = tail_array_field;
|
||||
field_type = TREE_TYPE (f);
|
||||
offset = int_const_binop (MINUS_EXPR, offset, byte_position (f), 1);
|
||||
|
||||
/* If we get here, we've got an aggregate field, and a possibly
|
||||
nonzero offset into them. Recurse and hope for a valid match. */
|
||||
base = fold_build3 (COMPONENT_REF, field_type, base, f, NULL_TREE);
|
||||
SET_EXPR_LOCATION (base, loc);
|
||||
|
||||
t = maybe_fold_offset_to_array_ref (loc, base, offset, orig_type,
|
||||
f == TYPE_FIELDS (record_type));
|
||||
if (t)
|
||||
return t;
|
||||
return maybe_fold_offset_to_component_ref (loc, field_type, base, offset,
|
||||
orig_type);
|
||||
}
|
||||
|
||||
/* Attempt to express (ORIG_TYPE)BASE+OFFSET as BASE->field_of_orig_type
|
||||
or BASE[index] or by combination of those.
|
||||
|
||||
/* Attempt to express (ORIG_TYPE)BASE+OFFSET as BASE[index].
|
||||
LOC is the location of original expression.
|
||||
|
||||
Before attempting the conversion strip off existing ADDR_EXPRs and
|
||||
handled component refs. */
|
||||
Before attempting the conversion strip off existing ADDR_EXPRs. */
|
||||
|
||||
tree
|
||||
maybe_fold_offset_to_reference (location_t loc, tree base, tree offset,
|
||||
tree orig_type)
|
||||
{
|
||||
tree ret;
|
||||
tree type;
|
||||
|
||||
STRIP_NOPS (base);
|
||||
if (TREE_CODE (base) != ADDR_EXPR)
|
||||
return NULL_TREE;
|
||||
|
||||
base = TREE_OPERAND (base, 0);
|
||||
|
||||
/* Handle case where existing COMPONENT_REF pick e.g. wrong field of union,
|
||||
so it needs to be removed and new COMPONENT_REF constructed.
|
||||
The wrong COMPONENT_REF are often constructed by folding the
|
||||
(type *)&object within the expression (type *)&object+offset */
|
||||
if (handled_component_p (base))
|
||||
{
|
||||
HOST_WIDE_INT sub_offset, size, maxsize;
|
||||
tree newbase;
|
||||
newbase = get_ref_base_and_extent (base, &sub_offset,
|
||||
&size, &maxsize);
|
||||
gcc_assert (newbase);
|
||||
if (size == maxsize
|
||||
&& size != -1
|
||||
&& !(sub_offset & (BITS_PER_UNIT - 1)))
|
||||
{
|
||||
base = newbase;
|
||||
if (sub_offset)
|
||||
offset = int_const_binop (PLUS_EXPR, offset,
|
||||
build_int_cst (TREE_TYPE (offset),
|
||||
sub_offset / BITS_PER_UNIT), 1);
|
||||
}
|
||||
}
|
||||
if (useless_type_conversion_p (orig_type, TREE_TYPE (base))
|
||||
if (types_compatible_p (orig_type, TREE_TYPE (base))
|
||||
&& integer_zerop (offset))
|
||||
return base;
|
||||
type = TREE_TYPE (base);
|
||||
|
||||
ret = maybe_fold_offset_to_component_ref (loc, type, base, offset, orig_type);
|
||||
if (!ret)
|
||||
ret = maybe_fold_offset_to_array_ref (loc, base, offset, orig_type, true);
|
||||
|
||||
return ret;
|
||||
ret = maybe_fold_offset_to_array_ref (loc, base, offset);
|
||||
if (ret && types_compatible_p (orig_type, TREE_TYPE (ret)))
|
||||
return ret;
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Attempt to express (ORIG_TYPE)&BASE+OFFSET as &BASE->field_of_orig_type
|
||||
or &BASE[index] or by combination of those.
|
||||
|
||||
LOC is the location of the original expression.
|
||||
|
||||
Before attempting the conversion strip off existing component refs. */
|
||||
/* Attempt to express (ORIG_TYPE)ADDR+OFFSET as (*ADDR)[index].
|
||||
LOC is the location of the original expression. */
|
||||
|
||||
tree
|
||||
maybe_fold_offset_to_address (location_t loc, tree addr, tree offset,
|
||||
tree orig_type)
|
||||
{
|
||||
tree t;
|
||||
tree base, ret;
|
||||
|
||||
gcc_assert (POINTER_TYPE_P (TREE_TYPE (addr))
|
||||
&& POINTER_TYPE_P (orig_type));
|
||||
|
||||
t = maybe_fold_offset_to_reference (loc, addr, offset,
|
||||
TREE_TYPE (orig_type));
|
||||
if (t != NULL_TREE)
|
||||
STRIP_NOPS (addr);
|
||||
if (TREE_CODE (addr) != ADDR_EXPR)
|
||||
return NULL_TREE;
|
||||
base = TREE_OPERAND (addr, 0);
|
||||
ret = maybe_fold_offset_to_array_ref (loc, base, offset);
|
||||
if (ret)
|
||||
{
|
||||
tree orig = addr;
|
||||
tree ptr_type;
|
||||
|
||||
/* For __builtin_object_size to function correctly we need to
|
||||
make sure not to fold address arithmetic so that we change
|
||||
reference from one array to another. This would happen for
|
||||
example for
|
||||
|
||||
struct X { char s1[10]; char s2[10] } s;
|
||||
char *foo (void) { return &s.s2[-4]; }
|
||||
|
||||
where we need to avoid generating &s.s1[6]. As the C and
|
||||
C++ frontends create different initial trees
|
||||
(char *) &s.s1 + -4 vs. &s.s1[-4] we have to do some
|
||||
sophisticated comparisons here. Note that checking for the
|
||||
condition after the fact is easier than trying to avoid doing
|
||||
the folding. */
|
||||
STRIP_NOPS (orig);
|
||||
if (TREE_CODE (orig) == ADDR_EXPR)
|
||||
orig = TREE_OPERAND (orig, 0);
|
||||
if ((TREE_CODE (orig) == ARRAY_REF
|
||||
|| (TREE_CODE (orig) == COMPONENT_REF
|
||||
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (orig, 1))) == ARRAY_TYPE))
|
||||
&& (TREE_CODE (t) == ARRAY_REF
|
||||
|| TREE_CODE (t) == COMPONENT_REF)
|
||||
&& !operand_equal_p (TREE_CODE (orig) == ARRAY_REF
|
||||
? TREE_OPERAND (orig, 0) : orig,
|
||||
TREE_CODE (t) == ARRAY_REF
|
||||
? TREE_OPERAND (t, 0) : t, 0))
|
||||
ret = build_fold_addr_expr (ret);
|
||||
if (!useless_type_conversion_p (orig_type, TREE_TYPE (ret)))
|
||||
return NULL_TREE;
|
||||
|
||||
ptr_type = build_pointer_type (TREE_TYPE (t));
|
||||
if (!useless_type_conversion_p (orig_type, ptr_type))
|
||||
return NULL_TREE;
|
||||
return build_fold_addr_expr_with_type_loc (loc, t, ptr_type);
|
||||
SET_EXPR_LOCATION (ret, loc);
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* A subroutine of fold_stmt. Attempt to simplify *(BASE+OFFSET).
|
||||
Return the simplified expression, or NULL if nothing could be done. */
|
||||
|
||||
static tree
|
||||
maybe_fold_stmt_indirect (tree expr, tree base, tree offset)
|
||||
{
|
||||
tree t;
|
||||
bool volatile_p = TREE_THIS_VOLATILE (expr);
|
||||
location_t loc = EXPR_LOCATION (expr);
|
||||
|
||||
/* We may well have constructed a double-nested PLUS_EXPR via multiple
|
||||
substitutions. Fold that down to one. Remove NON_LVALUE_EXPRs that
|
||||
are sometimes added. */
|
||||
base = fold (base);
|
||||
STRIP_TYPE_NOPS (base);
|
||||
TREE_OPERAND (expr, 0) = base;
|
||||
|
||||
/* One possibility is that the address reduces to a string constant. */
|
||||
t = fold_read_from_constant_string (expr);
|
||||
if (t)
|
||||
return t;
|
||||
|
||||
/* Add in any offset from a POINTER_PLUS_EXPR. */
|
||||
if (TREE_CODE (base) == POINTER_PLUS_EXPR)
|
||||
{
|
||||
tree offset2;
|
||||
|
||||
offset2 = TREE_OPERAND (base, 1);
|
||||
if (TREE_CODE (offset2) != INTEGER_CST)
|
||||
return NULL_TREE;
|
||||
base = TREE_OPERAND (base, 0);
|
||||
|
||||
offset = fold_convert (sizetype,
|
||||
int_const_binop (PLUS_EXPR, offset, offset2, 1));
|
||||
}
|
||||
|
||||
if (TREE_CODE (base) == ADDR_EXPR)
|
||||
{
|
||||
tree base_addr = base;
|
||||
|
||||
/* Strip the ADDR_EXPR. */
|
||||
base = TREE_OPERAND (base, 0);
|
||||
|
||||
/* Fold away CONST_DECL to its value, if the type is scalar. */
|
||||
if (TREE_CODE (base) == CONST_DECL
|
||||
&& is_gimple_min_invariant (DECL_INITIAL (base)))
|
||||
return DECL_INITIAL (base);
|
||||
|
||||
/* If there is no offset involved simply return the folded base. */
|
||||
if (integer_zerop (offset))
|
||||
return base;
|
||||
|
||||
/* Try folding *(&B+O) to B.X. */
|
||||
t = maybe_fold_offset_to_reference (loc, base_addr, offset,
|
||||
TREE_TYPE (expr));
|
||||
if (t)
|
||||
{
|
||||
/* Preserve volatileness of the original expression.
|
||||
We can end up with a plain decl here which is shared
|
||||
and we shouldn't mess with its flags. */
|
||||
if (!SSA_VAR_P (t))
|
||||
TREE_THIS_VOLATILE (t) = volatile_p;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We can get here for out-of-range string constant accesses,
|
||||
such as "_"[3]. Bail out of the entire substitution search
|
||||
and arrange for the entire statement to be replaced by a
|
||||
call to __builtin_trap. In all likelihood this will all be
|
||||
constant-folded away, but in the meantime we can't leave with
|
||||
something that get_expr_operands can't understand. */
|
||||
|
||||
t = base;
|
||||
STRIP_NOPS (t);
|
||||
if (TREE_CODE (t) == ADDR_EXPR
|
||||
&& TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST)
|
||||
{
|
||||
/* FIXME: Except that this causes problems elsewhere with dead
|
||||
code not being deleted, and we die in the rtl expanders
|
||||
because we failed to remove some ssa_name. In the meantime,
|
||||
just return zero. */
|
||||
/* FIXME2: This condition should be signaled by
|
||||
fold_read_from_constant_string directly, rather than
|
||||
re-checking for it here. */
|
||||
return integer_zero_node;
|
||||
}
|
||||
|
||||
/* Try folding *(B+O) to B->X. Still an improvement. */
|
||||
if (POINTER_TYPE_P (TREE_TYPE (base)))
|
||||
{
|
||||
t = maybe_fold_offset_to_reference (loc, base, offset,
|
||||
TREE_TYPE (expr));
|
||||
if (t)
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise we had an offset that we could not simplify. */
|
||||
return NULL_TREE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -622,18 +320,17 @@ maybe_fold_stmt_addition (location_t loc, tree res_type, tree op0, tree op1)
|
|||
/* Or op0 should now be A[0] and the non-constant offset defined
|
||||
via a multiplication by the array element size. */
|
||||
if (TREE_CODE (op0) == ARRAY_REF
|
||||
&& integer_zerop (TREE_OPERAND (op0, 1))
|
||||
&& TREE_CODE (op1) == SSA_NAME
|
||||
&& host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (op0)), 1))
|
||||
{
|
||||
gimple offset_def = SSA_NAME_DEF_STMT (op1);
|
||||
if (!is_gimple_assign (offset_def))
|
||||
return NULL_TREE;
|
||||
|
||||
/* As we will end up creating a variable index array access
|
||||
in the outermost array dimension make sure there isn't
|
||||
a more inner array that the index could overflow to. */
|
||||
if (TREE_CODE (TREE_OPERAND (op0, 0)) == ARRAY_REF)
|
||||
&& TREE_CODE (TREE_OPERAND (op0, 0)) != ARRAY_REF
|
||||
&& integer_zerop (TREE_OPERAND (op0, 1))
|
||||
&& TREE_CODE (op1) == SSA_NAME)
|
||||
{
|
||||
gimple offset_def = SSA_NAME_DEF_STMT (op1);
|
||||
tree elsz = TYPE_SIZE_UNIT (TREE_TYPE (op0));
|
||||
if (!host_integerp (elsz, 1)
|
||||
|| !is_gimple_assign (offset_def))
|
||||
return NULL_TREE;
|
||||
|
||||
/* Do not build array references of something that we can't
|
||||
|
|
@ -644,15 +341,14 @@ maybe_fold_stmt_addition (location_t loc, tree res_type, tree op0, tree op1)
|
|||
|
||||
if (gimple_assign_rhs_code (offset_def) == MULT_EXPR
|
||||
&& TREE_CODE (gimple_assign_rhs2 (offset_def)) == INTEGER_CST
|
||||
&& tree_int_cst_equal (gimple_assign_rhs2 (offset_def),
|
||||
TYPE_SIZE_UNIT (TREE_TYPE (op0))))
|
||||
&& tree_int_cst_equal (gimple_assign_rhs2 (offset_def), elsz))
|
||||
return build_fold_addr_expr
|
||||
(build4 (ARRAY_REF, TREE_TYPE (op0),
|
||||
TREE_OPERAND (op0, 0),
|
||||
gimple_assign_rhs1 (offset_def),
|
||||
TREE_OPERAND (op0, 2),
|
||||
TREE_OPERAND (op0, 3)));
|
||||
else if (integer_onep (TYPE_SIZE_UNIT (TREE_TYPE (op0)))
|
||||
else if (integer_onep (elsz)
|
||||
&& gimple_assign_rhs_code (offset_def) != MULT_EXPR)
|
||||
return build_fold_addr_expr
|
||||
(build4 (ARRAY_REF, TREE_TYPE (op0),
|
||||
|
|
@ -661,6 +357,38 @@ maybe_fold_stmt_addition (location_t loc, tree res_type, tree op0, tree op1)
|
|||
TREE_OPERAND (op0, 2),
|
||||
TREE_OPERAND (op0, 3)));
|
||||
}
|
||||
else if (TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE
|
||||
/* Dto. */
|
||||
&& TREE_CODE (TREE_TYPE (TREE_TYPE (op0))) != ARRAY_TYPE
|
||||
&& TREE_CODE (op1) == SSA_NAME)
|
||||
{
|
||||
gimple offset_def = SSA_NAME_DEF_STMT (op1);
|
||||
tree elsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (op0)));
|
||||
if (!host_integerp (elsz, 1)
|
||||
|| !is_gimple_assign (offset_def))
|
||||
return NULL_TREE;
|
||||
|
||||
/* Do not build array references of something that we can't
|
||||
see the true number of array dimensions for. */
|
||||
if (!DECL_P (op0)
|
||||
&& !handled_component_p (op0))
|
||||
return NULL_TREE;
|
||||
|
||||
if (gimple_assign_rhs_code (offset_def) == MULT_EXPR
|
||||
&& TREE_CODE (gimple_assign_rhs2 (offset_def)) == INTEGER_CST
|
||||
&& tree_int_cst_equal (gimple_assign_rhs2 (offset_def), elsz))
|
||||
return build_fold_addr_expr
|
||||
(build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (op0)),
|
||||
op0, gimple_assign_rhs1 (offset_def),
|
||||
integer_zero_node, NULL_TREE));
|
||||
else if (integer_onep (elsz)
|
||||
&& gimple_assign_rhs_code (offset_def) != MULT_EXPR)
|
||||
return build_fold_addr_expr
|
||||
(build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (op0)),
|
||||
op0, op1,
|
||||
integer_zero_node, NULL_TREE));
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
|
|
@ -715,13 +443,12 @@ maybe_fold_stmt_addition (location_t loc, tree res_type, tree op0, tree op1)
|
|||
ptd_type = TREE_TYPE (TREE_TYPE (op0));
|
||||
|
||||
/* At which point we can try some of the same things as for indirects. */
|
||||
t = maybe_fold_offset_to_array_ref (loc, op0, op1, ptd_type, true);
|
||||
if (!t)
|
||||
t = maybe_fold_offset_to_component_ref (loc, TREE_TYPE (op0), op0, op1,
|
||||
ptd_type);
|
||||
t = maybe_fold_offset_to_array_ref (loc, op0, op1);
|
||||
if (t)
|
||||
{
|
||||
t = build1 (ADDR_EXPR, res_type, t);
|
||||
t = build_fold_addr_expr (t);
|
||||
if (!useless_type_conversion_p (res_type, TREE_TYPE (t)))
|
||||
return NULL_TREE;
|
||||
SET_EXPR_LOCATION (t, loc);
|
||||
}
|
||||
|
||||
|
|
@ -759,19 +486,39 @@ maybe_fold_reference (tree expr, bool is_lhs)
|
|||
while (handled_component_p (*t))
|
||||
t = &TREE_OPERAND (*t, 0);
|
||||
|
||||
if (TREE_CODE (*t) == INDIRECT_REF)
|
||||
/* Fold back MEM_REFs to reference trees. */
|
||||
if (TREE_CODE (*t) == MEM_REF
|
||||
&& TREE_CODE (TREE_OPERAND (*t, 0)) == ADDR_EXPR
|
||||
&& integer_zerop (TREE_OPERAND (*t, 1))
|
||||
&& (TREE_THIS_VOLATILE (*t)
|
||||
== TREE_THIS_VOLATILE (TREE_OPERAND (TREE_OPERAND (*t, 0), 0)))
|
||||
&& !TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (TREE_OPERAND (*t, 1)))
|
||||
&& (TYPE_MAIN_VARIANT (TREE_TYPE (*t))
|
||||
== TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (TREE_OPERAND (*t, 1)))))
|
||||
/* We have to look out here to not drop a required conversion
|
||||
from the rhs to the lhs if is_lhs, but we don't have the
|
||||
rhs here to verify that. Thus require strict type
|
||||
compatibility. */
|
||||
&& types_compatible_p (TREE_TYPE (*t),
|
||||
TREE_TYPE (TREE_OPERAND
|
||||
(TREE_OPERAND (*t, 0), 0))))
|
||||
{
|
||||
tree tem = maybe_fold_stmt_indirect (*t, TREE_OPERAND (*t, 0),
|
||||
integer_zero_node);
|
||||
/* Avoid folding *"abc" = 5 into 'a' = 5. */
|
||||
if (is_lhs && tem && CONSTANT_CLASS_P (tem))
|
||||
tem = NULL_TREE;
|
||||
if (!tem
|
||||
&& TREE_CODE (TREE_OPERAND (*t, 0)) == ADDR_EXPR)
|
||||
/* If we had a good reason for propagating the address here,
|
||||
make sure we end up with valid gimple. See PR34989. */
|
||||
tem = TREE_OPERAND (TREE_OPERAND (*t, 0), 0);
|
||||
|
||||
tree tem;
|
||||
*t = TREE_OPERAND (TREE_OPERAND (*t, 0), 0);
|
||||
tem = maybe_fold_reference (expr, is_lhs);
|
||||
if (tem)
|
||||
return tem;
|
||||
return expr;
|
||||
}
|
||||
/* Canonicalize MEM_REFs invariant address operand. */
|
||||
else if (TREE_CODE (*t) == MEM_REF
|
||||
&& TREE_CODE (TREE_OPERAND (*t, 0)) == ADDR_EXPR
|
||||
&& !DECL_P (TREE_OPERAND (TREE_OPERAND (*t, 0), 0))
|
||||
&& !CONSTANT_CLASS_P (TREE_OPERAND (TREE_OPERAND (*t, 0), 0)))
|
||||
{
|
||||
tree tem = fold_binary (MEM_REF, TREE_TYPE (*t),
|
||||
TREE_OPERAND (*t, 0),
|
||||
TREE_OPERAND (*t, 1));
|
||||
if (tem)
|
||||
{
|
||||
*t = tem;
|
||||
|
|
@ -863,10 +610,18 @@ fold_gimple_assign (gimple_stmt_iterator *si)
|
|||
|
||||
else if (TREE_CODE (rhs) == ADDR_EXPR)
|
||||
{
|
||||
tree tem = maybe_fold_reference (TREE_OPERAND (rhs, 0), true);
|
||||
if (tem)
|
||||
tree ref = TREE_OPERAND (rhs, 0);
|
||||
tree tem = maybe_fold_reference (ref, true);
|
||||
if (tem
|
||||
&& TREE_CODE (tem) == MEM_REF
|
||||
&& integer_zerop (TREE_OPERAND (tem, 1)))
|
||||
result = fold_convert (TREE_TYPE (rhs), TREE_OPERAND (tem, 0));
|
||||
else if (tem)
|
||||
result = fold_convert (TREE_TYPE (rhs),
|
||||
build_fold_addr_expr_loc (loc, tem));
|
||||
else if (TREE_CODE (ref) == MEM_REF
|
||||
&& integer_zerop (TREE_OPERAND (ref, 1)))
|
||||
result = fold_convert (TREE_TYPE (rhs), TREE_OPERAND (ref, 0));
|
||||
}
|
||||
|
||||
else if (TREE_CODE (rhs) == CONSTRUCTOR
|
||||
|
|
@ -1580,7 +1335,7 @@ gimple_get_relevant_ref_binfo (tree ref, tree known_binfo)
|
|||
return TYPE_BINFO (TREE_TYPE (ref));
|
||||
else if (known_binfo
|
||||
&& (TREE_CODE (ref) == SSA_NAME
|
||||
|| TREE_CODE (ref) == INDIRECT_REF))
|
||||
|| TREE_CODE (ref) == MEM_REF))
|
||||
return known_binfo;
|
||||
else
|
||||
return NULL_TREE;
|
||||
|
|
|
|||
41
gcc/gimple.c
41
gcc/gimple.c
|
|
@ -2595,7 +2595,8 @@ is_gimple_condexpr (tree t)
|
|||
bool
|
||||
is_gimple_addressable (tree t)
|
||||
{
|
||||
return (is_gimple_id (t) || handled_component_p (t) || INDIRECT_REF_P (t));
|
||||
return (is_gimple_id (t) || handled_component_p (t)
|
||||
|| TREE_CODE (t) == MEM_REF);
|
||||
}
|
||||
|
||||
/* Return true if T is a valid gimple constant. */
|
||||
|
|
@ -2646,7 +2647,7 @@ is_gimple_address (const_tree t)
|
|||
op = TREE_OPERAND (op, 0);
|
||||
}
|
||||
|
||||
if (CONSTANT_CLASS_P (op) || INDIRECT_REF_P (op))
|
||||
if (CONSTANT_CLASS_P (op) || TREE_CODE (op) == MEM_REF)
|
||||
return true;
|
||||
|
||||
switch (TREE_CODE (op))
|
||||
|
|
@ -2706,8 +2707,18 @@ is_gimple_invariant_address (const_tree t)
|
|||
return false;
|
||||
|
||||
op = strip_invariant_refs (TREE_OPERAND (t, 0));
|
||||
if (!op)
|
||||
return false;
|
||||
|
||||
return op && (CONSTANT_CLASS_P (op) || decl_address_invariant_p (op));
|
||||
if (TREE_CODE (op) == MEM_REF)
|
||||
{
|
||||
const_tree op0 = TREE_OPERAND (op, 0);
|
||||
return (TREE_CODE (op0) == ADDR_EXPR
|
||||
&& (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))
|
||||
|| decl_address_invariant_p (TREE_OPERAND (op0, 0))));
|
||||
}
|
||||
|
||||
return CONSTANT_CLASS_P (op) || decl_address_invariant_p (op);
|
||||
}
|
||||
|
||||
/* Return true if T is a gimple invariant address at IPA level
|
||||
|
|
@ -2924,7 +2935,7 @@ is_gimple_min_lval (tree t)
|
|||
{
|
||||
if (!(t = CONST_CAST_TREE (strip_invariant_refs (t))))
|
||||
return false;
|
||||
return (is_gimple_id (t) || TREE_CODE (t) == INDIRECT_REF);
|
||||
return (is_gimple_id (t) || TREE_CODE (t) == MEM_REF);
|
||||
}
|
||||
|
||||
/* Return true if T is a typecast operation. */
|
||||
|
|
@ -2944,6 +2955,18 @@ is_gimple_call_addr (tree t)
|
|||
return (TREE_CODE (t) == OBJ_TYPE_REF || is_gimple_val (t));
|
||||
}
|
||||
|
||||
/* Return true if T is a valid address operand of a MEM_REF. */
|
||||
|
||||
bool
|
||||
is_gimple_mem_ref_addr (tree t)
|
||||
{
|
||||
return (is_gimple_reg (t)
|
||||
|| TREE_CODE (t) == INTEGER_CST
|
||||
|| (TREE_CODE (t) == ADDR_EXPR
|
||||
&& (CONSTANT_CLASS_P (TREE_OPERAND (t, 0))
|
||||
|| decl_address_invariant_p (TREE_OPERAND (t, 0)))));
|
||||
}
|
||||
|
||||
/* If T makes a function call, return the corresponding CALL_EXPR operand.
|
||||
Otherwise, return NULL_TREE. */
|
||||
|
||||
|
|
@ -2975,10 +2998,15 @@ get_base_address (tree t)
|
|||
while (handled_component_p (t))
|
||||
t = TREE_OPERAND (t, 0);
|
||||
|
||||
if (TREE_CODE (t) == MEM_REF
|
||||
&& TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR)
|
||||
t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
|
||||
|
||||
if (SSA_VAR_P (t)
|
||||
|| TREE_CODE (t) == STRING_CST
|
||||
|| TREE_CODE (t) == CONSTRUCTOR
|
||||
|| INDIRECT_REF_P (t))
|
||||
|| INDIRECT_REF_P (t)
|
||||
|| TREE_CODE (t) == MEM_REF)
|
||||
return t;
|
||||
else
|
||||
return NULL_TREE;
|
||||
|
|
@ -4418,7 +4446,7 @@ count_ptr_derefs (tree *tp, int *walk_subtrees, void *data)
|
|||
return NULL_TREE;
|
||||
}
|
||||
|
||||
if (INDIRECT_REF_P (*tp) && TREE_OPERAND (*tp, 0) == count_p->ptr)
|
||||
if (TREE_CODE (*tp) == MEM_REF && TREE_OPERAND (*tp, 0) == count_p->ptr)
|
||||
{
|
||||
if (wi_p->is_lhs)
|
||||
count_p->num_stores++;
|
||||
|
|
@ -4491,6 +4519,7 @@ get_base_loadstore (tree op)
|
|||
op = TREE_OPERAND (op, 0);
|
||||
if (DECL_P (op)
|
||||
|| INDIRECT_REF_P (op)
|
||||
|| TREE_CODE (op) == MEM_REF
|
||||
|| TREE_CODE (op) == TARGET_MEM_REF)
|
||||
return op;
|
||||
return NULL_TREE;
|
||||
|
|
|
|||
17
gcc/gimple.h
17
gcc/gimple.h
|
|
@ -933,6 +933,8 @@ extern bool is_gimple_ip_invariant (const_tree);
|
|||
extern bool is_gimple_val (tree);
|
||||
/* Returns true iff T is a GIMPLE asm statement input. */
|
||||
extern bool is_gimple_asm_val (tree);
|
||||
/* Returns true iff T is a valid address operand of a MEM_REF. */
|
||||
bool is_gimple_mem_ref_addr (tree);
|
||||
/* Returns true iff T is a valid rhs for a MODIFY_EXPR where the LHS is a
|
||||
GIMPLE temporary, a renamed user variable, or something else,
|
||||
respectively. */
|
||||
|
|
@ -2037,7 +2039,18 @@ gimple_call_fndecl (const_gimple gs)
|
|||
{
|
||||
tree addr = gimple_call_fn (gs);
|
||||
if (TREE_CODE (addr) == ADDR_EXPR)
|
||||
return TREE_OPERAND (addr, 0);
|
||||
{
|
||||
tree fndecl = TREE_OPERAND (addr, 0);
|
||||
if (TREE_CODE (fndecl) == MEM_REF)
|
||||
{
|
||||
if (TREE_CODE (TREE_OPERAND (fndecl, 0)) == ADDR_EXPR
|
||||
&& integer_zerop (TREE_OPERAND (fndecl, 1)))
|
||||
return TREE_OPERAND (TREE_OPERAND (fndecl, 0), 0);
|
||||
else
|
||||
return NULL_TREE;
|
||||
}
|
||||
return TREE_OPERAND (addr, 0);
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
|
|
@ -4857,8 +4870,8 @@ void gimplify_and_update_call_from_tree (gimple_stmt_iterator *, tree);
|
|||
tree gimple_fold_builtin (gimple);
|
||||
bool fold_stmt (gimple_stmt_iterator *);
|
||||
bool fold_stmt_inplace (gimple);
|
||||
tree maybe_fold_offset_to_reference (location_t, tree, tree, tree);
|
||||
tree maybe_fold_offset_to_address (location_t, tree, tree, tree);
|
||||
tree maybe_fold_offset_to_reference (location_t, tree, tree, tree);
|
||||
tree maybe_fold_stmt_addition (location_t, tree, tree, tree);
|
||||
tree get_symbol_constant_value (tree);
|
||||
bool may_propagate_address_into_dereference (tree, tree);
|
||||
|
|
|
|||
150
gcc/gimplify.c
150
gcc/gimplify.c
|
|
@ -110,10 +110,13 @@ mark_addressable (tree x)
|
|||
{
|
||||
while (handled_component_p (x))
|
||||
x = TREE_OPERAND (x, 0);
|
||||
if (TREE_CODE (x) == MEM_REF
|
||||
&& TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
|
||||
x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
|
||||
if (TREE_CODE (x) != VAR_DECL
|
||||
&& TREE_CODE (x) != PARM_DECL
|
||||
&& TREE_CODE (x) != RESULT_DECL)
|
||||
return ;
|
||||
return;
|
||||
TREE_ADDRESSABLE (x) = 1;
|
||||
}
|
||||
|
||||
|
|
@ -2961,7 +2964,7 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
|
|||
= build3 (COND_EXPR, type, TREE_OPERAND (expr, 0), then_, else_);
|
||||
|
||||
tmp = create_tmp_var (type, "iftmp");
|
||||
result = build_fold_indirect_ref_loc (loc, tmp);
|
||||
result = build_simple_mem_ref_loc (loc, tmp);
|
||||
}
|
||||
|
||||
/* Build the new then clause, `tmp = then_;'. But don't build the
|
||||
|
|
@ -3185,7 +3188,7 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value,
|
|||
gimple_call_set_lhs (gs, t);
|
||||
gimplify_seq_add_stmt (seq_p, gs);
|
||||
|
||||
*expr_p = build1 (INDIRECT_REF, TREE_TYPE (to), t);
|
||||
*expr_p = build_simple_mem_ref (t);
|
||||
return GS_ALL_DONE;
|
||||
}
|
||||
|
||||
|
|
@ -3269,13 +3272,16 @@ gimplify_init_ctor_preeval_1 (tree *tp, int *walk_subtrees, void *xdata)
|
|||
/* If the constructor component is indirect, determine if we have a
|
||||
potential overlap with the lhs. The only bits of information we
|
||||
have to go on at this point are addressability and alias sets. */
|
||||
if (TREE_CODE (t) == INDIRECT_REF
|
||||
if ((INDIRECT_REF_P (t)
|
||||
|| TREE_CODE (t) == MEM_REF)
|
||||
&& (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
|
||||
&& alias_sets_conflict_p (data->lhs_alias_set, get_alias_set (t)))
|
||||
return t;
|
||||
|
||||
/* If the constructor component is a call, determine if it can hide a
|
||||
potential overlap with the lhs through an INDIRECT_REF like above. */
|
||||
potential overlap with the lhs through an INDIRECT_REF like above.
|
||||
??? Ugh - this is completely broken. In fact this whole analysis
|
||||
doesn't look conservative. */
|
||||
if (TREE_CODE (t) == CALL_EXPR)
|
||||
{
|
||||
tree type, fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (t)));
|
||||
|
|
@ -4004,7 +4010,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
|
|||
tree
|
||||
gimple_fold_indirect_ref (tree t)
|
||||
{
|
||||
tree type = TREE_TYPE (TREE_TYPE (t));
|
||||
tree ptype = TREE_TYPE (t), type = TREE_TYPE (ptype);
|
||||
tree sub = t;
|
||||
tree subtype;
|
||||
|
||||
|
|
@ -4047,51 +4053,52 @@ gimple_fold_indirect_ref (tree t)
|
|||
}
|
||||
}
|
||||
|
||||
/* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
|
||||
/* *(p + CST) -> ... */
|
||||
if (TREE_CODE (sub) == POINTER_PLUS_EXPR
|
||||
&& TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
|
||||
{
|
||||
tree op00 = TREE_OPERAND (sub, 0);
|
||||
tree op01 = TREE_OPERAND (sub, 1);
|
||||
tree op00type;
|
||||
tree addr = TREE_OPERAND (sub, 0);
|
||||
tree off = TREE_OPERAND (sub, 1);
|
||||
tree addrtype;
|
||||
|
||||
STRIP_NOPS (op00);
|
||||
op00type = TREE_TYPE (op00);
|
||||
if (TREE_CODE (op00) == ADDR_EXPR
|
||||
&& TREE_CODE (TREE_TYPE (op00type)) == VECTOR_TYPE
|
||||
&& useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (op00type))))
|
||||
STRIP_NOPS (addr);
|
||||
addrtype = TREE_TYPE (addr);
|
||||
|
||||
/* ((foo*)&vectorfoo)[1] -> BIT_FIELD_REF<vectorfoo,...> */
|
||||
if (TREE_CODE (addr) == ADDR_EXPR
|
||||
&& TREE_CODE (TREE_TYPE (addrtype)) == VECTOR_TYPE
|
||||
&& useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype))))
|
||||
{
|
||||
HOST_WIDE_INT offset = tree_low_cst (op01, 0);
|
||||
tree part_width = TYPE_SIZE (type);
|
||||
unsigned HOST_WIDE_INT part_widthi
|
||||
= tree_low_cst (part_width, 0) / BITS_PER_UNIT;
|
||||
unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
|
||||
tree index = bitsize_int (indexi);
|
||||
if (offset / part_widthi
|
||||
<= TYPE_VECTOR_SUBPARTS (TREE_TYPE (op00type)))
|
||||
return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (op00, 0),
|
||||
part_width, index);
|
||||
HOST_WIDE_INT offset = tree_low_cst (off, 0);
|
||||
tree part_width = TYPE_SIZE (type);
|
||||
unsigned HOST_WIDE_INT part_widthi
|
||||
= tree_low_cst (part_width, 0) / BITS_PER_UNIT;
|
||||
unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
|
||||
tree index = bitsize_int (indexi);
|
||||
if (offset / part_widthi
|
||||
<= TYPE_VECTOR_SUBPARTS (TREE_TYPE (addrtype)))
|
||||
return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (addr, 0),
|
||||
part_width, index);
|
||||
}
|
||||
}
|
||||
|
||||
/* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
|
||||
if (TREE_CODE (sub) == POINTER_PLUS_EXPR
|
||||
&& TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
|
||||
{
|
||||
tree op00 = TREE_OPERAND (sub, 0);
|
||||
tree op01 = TREE_OPERAND (sub, 1);
|
||||
tree op00type;
|
||||
/* ((foo*)&complexfoo)[1] -> __imag__ complexfoo */
|
||||
if (TREE_CODE (addr) == ADDR_EXPR
|
||||
&& TREE_CODE (TREE_TYPE (addrtype)) == COMPLEX_TYPE
|
||||
&& useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype))))
|
||||
{
|
||||
tree size = TYPE_SIZE_UNIT (type);
|
||||
if (tree_int_cst_equal (size, off))
|
||||
return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (addr, 0));
|
||||
}
|
||||
|
||||
STRIP_NOPS (op00);
|
||||
op00type = TREE_TYPE (op00);
|
||||
if (TREE_CODE (op00) == ADDR_EXPR
|
||||
&& TREE_CODE (TREE_TYPE (op00type)) == COMPLEX_TYPE
|
||||
&& useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (op00type))))
|
||||
{
|
||||
tree size = TYPE_SIZE_UNIT (type);
|
||||
if (tree_int_cst_equal (size, op01))
|
||||
return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (op00, 0));
|
||||
}
|
||||
/* *(p + CST) -> MEM_REF <p, CST>. */
|
||||
if (TREE_CODE (addr) != ADDR_EXPR
|
||||
|| DECL_P (TREE_OPERAND (addr, 0)))
|
||||
return fold_build2 (MEM_REF, type,
|
||||
addr,
|
||||
build_int_cst_wide (ptype,
|
||||
TREE_INT_CST_LOW (off),
|
||||
TREE_INT_CST_HIGH (off)));
|
||||
}
|
||||
|
||||
/* *(foo *)fooarrptr => (*fooarrptr)[0] */
|
||||
|
|
@ -6558,7 +6565,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
|
|||
|| gimple_test_f == is_gimple_mem_rhs_or_call
|
||||
|| gimple_test_f == is_gimple_reg_rhs
|
||||
|| gimple_test_f == is_gimple_reg_rhs_or_call
|
||||
|| gimple_test_f == is_gimple_asm_val)
|
||||
|| gimple_test_f == is_gimple_asm_val
|
||||
|| gimple_test_f == is_gimple_mem_ref_addr)
|
||||
gcc_assert (fallback & fb_rvalue);
|
||||
else if (gimple_test_f == is_gimple_min_lval
|
||||
|| gimple_test_f == is_gimple_lvalue)
|
||||
|
|
@ -6764,21 +6772,59 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
|
|||
recalculate_side_effects (*expr_p);
|
||||
break;
|
||||
|
||||
case INDIRECT_REF:
|
||||
*expr_p = fold_indirect_ref_loc (input_location, *expr_p);
|
||||
if (*expr_p != save_expr)
|
||||
{
|
||||
ret = GS_OK;
|
||||
break;
|
||||
}
|
||||
/* else fall through. */
|
||||
case ALIGN_INDIRECT_REF:
|
||||
case MISALIGNED_INDIRECT_REF:
|
||||
/* We can only reach this through re-gimplification from
|
||||
tree optimizers. */
|
||||
ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
|
||||
is_gimple_reg, fb_rvalue);
|
||||
recalculate_side_effects (*expr_p);
|
||||
break;
|
||||
|
||||
case INDIRECT_REF:
|
||||
{
|
||||
bool volatilep = TREE_THIS_VOLATILE (*expr_p);
|
||||
tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
|
||||
|
||||
*expr_p = fold_indirect_ref_loc (input_location, *expr_p);
|
||||
if (*expr_p != save_expr)
|
||||
{
|
||||
ret = GS_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
|
||||
is_gimple_reg, fb_rvalue);
|
||||
recalculate_side_effects (*expr_p);
|
||||
|
||||
*expr_p = fold_build2_loc (input_location, MEM_REF,
|
||||
TREE_TYPE (*expr_p),
|
||||
TREE_OPERAND (*expr_p, 0),
|
||||
build_int_cst (saved_ptr_type, 0));
|
||||
TREE_THIS_VOLATILE (*expr_p) = volatilep;
|
||||
ret = GS_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
/* We arrive here through the various re-gimplifcation paths. */
|
||||
case MEM_REF:
|
||||
/* First try re-folding the whole thing. */
|
||||
tmp = fold_binary (MEM_REF, TREE_TYPE (*expr_p),
|
||||
TREE_OPERAND (*expr_p, 0),
|
||||
TREE_OPERAND (*expr_p, 1));
|
||||
if (tmp)
|
||||
{
|
||||
*expr_p = tmp;
|
||||
recalculate_side_effects (*expr_p);
|
||||
ret = GS_OK;
|
||||
break;
|
||||
}
|
||||
ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
|
||||
is_gimple_mem_ref_addr, fb_rvalue);
|
||||
recalculate_side_effects (*expr_p);
|
||||
ret = GS_ALL_DONE;
|
||||
break;
|
||||
|
||||
/* Constants need not be gimplified. */
|
||||
case INTEGER_CST:
|
||||
case REAL_CST:
|
||||
|
|
|
|||
|
|
@ -1832,10 +1832,12 @@ likely_eliminated_by_inlining_p (gimple stmt)
|
|||
bool rhs_free = false;
|
||||
bool lhs_free = false;
|
||||
|
||||
while (handled_component_p (inner_lhs) || TREE_CODE (inner_lhs) == INDIRECT_REF)
|
||||
while (handled_component_p (inner_lhs)
|
||||
|| TREE_CODE (inner_lhs) == MEM_REF)
|
||||
inner_lhs = TREE_OPERAND (inner_lhs, 0);
|
||||
while (handled_component_p (inner_rhs)
|
||||
|| TREE_CODE (inner_rhs) == ADDR_EXPR || TREE_CODE (inner_rhs) == INDIRECT_REF)
|
||||
|| TREE_CODE (inner_rhs) == ADDR_EXPR
|
||||
|| TREE_CODE (inner_rhs) == MEM_REF)
|
||||
inner_rhs = TREE_OPERAND (inner_rhs, 0);
|
||||
|
||||
|
||||
|
|
@ -1855,7 +1857,8 @@ likely_eliminated_by_inlining_p (gimple stmt)
|
|||
|| (TREE_CODE (inner_lhs) == SSA_NAME
|
||||
&& TREE_CODE (SSA_NAME_VAR (inner_lhs)) == RESULT_DECL))
|
||||
lhs_free = true;
|
||||
if (lhs_free && (is_gimple_reg (rhs) || is_gimple_min_invariant (rhs)))
|
||||
if (lhs_free
|
||||
&& (is_gimple_reg (rhs) || is_gimple_min_invariant (rhs)))
|
||||
rhs_free = true;
|
||||
if (lhs_free && rhs_free)
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -405,11 +405,12 @@ compute_complex_assign_jump_func (struct ipa_node_params *info,
|
|||
if (TREE_CODE (type) != RECORD_TYPE)
|
||||
return;
|
||||
op1 = get_ref_base_and_extent (op1, &offset, &size, &max_size);
|
||||
if (TREE_CODE (op1) != INDIRECT_REF
|
||||
if (TREE_CODE (op1) != MEM_REF
|
||||
/* If this is a varying address, punt. */
|
||||
|| max_size == -1
|
||||
|| max_size != size)
|
||||
return;
|
||||
offset += mem_ref_offset (op1).low * BITS_PER_UNIT;
|
||||
op1 = TREE_OPERAND (op1, 0);
|
||||
if (TREE_CODE (op1) != SSA_NAME
|
||||
|| !SSA_NAME_IS_DEFAULT_DEF (op1))
|
||||
|
|
@ -481,11 +482,12 @@ compute_complex_ancestor_jump_func (struct ipa_node_params *info,
|
|||
expr = TREE_OPERAND (expr, 0);
|
||||
expr = get_ref_base_and_extent (expr, &offset, &size, &max_size);
|
||||
|
||||
if (TREE_CODE (expr) != INDIRECT_REF
|
||||
if (TREE_CODE (expr) != MEM_REF
|
||||
/* If this is a varying address, punt. */
|
||||
|| max_size == -1
|
||||
|| max_size != size)
|
||||
return;
|
||||
offset += mem_ref_offset (expr).low * BITS_PER_UNIT;
|
||||
parm = TREE_OPERAND (expr, 0);
|
||||
if (TREE_CODE (parm) != SSA_NAME
|
||||
|| !SSA_NAME_IS_DEFAULT_DEF (parm))
|
||||
|
|
@ -1179,7 +1181,7 @@ ipa_analyze_virtual_call_uses (struct cgraph_node *node,
|
|||
obj = TREE_OPERAND (obj, 0);
|
||||
}
|
||||
while (TREE_CODE (obj) == COMPONENT_REF);
|
||||
if (TREE_CODE (obj) != INDIRECT_REF)
|
||||
if (TREE_CODE (obj) != MEM_REF)
|
||||
return;
|
||||
obj = TREE_OPERAND (obj, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ check_op (funct_state local, tree t, bool checking_write)
|
|||
return;
|
||||
}
|
||||
else if (t
|
||||
&& INDIRECT_REF_P (t)
|
||||
&& (INDIRECT_REF_P (t) || TREE_CODE (t) == MEM_REF)
|
||||
&& TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME
|
||||
&& !ptr_deref_may_alias_global_p (TREE_OPERAND (t, 0)))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -421,6 +421,10 @@ decompose_indirect_ref_acc (tree str_decl, struct field_access_site *acc)
|
|||
if (!is_result_of_mult (before_cast, &acc->num, struct_size))
|
||||
return false;
|
||||
|
||||
/* ??? Add TREE_OPERAND (acc->ref, 1) to acc->offset. */
|
||||
if (!integer_zerop (TREE_OPERAND (acc->ref, 1)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -434,7 +438,7 @@ decompose_access (tree str_decl, struct field_access_site *acc)
|
|||
{
|
||||
gcc_assert (acc->ref);
|
||||
|
||||
if (TREE_CODE (acc->ref) == INDIRECT_REF)
|
||||
if (TREE_CODE (acc->ref) == MEM_REF)
|
||||
return decompose_indirect_ref_acc (str_decl, acc);
|
||||
else if (TREE_CODE (acc->ref) == ARRAY_REF)
|
||||
return true;
|
||||
|
|
@ -969,12 +973,12 @@ replace_field_acc (struct field_access_site *acc, tree new_type)
|
|||
type_wrapper_t *wr_p = NULL;
|
||||
struct ref_pos r_pos;
|
||||
|
||||
while (TREE_CODE (ref_var) == INDIRECT_REF
|
||||
while (TREE_CODE (ref_var) == MEM_REF
|
||||
|| TREE_CODE (ref_var) == ARRAY_REF)
|
||||
{
|
||||
type_wrapper_t wr;
|
||||
|
||||
if ( TREE_CODE (ref_var) == INDIRECT_REF)
|
||||
if (TREE_CODE (ref_var) == MEM_REF)
|
||||
{
|
||||
wr.wrap = 0;
|
||||
wr.domain = 0;
|
||||
|
|
@ -1001,7 +1005,7 @@ replace_field_acc (struct field_access_site *acc, tree new_type)
|
|||
new_ref = build4 (ARRAY_REF, type, new_ref,
|
||||
wr_p->domain, NULL_TREE, NULL_TREE);
|
||||
else /* Pointer. */
|
||||
new_ref = build1 (INDIRECT_REF, type, new_ref);
|
||||
new_ref = build_simple_mem_ref (new_ref);
|
||||
VEC_pop (type_wrapper_t, wrapper);
|
||||
}
|
||||
|
||||
|
|
@ -1041,7 +1045,7 @@ static void
|
|||
replace_field_access_stmt (struct field_access_site *acc, tree new_type)
|
||||
{
|
||||
|
||||
if (TREE_CODE (acc->ref) == INDIRECT_REF
|
||||
if (TREE_CODE (acc->ref) == MEM_REF
|
||||
||TREE_CODE (acc->ref) == ARRAY_REF
|
||||
||TREE_CODE (acc->ref) == VAR_DECL)
|
||||
replace_field_acc (acc, new_type);
|
||||
|
|
@ -1277,13 +1281,11 @@ insert_new_var_in_stmt (gimple stmt, tree var, tree new_var)
|
|||
pos = find_pos_in_stmt (stmt, var, &r_pos);
|
||||
gcc_assert (pos);
|
||||
|
||||
while (r_pos.container && (TREE_CODE(r_pos.container) == INDIRECT_REF
|
||||
while (r_pos.container && (TREE_CODE(r_pos.container) == MEM_REF
|
||||
|| TREE_CODE(r_pos.container) == ADDR_EXPR))
|
||||
{
|
||||
tree type = TREE_TYPE (TREE_TYPE (new_var));
|
||||
|
||||
if (TREE_CODE(r_pos.container) == INDIRECT_REF)
|
||||
new_var = build1 (INDIRECT_REF, type, new_var);
|
||||
if (TREE_CODE(r_pos.container) == MEM_REF)
|
||||
new_var = build_simple_mem_ref (new_var);
|
||||
else
|
||||
new_var = build_fold_addr_expr (new_var);
|
||||
pos = find_pos_in_stmt (stmt, r_pos.container, &r_pos);
|
||||
|
|
@ -2530,7 +2532,7 @@ get_stmt_accesses (tree *tp, int *walk_subtrees, void *data)
|
|||
tree field_decl = TREE_OPERAND (t, 1);
|
||||
|
||||
|
||||
if ((TREE_CODE (ref) == INDIRECT_REF
|
||||
if ((TREE_CODE (ref) == MEM_REF
|
||||
|| TREE_CODE (ref) == ARRAY_REF
|
||||
|| TREE_CODE (ref) == VAR_DECL)
|
||||
&& TREE_CODE (field_decl) == FIELD_DECL)
|
||||
|
|
@ -4031,7 +4033,10 @@ reorg_structs (void)
|
|||
static unsigned int
|
||||
reorg_structs_drive (void)
|
||||
{
|
||||
reorg_structs ();
|
||||
/* IPA struct-reorg is completely broken - its analysis phase is
|
||||
non-conservative (which is not the only reason it is broken). */
|
||||
if (0)
|
||||
reorg_structs ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ collect_data_for_malloc_call (gimple stmt, struct malloc_call_data *m_data)
|
|||
initial address and index of each dimension. */
|
||||
struct access_site_info
|
||||
{
|
||||
/* The statement (INDIRECT_REF or POINTER_PLUS_EXPR). */
|
||||
/* The statement (MEM_REF or POINTER_PLUS_EXPR). */
|
||||
gimple stmt;
|
||||
|
||||
/* In case of POINTER_PLUS_EXPR, what is the offset. */
|
||||
|
|
@ -334,7 +334,7 @@ struct ssa_acc_in_tree
|
|||
/* The variable whose accesses in the tree we are looking for. */
|
||||
tree ssa_var;
|
||||
/* The tree and code inside it the ssa_var is accessed, currently
|
||||
it could be an INDIRECT_REF or CALL_EXPR. */
|
||||
it could be an MEM_REF or CALL_EXPR. */
|
||||
enum tree_code t_code;
|
||||
tree t_tree;
|
||||
/* The place in the containing tree. */
|
||||
|
|
@ -413,33 +413,18 @@ mtt_info_eq (const void *mtt1, const void *mtt2)
|
|||
static bool
|
||||
may_flatten_matrices_1 (gimple stmt)
|
||||
{
|
||||
tree t;
|
||||
|
||||
switch (gimple_code (stmt))
|
||||
{
|
||||
case GIMPLE_ASSIGN:
|
||||
if (!gimple_assign_cast_p (stmt))
|
||||
case GIMPLE_CALL:
|
||||
if (!gimple_has_lhs (stmt))
|
||||
return true;
|
||||
|
||||
t = gimple_assign_rhs1 (stmt);
|
||||
while (CONVERT_EXPR_P (t))
|
||||
if (TREE_CODE (TREE_TYPE (gimple_get_lhs (stmt))) == VECTOR_TYPE)
|
||||
{
|
||||
if (TREE_TYPE (t) && POINTER_TYPE_P (TREE_TYPE (t)))
|
||||
{
|
||||
tree pointee;
|
||||
|
||||
pointee = TREE_TYPE (t);
|
||||
while (POINTER_TYPE_P (pointee))
|
||||
pointee = TREE_TYPE (pointee);
|
||||
if (TREE_CODE (pointee) == VECTOR_TYPE)
|
||||
{
|
||||
if (dump_file)
|
||||
fprintf (dump_file,
|
||||
"Found vector type, don't flatten matrix\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
t = TREE_OPERAND (t, 0);
|
||||
if (dump_file)
|
||||
fprintf (dump_file,
|
||||
"Found vector type, don't flatten matrix\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case GIMPLE_ASM:
|
||||
|
|
@ -602,7 +587,7 @@ mark_min_matrix_escape_level (struct matrix_info *mi, int l, gimple s)
|
|||
/* Find if the SSA variable is accessed inside the
|
||||
tree and record the tree containing it.
|
||||
The only relevant uses are the case of SSA_NAME, or SSA inside
|
||||
INDIRECT_REF, PLUS_EXPR, POINTER_PLUS_EXPR, MULT_EXPR. */
|
||||
MEM_REF, PLUS_EXPR, POINTER_PLUS_EXPR, MULT_EXPR. */
|
||||
static void
|
||||
ssa_accessed_in_tree (tree t, struct ssa_acc_in_tree *a)
|
||||
{
|
||||
|
|
@ -613,7 +598,7 @@ ssa_accessed_in_tree (tree t, struct ssa_acc_in_tree *a)
|
|||
if (t == a->ssa_var)
|
||||
a->var_found = true;
|
||||
break;
|
||||
case INDIRECT_REF:
|
||||
case MEM_REF:
|
||||
if (SSA_VAR_P (TREE_OPERAND (t, 0))
|
||||
&& TREE_OPERAND (t, 0) == a->ssa_var)
|
||||
a->var_found = true;
|
||||
|
|
@ -660,7 +645,7 @@ ssa_accessed_in_assign_rhs (gimple stmt, struct ssa_acc_in_tree *a)
|
|||
tree op1, op2;
|
||||
|
||||
case SSA_NAME:
|
||||
case INDIRECT_REF:
|
||||
case MEM_REF:
|
||||
CASE_CONVERT:
|
||||
case VIEW_CONVERT_EXPR:
|
||||
ssa_accessed_in_tree (gimple_assign_rhs1 (stmt), a);
|
||||
|
|
@ -984,7 +969,7 @@ get_index_from_offset (tree offset, gimple def_stmt)
|
|||
|
||||
/* update MI->dimension_type_size[CURRENT_INDIRECT_LEVEL] with the size
|
||||
of the type related to the SSA_VAR, or the type related to the
|
||||
lhs of STMT, in the case that it is an INDIRECT_REF. */
|
||||
lhs of STMT, in the case that it is an MEM_REF. */
|
||||
static void
|
||||
update_type_size (struct matrix_info *mi, gimple stmt, tree ssa_var,
|
||||
int current_indirect_level)
|
||||
|
|
@ -992,9 +977,9 @@ update_type_size (struct matrix_info *mi, gimple stmt, tree ssa_var,
|
|||
tree lhs;
|
||||
HOST_WIDE_INT type_size;
|
||||
|
||||
/* Update type according to the type of the INDIRECT_REF expr. */
|
||||
/* Update type according to the type of the MEM_REF expr. */
|
||||
if (is_gimple_assign (stmt)
|
||||
&& TREE_CODE (gimple_assign_lhs (stmt)) == INDIRECT_REF)
|
||||
&& TREE_CODE (gimple_assign_lhs (stmt)) == MEM_REF)
|
||||
{
|
||||
lhs = gimple_assign_lhs (stmt);
|
||||
gcc_assert (POINTER_TYPE_P
|
||||
|
|
@ -1073,7 +1058,7 @@ analyze_accesses_for_call_stmt (struct matrix_info *mi, tree ssa_var,
|
|||
at this level because in this case we cannot calculate the
|
||||
address correctly. */
|
||||
if ((lhs_acc.var_found && rhs_acc.var_found
|
||||
&& lhs_acc.t_code == INDIRECT_REF)
|
||||
&& lhs_acc.t_code == MEM_REF)
|
||||
|| (!rhs_acc.var_found && !lhs_acc.var_found))
|
||||
{
|
||||
mark_min_matrix_escape_level (mi, current_indirect_level, use_stmt);
|
||||
|
|
@ -1087,7 +1072,7 @@ analyze_accesses_for_call_stmt (struct matrix_info *mi, tree ssa_var,
|
|||
{
|
||||
int l = current_indirect_level + 1;
|
||||
|
||||
gcc_assert (lhs_acc.t_code == INDIRECT_REF);
|
||||
gcc_assert (lhs_acc.t_code == MEM_REF);
|
||||
mark_min_matrix_escape_level (mi, l, use_stmt);
|
||||
return current_indirect_level;
|
||||
}
|
||||
|
|
@ -1213,7 +1198,7 @@ analyze_accesses_for_assign_stmt (struct matrix_info *mi, tree ssa_var,
|
|||
at this level because in this case we cannot calculate the
|
||||
address correctly. */
|
||||
if ((lhs_acc.var_found && rhs_acc.var_found
|
||||
&& lhs_acc.t_code == INDIRECT_REF)
|
||||
&& lhs_acc.t_code == MEM_REF)
|
||||
|| (!rhs_acc.var_found && !lhs_acc.var_found))
|
||||
{
|
||||
mark_min_matrix_escape_level (mi, current_indirect_level, use_stmt);
|
||||
|
|
@ -1227,7 +1212,7 @@ analyze_accesses_for_assign_stmt (struct matrix_info *mi, tree ssa_var,
|
|||
{
|
||||
int l = current_indirect_level + 1;
|
||||
|
||||
gcc_assert (lhs_acc.t_code == INDIRECT_REF);
|
||||
gcc_assert (lhs_acc.t_code == MEM_REF);
|
||||
|
||||
if (!(gimple_assign_copy_p (use_stmt)
|
||||
|| gimple_assign_cast_p (use_stmt))
|
||||
|
|
@ -1248,7 +1233,7 @@ analyze_accesses_for_assign_stmt (struct matrix_info *mi, tree ssa_var,
|
|||
is used. */
|
||||
if (rhs_acc.var_found)
|
||||
{
|
||||
if (rhs_acc.t_code != INDIRECT_REF
|
||||
if (rhs_acc.t_code != MEM_REF
|
||||
&& rhs_acc.t_code != POINTER_PLUS_EXPR && rhs_acc.t_code != SSA_NAME)
|
||||
{
|
||||
mark_min_matrix_escape_level (mi, current_indirect_level, use_stmt);
|
||||
|
|
@ -1256,7 +1241,7 @@ analyze_accesses_for_assign_stmt (struct matrix_info *mi, tree ssa_var,
|
|||
}
|
||||
/* If the access in the RHS has an indirection increase the
|
||||
indirection level. */
|
||||
if (rhs_acc.t_code == INDIRECT_REF)
|
||||
if (rhs_acc.t_code == MEM_REF)
|
||||
{
|
||||
if (record_accesses)
|
||||
record_access_alloc_site_info (mi, use_stmt, NULL_TREE,
|
||||
|
|
@ -1309,7 +1294,7 @@ analyze_accesses_for_assign_stmt (struct matrix_info *mi, tree ssa_var,
|
|||
}
|
||||
/* If we are storing this level of indirection mark it as
|
||||
escaping. */
|
||||
if (lhs_acc.t_code == INDIRECT_REF || TREE_CODE (lhs) != SSA_NAME)
|
||||
if (lhs_acc.t_code == MEM_REF || TREE_CODE (lhs) != SSA_NAME)
|
||||
{
|
||||
int l = current_indirect_level;
|
||||
|
||||
|
|
@ -1369,8 +1354,8 @@ analyze_matrix_accesses (struct matrix_info *mi, tree ssa_var,
|
|||
return;
|
||||
|
||||
/* Now go over the uses of the SSA_NAME and check how it is used in
|
||||
each one of them. We are mainly looking for the pattern INDIRECT_REF,
|
||||
then a POINTER_PLUS_EXPR, then INDIRECT_REF etc. while in between there could
|
||||
each one of them. We are mainly looking for the pattern MEM_REF,
|
||||
then a POINTER_PLUS_EXPR, then MEM_REF etc. while in between there could
|
||||
be any number of copies and casts. */
|
||||
gcc_assert (TREE_CODE (ssa_var) == SSA_NAME);
|
||||
|
||||
|
|
@ -1856,7 +1841,7 @@ transform_access_sites (void **slot, void *data ATTRIBUTE_UNUSED)
|
|||
gimple new_stmt;
|
||||
|
||||
gcc_assert (gimple_assign_rhs_code (acc_info->stmt)
|
||||
== INDIRECT_REF);
|
||||
== MEM_REF);
|
||||
/* Emit convert statement to convert to type of use. */
|
||||
tmp = create_tmp_var (TREE_TYPE (lhs), "new");
|
||||
add_referenced_var (tmp);
|
||||
|
|
@ -1878,10 +1863,10 @@ transform_access_sites (void **slot, void *data ATTRIBUTE_UNUSED)
|
|||
continue;
|
||||
}
|
||||
code = gimple_assign_rhs_code (acc_info->stmt);
|
||||
if (code == INDIRECT_REF
|
||||
if (code == MEM_REF
|
||||
&& acc_info->level < min_escape_l - 1)
|
||||
{
|
||||
/* Replace the INDIRECT_REF with NOP (cast) usually we are casting
|
||||
/* Replace the MEM_REF with NOP (cast) usually we are casting
|
||||
from "pointer to type" to "type". */
|
||||
tree t =
|
||||
build1 (NOP_EXPR, TREE_TYPE (gimple_assign_rhs1 (acc_info->stmt)),
|
||||
|
|
@ -2206,7 +2191,6 @@ transform_allocation_sites (void **slot, void *data ATTRIBUTE_UNUSED)
|
|||
for (i = 1; i < mi->min_indirect_level_escape; i++)
|
||||
{
|
||||
gimple_stmt_iterator gsi;
|
||||
gimple use_stmt1 = NULL;
|
||||
|
||||
gimple call_stmt = mi->malloc_for_level[i];
|
||||
gcc_assert (is_gimple_call (call_stmt));
|
||||
|
|
@ -2216,17 +2200,9 @@ transform_allocation_sites (void **slot, void *data ATTRIBUTE_UNUSED)
|
|||
gsi = gsi_for_stmt (call_stmt);
|
||||
/* Remove the call stmt. */
|
||||
gsi_remove (&gsi, true);
|
||||
/* remove the type cast stmt. */
|
||||
FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter,
|
||||
gimple_call_lhs (call_stmt))
|
||||
{
|
||||
use_stmt1 = use_stmt;
|
||||
gsi = gsi_for_stmt (use_stmt);
|
||||
gsi_remove (&gsi, true);
|
||||
}
|
||||
/* Remove the assignment of the allocated area. */
|
||||
FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter,
|
||||
gimple_get_lhs (use_stmt1))
|
||||
gimple_call_lhs (call_stmt))
|
||||
{
|
||||
gsi = gsi_for_stmt (use_stmt);
|
||||
gsi_remove (&gsi, true);
|
||||
|
|
|
|||
|
|
@ -864,10 +864,10 @@ build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
|
|||
if (x != NULL)
|
||||
field = x;
|
||||
|
||||
x = build_fold_indirect_ref (ctx->receiver_decl);
|
||||
x = build_simple_mem_ref (ctx->receiver_decl);
|
||||
x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
|
||||
if (by_ref)
|
||||
x = build_fold_indirect_ref (x);
|
||||
x = build_simple_mem_ref (x);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
|
@ -887,7 +887,7 @@ build_outer_var_ref (tree var, omp_context *ctx)
|
|||
{
|
||||
x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
|
||||
x = build_outer_var_ref (x, ctx);
|
||||
x = build_fold_indirect_ref (x);
|
||||
x = build_simple_mem_ref (x);
|
||||
}
|
||||
else if (is_taskreg_ctx (ctx))
|
||||
{
|
||||
|
|
@ -904,7 +904,7 @@ build_outer_var_ref (tree var, omp_context *ctx)
|
|||
gcc_unreachable ();
|
||||
|
||||
if (is_reference (var))
|
||||
x = build_fold_indirect_ref (x);
|
||||
x = build_simple_mem_ref (x);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
|
@ -1916,7 +1916,18 @@ scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
|
|||
{
|
||||
*walk_subtrees = 1;
|
||||
if (ctx)
|
||||
TREE_TYPE (t) = remap_type (TREE_TYPE (t), &ctx->cb);
|
||||
{
|
||||
tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
|
||||
if (tem != TREE_TYPE (t))
|
||||
{
|
||||
if (TREE_CODE (t) == INTEGER_CST)
|
||||
*tp = build_int_cst_wide (tem,
|
||||
TREE_INT_CST_LOW (t),
|
||||
TREE_INT_CST_HIGH (t));
|
||||
else
|
||||
TREE_TYPE (t) = tem;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -2337,7 +2348,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
|
|||
x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
|
||||
gimplify_assign (new_var, x, ilist);
|
||||
|
||||
new_var = build_fold_indirect_ref_loc (clause_loc, new_var);
|
||||
new_var = build_simple_mem_ref_loc (clause_loc, new_var);
|
||||
}
|
||||
else if (c_kind == OMP_CLAUSE_REDUCTION
|
||||
&& OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
|
||||
|
|
@ -2555,7 +2566,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
|
|||
|
||||
x = build_outer_var_ref (var, ctx);
|
||||
if (is_reference (var))
|
||||
new_var = build_fold_indirect_ref_loc (clause_loc, new_var);
|
||||
new_var = build_simple_mem_ref_loc (clause_loc, new_var);
|
||||
x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
|
||||
gimplify_and_add (x, stmt_list);
|
||||
}
|
||||
|
|
@ -2622,7 +2633,7 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
|
|||
var = OMP_CLAUSE_DECL (c);
|
||||
new_var = lookup_decl (var, ctx);
|
||||
if (is_reference (var))
|
||||
new_var = build_fold_indirect_ref_loc (clause_loc, new_var);
|
||||
new_var = build_simple_mem_ref_loc (clause_loc, new_var);
|
||||
ref = build_outer_var_ref (var, ctx);
|
||||
code = OMP_CLAUSE_REDUCTION_CODE (c);
|
||||
|
||||
|
|
@ -2714,8 +2725,8 @@ lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
|
|||
if (is_reference (var))
|
||||
{
|
||||
ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
|
||||
ref = build_fold_indirect_ref_loc (clause_loc, ref);
|
||||
new_var = build_fold_indirect_ref_loc (clause_loc, new_var);
|
||||
ref = build_simple_mem_ref_loc (clause_loc, ref);
|
||||
new_var = build_simple_mem_ref_loc (clause_loc, new_var);
|
||||
}
|
||||
x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
|
||||
gimplify_and_add (x, rlist);
|
||||
|
|
@ -5067,8 +5078,12 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
|
|||
loadedi = loaded_val;
|
||||
}
|
||||
|
||||
initial = force_gimple_operand_gsi (&si, build_fold_indirect_ref (iaddr),
|
||||
true, NULL_TREE, true, GSI_SAME_STMT);
|
||||
initial
|
||||
= force_gimple_operand_gsi (&si,
|
||||
build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)),
|
||||
iaddr,
|
||||
build_int_cst (TREE_TYPE (iaddr), 0)),
|
||||
true, NULL_TREE, true, GSI_SAME_STMT);
|
||||
|
||||
/* Move the value to the LOADEDI temporary. */
|
||||
if (gimple_in_ssa_p (cfun))
|
||||
|
|
@ -5212,15 +5227,15 @@ expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
|
|||
t = build_function_call_expr (UNKNOWN_LOCATION, t, 0);
|
||||
force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
|
||||
|
||||
stmt = gimple_build_assign (loaded_val, build_fold_indirect_ref (addr));
|
||||
stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
|
||||
gsi_insert_before (&si, stmt, GSI_SAME_STMT);
|
||||
gsi_remove (&si, true);
|
||||
|
||||
si = gsi_last_bb (store_bb);
|
||||
gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
|
||||
|
||||
stmt = gimple_build_assign (build_fold_indirect_ref (unshare_expr (addr)),
|
||||
stored_val);
|
||||
stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
|
||||
stored_val);
|
||||
gsi_insert_before (&si, stmt, GSI_SAME_STMT);
|
||||
|
||||
t = built_in_decls[BUILT_IN_GOMP_ATOMIC_END];
|
||||
|
|
@ -6269,7 +6284,7 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
|
|||
n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
|
||||
sf = (tree) n->value;
|
||||
sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
|
||||
src = build_fold_indirect_ref_loc (loc, sarg);
|
||||
src = build_simple_mem_ref_loc (loc, sarg);
|
||||
src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
|
||||
t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
|
||||
append_to_statement_list (t, &list);
|
||||
|
|
@ -6292,9 +6307,9 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
|
|||
sf = (tree) n->value;
|
||||
if (tcctx.cb.decl_map)
|
||||
sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
|
||||
src = build_fold_indirect_ref_loc (loc, sarg);
|
||||
src = build_simple_mem_ref_loc (loc, sarg);
|
||||
src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
|
||||
dst = build_fold_indirect_ref_loc (loc, arg);
|
||||
dst = build_simple_mem_ref_loc (loc, arg);
|
||||
dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
|
||||
t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
|
||||
append_to_statement_list (t, &list);
|
||||
|
|
@ -6315,14 +6330,14 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
|
|||
sf = (tree) n->value;
|
||||
if (tcctx.cb.decl_map)
|
||||
sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
|
||||
src = build_fold_indirect_ref_loc (loc, sarg);
|
||||
src = build_simple_mem_ref_loc (loc, sarg);
|
||||
src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
|
||||
if (use_pointer_for_field (decl, NULL) || is_reference (decl))
|
||||
src = build_fold_indirect_ref_loc (loc, src);
|
||||
src = build_simple_mem_ref_loc (loc, src);
|
||||
}
|
||||
else
|
||||
src = decl;
|
||||
dst = build_fold_indirect_ref_loc (loc, arg);
|
||||
dst = build_simple_mem_ref_loc (loc, arg);
|
||||
dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
|
||||
t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
|
||||
append_to_statement_list (t, &list);
|
||||
|
|
@ -6341,14 +6356,14 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
|
|||
sf = (tree) n->value;
|
||||
if (tcctx.cb.decl_map)
|
||||
sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
|
||||
src = build_fold_indirect_ref_loc (loc, sarg);
|
||||
src = build_simple_mem_ref_loc (loc, sarg);
|
||||
src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
|
||||
if (use_pointer_for_field (decl, NULL))
|
||||
src = build_fold_indirect_ref_loc (loc, src);
|
||||
src = build_simple_mem_ref_loc (loc, src);
|
||||
}
|
||||
else
|
||||
src = decl;
|
||||
dst = build_fold_indirect_ref_loc (loc, arg);
|
||||
dst = build_simple_mem_ref_loc (loc, arg);
|
||||
dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
|
||||
t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
|
||||
append_to_statement_list (t, &list);
|
||||
|
|
@ -6380,10 +6395,10 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
|
|||
(splay_tree_key) TREE_OPERAND (ind, 0));
|
||||
sf = (tree) n->value;
|
||||
sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
|
||||
src = build_fold_indirect_ref_loc (loc, sarg);
|
||||
src = build_simple_mem_ref_loc (loc, sarg);
|
||||
src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
|
||||
src = build_fold_indirect_ref_loc (loc, src);
|
||||
dst = build_fold_indirect_ref_loc (loc, arg);
|
||||
src = build_simple_mem_ref_loc (loc, src);
|
||||
dst = build_simple_mem_ref_loc (loc, arg);
|
||||
dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
|
||||
t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
|
||||
append_to_statement_list (t, &list);
|
||||
|
|
@ -6391,7 +6406,7 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
|
|||
(splay_tree_key) TREE_OPERAND (ind, 0));
|
||||
df = (tree) n->value;
|
||||
df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
|
||||
ptr = build_fold_indirect_ref_loc (loc, arg);
|
||||
ptr = build_simple_mem_ref_loc (loc, arg);
|
||||
ptr = build3 (COMPONENT_REF, TREE_TYPE (df), ptr, df, NULL);
|
||||
t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
|
||||
build_fold_addr_expr_loc (loc, dst));
|
||||
|
|
|
|||
|
|
@ -1,3 +1,70 @@
|
|||
2010-07-01 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/42834
|
||||
PR middle-end/44468
|
||||
* gcc.c-torture/execute/20100316-1.c: New testcase.
|
||||
* gcc.c-torture/execute/pr44468.c: Likewise.
|
||||
* gcc.c-torture/compile/20100609-1.c: Likewise.
|
||||
* gcc.dg/volatile2.c: Adjust.
|
||||
* gcc.dg/plugin/selfassign.c: Likewise.
|
||||
* gcc.dg/pr36902.c: Likewise.
|
||||
* gcc.dg/tree-ssa/foldaddr-2.c: Remove.
|
||||
* gcc.dg/tree-ssa/foldaddr-3.c: Likewise.
|
||||
* gcc.dg/tree-ssa/forwprop-8.c: Adjust.
|
||||
* gcc.dg/tree-ssa/pr17141-1.c: Likewise.
|
||||
* gcc.dg/tree-ssa/ssa-fre-13.c: Likewise.
|
||||
* gcc.dg/tree-ssa/ssa-fre-14.c: Likewise.
|
||||
* gcc.dg/tree-ssa/ssa-ccp-21.c: Likewise.
|
||||
* gcc.dg/tree-ssa/pta-ptrarith-1.c: Likewise.
|
||||
* gcc.dg/tree-ssa/20030807-7.c: Likewise.
|
||||
* gcc.dg/tree-ssa/forwprop-10.c: Likewise.
|
||||
* gcc.dg/tree-ssa/ssa-fre-1.c: Likewise.
|
||||
* gcc.dg/tree-ssa/pta-ptrarith-2.c: Likewise.
|
||||
* gcc.dg/tree-ssa/ssa-ccp-23.c: Likewise.
|
||||
* gcc.dg/tree-ssa/forwprop-1.c: Likewise.
|
||||
* gcc.dg/tree-ssa/forwprop-2.c: Likewise.
|
||||
* gcc.dg/tree-ssa/struct-aliasing-1.c: Likewise.
|
||||
* gcc.dg/tree-ssa/ssa-ccp-25.c: Likewise.
|
||||
* gcc.dg/tree-ssa/ssa-pre-26.c: Likewise.
|
||||
* gcc.dg/tree-ssa/struct-aliasing-2.c: Likewise.
|
||||
* gcc.dg/tree-ssa/ssa-ccp-26.c: Likewise.
|
||||
* gcc.dg/tree-ssa/ssa-sccvn-4.c: Likewise.
|
||||
* gcc.dg/tree-ssa/ssa-pre-7.c: Likewise.
|
||||
* gcc.dg/tree-ssa/forwprop-5.c: Likewise.
|
||||
* gcc.dg/struct/w_prof_two_strs.c: XFAIL.
|
||||
* gcc.dg/struct/wo_prof_escape_arg_to_local.c: Likewise.
|
||||
* gcc.dg/struct/wo_prof_global_var.c: Likewise.
|
||||
* gcc.dg/struct/wo_prof_malloc_size_var.c: Likewise.
|
||||
* gcc.dg/struct/w_prof_local_array.c: Likewise.
|
||||
* gcc.dg/struct/w_prof_single_str_global.c: Likewise.
|
||||
* gcc.dg/struct/wo_prof_escape_str_init.c: Likewise.
|
||||
* gcc.dg/struct/wo_prof_array_through_pointer.c: Likewise.
|
||||
* gcc.dg/struct/w_prof_global_array.c: Likewise.
|
||||
* gcc.dg/struct/wo_prof_array_field.c: Likewise.
|
||||
* gcc.dg/struct/wo_prof_single_str_local.c: Likewise.
|
||||
* gcc.dg/struct/w_prof_local_var.c: Likewise.
|
||||
* gcc.dg/struct/wo_prof_two_strs.c: Likewise.
|
||||
* gcc.dg/struct/wo_prof_empty_str.c: Likewise.
|
||||
* gcc.dg/struct/wo_prof_local_array.c: Likewise.
|
||||
* gcc.dg/struct/w_prof_global_var.c: Likewise.
|
||||
* gcc.dg/struct/wo_prof_single_str_global.c: Likewise.
|
||||
* gcc.dg/struct/wo_prof_escape_substr_value.c: Likewise.
|
||||
* gcc.dg/struct/wo_prof_global_array.c: Likewise.
|
||||
* gcc.dg/struct/wo_prof_escape_return.c: Likewise.
|
||||
* gcc.dg/struct/wo_prof_escape_substr_array.c: Likewise.
|
||||
* gcc.dg/struct/wo_prof_double_malloc.c: Likewise.
|
||||
* gcc.dg/struct/w_ratio_cold_str.c: Likewise.
|
||||
* gcc.dg/struct/wo_prof_escape_substr_pointer.c: Likewise.
|
||||
* gcc.dg/struct/wo_prof_local_var.c: Likewise.
|
||||
* gcc.dg/tree-prof/stringop-1.c: Adjust.
|
||||
* g++.dg/tree-ssa/pr31146.C: Likewise.
|
||||
* g++.dg/tree-ssa/copyprop-1.C: Likewise.
|
||||
* g++.dg/tree-ssa/pr33604.C: Likewise.
|
||||
* g++.dg/plugin/selfassign.c: Likewise.
|
||||
* gfortran.dg/array_memcpy_3.f90: Likewise.
|
||||
* gfortran.dg/array_memcpy_4.f90: Likewise.
|
||||
* c-c++-common/torture/pr42834.c: New testcase.
|
||||
|
||||
2010-06-30 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
|
||||
PR c++/44628
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
/* { dg-do run } */
|
||||
|
||||
void __attribute__((noinline,noclone))
|
||||
foo(int *p, float *q) { __asm__ volatile ("" : : : "memory"); }
|
||||
|
||||
int main()
|
||||
{
|
||||
if (sizeof (int) == sizeof (float))
|
||||
{
|
||||
int i;
|
||||
float f;
|
||||
int *p;
|
||||
/* Prevent i and f from being rewritten into SSA form. */
|
||||
foo (&i, &f);
|
||||
i = 0;
|
||||
f = 1.0;
|
||||
p = (int *)&f;
|
||||
__builtin_memcpy (&i, p, 4);
|
||||
if (*(float *)&i != 1.0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -52,9 +52,7 @@ get_real_ref_rhs (tree expr)
|
|||
/* We are only interested in an assignment with a single
|
||||
rhs operand because if it is not, the original assignment
|
||||
will not possibly be a self-assignment. */
|
||||
if (is_gimple_assign (def_stmt)
|
||||
&& (get_gimple_rhs_class (gimple_assign_rhs_code (def_stmt))
|
||||
== GIMPLE_SINGLE_RHS))
|
||||
if (gimple_assign_single_p (def_stmt))
|
||||
return get_real_ref_rhs (gimple_assign_rhs1 (def_stmt));
|
||||
else
|
||||
return NULL_TREE;
|
||||
|
|
@ -66,7 +64,7 @@ get_real_ref_rhs (tree expr)
|
|||
case PARM_DECL:
|
||||
case FIELD_DECL:
|
||||
case COMPONENT_REF:
|
||||
case INDIRECT_REF:
|
||||
case MEM_REF:
|
||||
case ARRAY_REF:
|
||||
return expr;
|
||||
default:
|
||||
|
|
@ -116,17 +114,18 @@ get_non_ssa_expr (tree expr)
|
|||
else
|
||||
return expr;
|
||||
}
|
||||
case INDIRECT_REF:
|
||||
case MEM_REF:
|
||||
{
|
||||
tree orig_base = TREE_OPERAND (expr, 0);
|
||||
tree base = get_non_ssa_expr (orig_base);
|
||||
if (!base)
|
||||
return NULL_TREE;
|
||||
/* If BASE is converted, build a new indirect reference tree. */
|
||||
if (base != orig_base)
|
||||
return build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (base)), base);
|
||||
else
|
||||
return expr;
|
||||
if (TREE_CODE (orig_base) == SSA_NAME)
|
||||
{
|
||||
tree base = get_non_ssa_expr (orig_base);
|
||||
if (!base)
|
||||
return NULL_TREE;
|
||||
return fold_build2 (MEM_REF, TREE_TYPE (expr),
|
||||
base, TREE_OPERAND (expr, 1));
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
case ARRAY_REF:
|
||||
{
|
||||
|
|
@ -153,9 +152,7 @@ get_non_ssa_expr (tree expr)
|
|||
&& !gimple_nop_p (SSA_NAME_DEF_STMT (expr)))
|
||||
{
|
||||
gimple def_stmt = SSA_NAME_DEF_STMT (expr);
|
||||
if (is_gimple_assign (def_stmt)
|
||||
&& (get_gimple_rhs_class (gimple_assign_rhs_code (def_stmt))
|
||||
== GIMPLE_SINGLE_RHS))
|
||||
if (gimple_assign_single_p (def_stmt))
|
||||
vdecl = gimple_assign_rhs1 (def_stmt);
|
||||
}
|
||||
return get_non_ssa_expr (vdecl);
|
||||
|
|
@ -201,9 +198,7 @@ warn_self_assign (gimple stmt)
|
|||
tree rhs, lhs;
|
||||
|
||||
/* Check assigment statement. */
|
||||
if (is_gimple_assign (stmt)
|
||||
&& (get_gimple_rhs_class (gimple_assign_rhs_code (stmt))
|
||||
== GIMPLE_SINGLE_RHS))
|
||||
if (gimple_assign_single_p (stmt))
|
||||
{
|
||||
rhs = get_real_ref_rhs (gimple_assign_rhs1 (stmt));
|
||||
if (!rhs)
|
||||
|
|
|
|||
|
|
@ -25,5 +25,7 @@ int foo(Object&o)
|
|||
return o[0];
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-not ".* = \[^>;\]*;" "dce2" } } */
|
||||
/* Remaining should be two loads. */
|
||||
|
||||
/* { dg-final { scan-tree-dump-times " = \[^\n\]*;" 2 "dce2" } } */
|
||||
/* { dg-final { cleanup-tree-dump "dce2" } } */
|
||||
|
|
|
|||
|
|
@ -12,5 +12,5 @@ void foo (int j)
|
|||
*q = 1;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "i\\\[j.*\\\] =.* 1;" "forwprop1" } } */
|
||||
/* { dg-final { scan-tree-dump "MEM\\\[.*&i\\\]\\\[j.*\\\] =.* 1;" "forwprop1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "forwprop?" } } */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do run } */
|
||||
/* { dg-options "-O -fdump-tree-forwprop1" } */
|
||||
/* { dg-options "-O -fdump-tree-optimized-vops" } */
|
||||
|
||||
struct Value
|
||||
{
|
||||
|
|
@ -35,12 +35,14 @@ int main(int argc, char *argv[])
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Check that we forward propagated
|
||||
/* Check that we propagate
|
||||
D.2182_13 = (struct Ref *) &D.2137.lhs;
|
||||
to
|
||||
D.2182_13->lhs.m ={v} &I;
|
||||
yielding
|
||||
D.2137.lhs.m ={v} &I; */
|
||||
D.2137.lhs.m ={v} &I;
|
||||
so that SRA can promote all locals to registers and we end up
|
||||
referencing a single virtual operand at abort () after optimization. */
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "D\\\.....\\\..hs\\\.m =" 2 "forwprop1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "forwprop1" } } */
|
||||
/* { dg-final { scan-tree-dump-times ".MEM_\[0-9\]*\\\(D\\\)" 1 "optimized" } } */
|
||||
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
extern unsigned long int strtoul (__const char *__restrict __nptr, char **__restrict __endptr, int __base);
|
||||
int find_reloads (int i, char *p)
|
||||
{
|
||||
int c;
|
||||
while ((c = *p++))
|
||||
return strtoul (p - 1, &p, 10);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
struct Foo {
|
||||
int i;
|
||||
unsigned precision : 10;
|
||||
unsigned blah : 3;
|
||||
} f;
|
||||
|
||||
int __attribute__((noinline,noclone))
|
||||
foo (struct Foo *p)
|
||||
{
|
||||
struct Foo *q = p;
|
||||
return (*q).precision;
|
||||
}
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
int main()
|
||||
{
|
||||
f.i = -1;
|
||||
f.precision = 0;
|
||||
f.blah = -1;
|
||||
if (foo (&f) != 0)
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
#include <stddef.h>
|
||||
|
||||
struct S {
|
||||
int i;
|
||||
int j;
|
||||
};
|
||||
struct R {
|
||||
int k;
|
||||
struct S a;
|
||||
};
|
||||
struct Q {
|
||||
float k;
|
||||
struct S a;
|
||||
};
|
||||
struct Q s;
|
||||
int __attribute__((noinline,noclone))
|
||||
test1 (void *q)
|
||||
{
|
||||
struct S *b = (struct S *)((char *)q + sizeof (int));
|
||||
s.a.i = 0;
|
||||
b->i = 3;
|
||||
return s.a.i;
|
||||
}
|
||||
int __attribute__((noinline,noclone))
|
||||
test2 (void *q)
|
||||
{
|
||||
struct S *b = &((struct R *)q)->a;
|
||||
s.a.i = 0;
|
||||
b->i = 3;
|
||||
return s.a.i;
|
||||
}
|
||||
int __attribute__((noinline,noclone))
|
||||
test3 (void *q)
|
||||
{
|
||||
s.a.i = 0;
|
||||
((struct S *)((char *)q + sizeof (int)))->i = 3;
|
||||
return s.a.i;
|
||||
}
|
||||
extern void abort (void);
|
||||
int
|
||||
main()
|
||||
{
|
||||
if (sizeof (float) != sizeof (int)
|
||||
|| offsetof (struct R, a) != sizeof (int)
|
||||
|| offsetof (struct Q, a) != sizeof (int))
|
||||
return 0;
|
||||
s.a.i = 1;
|
||||
s.a.j = 2;
|
||||
if (test1 ((void *)&s) != 3)
|
||||
abort ();
|
||||
s.a.i = 1;
|
||||
s.a.j = 2;
|
||||
if (test2 ((void *)&s) != 3)
|
||||
abort ();
|
||||
s.a.i = 1;
|
||||
s.a.j = 2;
|
||||
if (test3 ((void *)&s) != 3)
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -52,9 +52,7 @@ get_real_ref_rhs (tree expr)
|
|||
/* We are only interested in an assignment with a single
|
||||
rhs operand because if it is not, the original assignment
|
||||
will not possibly be a self-assignment. */
|
||||
if (is_gimple_assign (def_stmt)
|
||||
&& (get_gimple_rhs_class (gimple_assign_rhs_code (def_stmt))
|
||||
== GIMPLE_SINGLE_RHS))
|
||||
if (gimple_assign_single_p (def_stmt))
|
||||
return get_real_ref_rhs (gimple_assign_rhs1 (def_stmt));
|
||||
else
|
||||
return NULL_TREE;
|
||||
|
|
@ -66,7 +64,7 @@ get_real_ref_rhs (tree expr)
|
|||
case PARM_DECL:
|
||||
case FIELD_DECL:
|
||||
case COMPONENT_REF:
|
||||
case INDIRECT_REF:
|
||||
case MEM_REF:
|
||||
case ARRAY_REF:
|
||||
return expr;
|
||||
default:
|
||||
|
|
@ -116,17 +114,18 @@ get_non_ssa_expr (tree expr)
|
|||
else
|
||||
return expr;
|
||||
}
|
||||
case INDIRECT_REF:
|
||||
case MEM_REF:
|
||||
{
|
||||
tree orig_base = TREE_OPERAND (expr, 0);
|
||||
tree base = get_non_ssa_expr (orig_base);
|
||||
if (!base)
|
||||
return NULL_TREE;
|
||||
/* If BASE is converted, build a new indirect reference tree. */
|
||||
if (base != orig_base)
|
||||
return build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (base)), base);
|
||||
else
|
||||
return expr;
|
||||
if (TREE_CODE (orig_base) == SSA_NAME)
|
||||
{
|
||||
tree base = get_non_ssa_expr (orig_base);
|
||||
if (!base)
|
||||
return NULL_TREE;
|
||||
return fold_build2 (MEM_REF, TREE_TYPE (expr),
|
||||
base, TREE_OPERAND (expr, 1));
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
case ARRAY_REF:
|
||||
{
|
||||
|
|
@ -153,9 +152,7 @@ get_non_ssa_expr (tree expr)
|
|||
&& !gimple_nop_p (SSA_NAME_DEF_STMT (expr)))
|
||||
{
|
||||
gimple def_stmt = SSA_NAME_DEF_STMT (expr);
|
||||
if (is_gimple_assign (def_stmt)
|
||||
&& (get_gimple_rhs_class (gimple_assign_rhs_code (def_stmt))
|
||||
== GIMPLE_SINGLE_RHS))
|
||||
if (gimple_assign_single_p (def_stmt))
|
||||
vdecl = gimple_assign_rhs1 (def_stmt);
|
||||
}
|
||||
return get_non_ssa_expr (vdecl);
|
||||
|
|
@ -201,9 +198,7 @@ warn_self_assign (gimple stmt)
|
|||
tree rhs, lhs;
|
||||
|
||||
/* Check assigment statement. */
|
||||
if (is_gimple_assign (stmt)
|
||||
&& (get_gimple_rhs_class (gimple_assign_rhs_code (stmt))
|
||||
== GIMPLE_SINGLE_RHS))
|
||||
if (gimple_assign_single_p (stmt))
|
||||
{
|
||||
rhs = get_real_ref_rhs (gimple_assign_rhs1 (stmt));
|
||||
if (!rhs)
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ foo2(unsigned char * to, const unsigned char * from, int n)
|
|||
*to = *from;
|
||||
break;
|
||||
case 5:
|
||||
to[4] = from [4]; /* { dg-warning "20:array subscript is above array bounds" } */
|
||||
to[4] = from [4]; /* { dg-warning "array subscript is above array bounds" } */
|
||||
break;
|
||||
}
|
||||
return to;
|
||||
|
|
|
|||
|
|
@ -26,5 +26,5 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" } } */
|
||||
/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final-use { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -39,5 +39,5 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail { "avr-*-*" } } } } */
|
||||
/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final-use { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -34,5 +34,5 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail { "avr-*-*" } } } } */
|
||||
/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final-use { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -37,5 +37,5 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" } } */
|
||||
/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final-use { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -28,6 +28,6 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail { "avr-*-*" } } } } */
|
||||
/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final-use { cleanup-ipa-dump "*" } } */
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,6 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 2" "ipa_struct_reorg" } } */
|
||||
/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 2" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final-use { cleanup-ipa-dump "*" } } */
|
||||
|
||||
|
|
|
|||
|
|
@ -39,5 +39,5 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" } } */
|
||||
/* { dg-final-use { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final-use { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -23,5 +23,5 @@ int main()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail { "avr-*-*" } } } } */
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -35,5 +35,5 @@ main ()
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" } } */
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -26,5 +26,5 @@ int main()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail { "avr-*-*" } } } } */
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -43,5 +43,5 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final { scan-ipa-dump "No structures to transform" "ipa_struct_reorg" { xfail { "avr-*-*" } } } } */
|
||||
/* { dg-final { scan-ipa-dump "No structures to transform" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -42,5 +42,5 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final { scan-ipa-dump "is passed to local function...Excluded." "ipa_struct_reorg" } } */
|
||||
/* { dg-final { scan-ipa-dump "is passed to local function...Excluded." "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -29,5 +29,5 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final { scan-ipa-dump "is return type of function...Excluded" "ipa_struct_reorg" } } */
|
||||
/* { dg-final { scan-ipa-dump "is return type of function...Excluded" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -28,6 +28,6 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final { scan-ipa-dump "is initialized...Excluded" "ipa_struct_reorg" } } */
|
||||
/* { dg-final { scan-ipa-dump "is initialized...Excluded" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "*" } } */
|
||||
|
||||
|
|
|
|||
|
|
@ -30,5 +30,5 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final { scan-ipa-dump "is a field in the structure" "ipa_struct_reorg" } } */
|
||||
/* { dg-final { scan-ipa-dump "is a field in the structure" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -45,5 +45,5 @@ main (void)
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final { scan-ipa-dump "is a field in the structure" "ipa_struct_reorg" } } */
|
||||
/* { dg-final { scan-ipa-dump "is a field in the structure" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -42,5 +42,5 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final { scan-ipa-dump "is a field in the structure" "ipa_struct_reorg" } } */
|
||||
/* { dg-final { scan-ipa-dump "is a field in the structure" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -29,5 +29,5 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail { "avr-*-*" } } } } */
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -42,5 +42,5 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail { "avr-*-*" } } } } */
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -37,5 +37,5 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail { "avr-*-*" } } } } */
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -40,5 +40,5 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail { "avr-*-*" } } } } */
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -44,5 +44,5 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail { "avr-*-*" } } } } */
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -31,5 +31,5 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail { "avr-*-*" } } } } */
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -31,5 +31,5 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final { scan-ipa-dump "No structures to transform" "ipa_struct_reorg" { xfail { "avr-*-*" } } } } */
|
||||
/* { dg-final { scan-ipa-dump "No structures to transform" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -64,5 +64,5 @@ main ()
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "ipa_struct_reorg" { xfail { "avr-*-*" } } } } */
|
||||
/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "ipa_struct_reorg" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-ipa-dump "*" } } */
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ main()
|
|||
/* { dg-final-use { scan-tree-dump "Single value 4 stringop" "tree_profile"} } */
|
||||
/* Really this ought to simplify into assignment, but we are not there yet. */
|
||||
/* a[0] = b[0] is what we fold the resulting memcpy into. */
|
||||
/* { dg-final-use { scan-tree-dump "a.0. = " "optimized"} } */
|
||||
/* { dg-final-use { scan-tree-dump "= b.0." "optimized"} } */
|
||||
/* { dg-final-use { scan-tree-dump " = MEM.*&b" "optimized"} } */
|
||||
/* { dg-final-use { scan-tree-dump "MEM.*&a\\\] = " "optimized"} } */
|
||||
/* { dg-final-use { cleanup-tree-dump "optimized" } } */
|
||||
/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */
|
||||
|
|
|
|||
|
|
@ -33,5 +33,5 @@ simplify_condition (cond_p)
|
|||
}
|
||||
|
||||
/* There should be exactly one IF conditional. */
|
||||
/* { dg-final { scan-tree-dump-times "if " 1 "vrp1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "if " 1 "vrp1" { xfail *-*-* } } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O1 -fdump-tree-optimized" } */
|
||||
struct a{
|
||||
int a;
|
||||
int b;
|
||||
} a;
|
||||
int *
|
||||
t()
|
||||
{
|
||||
return (int *)&a;
|
||||
}
|
||||
/* { dg-final { scan-tree-dump "a.a" "optimized"} } */
|
||||
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O1 -fdump-tree-optimized" } */
|
||||
union a
|
||||
{
|
||||
struct s1
|
||||
{
|
||||
long long a;
|
||||
long long b;
|
||||
} s1;
|
||||
struct s2
|
||||
{
|
||||
int c;
|
||||
int d;
|
||||
} s2;
|
||||
struct s3
|
||||
{
|
||||
unsigned long long e;
|
||||
unsigned long long f;
|
||||
} s3;
|
||||
} a;
|
||||
int *
|
||||
t ()
|
||||
{
|
||||
return (int *) &a;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "a.s2.c" "optimized"} } */
|
||||
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
||||
|
|
@ -15,5 +15,5 @@ void f(struct a * b, __SIZE_TYPE__ i)
|
|||
c[i] = 1;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "t\\\[i.*\\\] =.* 1;" 1 "forwprop1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "t\\\[i.*\\\].* = 1;" 1 "forwprop1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "forwprop1" } } */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O -fdump-tree-forwprop1" } */
|
||||
/* { dg-options "-O -fdump-tree-fre-details" } */
|
||||
|
||||
int b;
|
||||
unsigned a;
|
||||
|
|
@ -15,9 +15,8 @@ void test2(void)
|
|||
}
|
||||
|
||||
/* The indirect load should be replaced by a load from a and a
|
||||
conversion to int. */
|
||||
conversion to int. FRE should then be able to replace
|
||||
the rhs of the store to b by 1. */
|
||||
|
||||
/* { dg-final { scan-tree-dump "= a;" "forwprop1" } } */
|
||||
/* { dg-final { scan-tree-dump "= \\\(int\\\) " "forwprop1" } } */
|
||||
/* { dg-final { scan-tree-dump-not "= \\\*" "forwprop1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "forwprop1" } } */
|
||||
/* { dg-final { scan-tree-dump "Replaced\[^\\n\]*with 1" "fre" } } */
|
||||
/* { dg-final { cleanup-tree-dump "fre" } } */
|
||||
|
|
|
|||
|
|
@ -17,5 +17,5 @@ void f(__SIZE_TYPE__ i)
|
|||
c[i] = 1;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "t\\\[i.*\\\] =.* 1;" 1 "forwprop1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "t\\\[i.*\\\].* = 1;" 1 "forwprop1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "forwprop?" } } */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O1 -fdump-tree-forwprop1 -w" } */
|
||||
/* { dg-options "-O1 -fdump-tree-esra -w" } */
|
||||
|
||||
#define vector __attribute__((vector_size(16) ))
|
||||
struct VecClass
|
||||
|
|
@ -15,7 +15,8 @@ vector float foo( vector float v )
|
|||
return y.v;
|
||||
}
|
||||
|
||||
/* We should be able to convert the cast to a VCE in forwprop1. */
|
||||
/* { dg-final { scan-tree-dump-times "VIEW_CONVERT_EXPR" 1 "forwprop1"} } */
|
||||
/* { dg-final { cleanup-tree-dump "forwprop1" } } */
|
||||
|
||||
/* We should be able to remove the intermediate struct and directly
|
||||
return x. As we do not fold VIEW_CONVERT_EXPR<struct VecClass>(x).v
|
||||
that doesn't happen right now. */
|
||||
/* { dg-final { scan-tree-dump-times "VIEW_CONVERT_EXPR" 1 "esra"} } */
|
||||
/* { dg-final { cleanup-tree-dump "esra" } } */
|
||||
|
|
|
|||
|
|
@ -12,5 +12,5 @@ int foo(struct X *q)
|
|||
|
||||
/* We should have propragated &q->a into (*pointer). */
|
||||
/* { dg-final { scan-tree-dump-times "pointer" 0 "forwprop1"} } */
|
||||
/* { dg-final { scan-tree-dump "->a\\\[0\\\]" "forwprop1" } } */
|
||||
/* { dg-final { scan-tree-dump "\\\[0\\\]" "forwprop1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "forwprop1" } } */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-pre-stats" } */
|
||||
/* { dg-options "-O2 -fdump-tree-pre-stats -fdump-tree-fre" } */
|
||||
#include <stddef.h>
|
||||
|
||||
union tree_node;
|
||||
|
|
@ -72,7 +72,9 @@ main (void)
|
|||
remove_useless_vars (&unexpanded_var_list, 0);
|
||||
return 0;
|
||||
}
|
||||
/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */
|
||||
|
||||
/* See PR44656. The last elimination is only done by PRE. */
|
||||
/* { dg-final { scan-tree-dump-not "= unexpanded_var_list;" "fre" { xfail *-*-* } } } */
|
||||
/* { dg-final { scan-tree-dump-times "Eliminated: 1" 2 "pre" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Insertions: 2" 1 "pre" } } */
|
||||
/* { dg-final { cleanup-tree-dump "pre" } } */
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-forwprop1" } */
|
||||
/* { dg-options "-O -fdump-tree-forwprop1" } */
|
||||
|
||||
struct A { int i; };
|
||||
int
|
||||
|
|
@ -11,5 +11,7 @@ foo(struct A *locp, int str)
|
|||
return locp->i;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "locp.*->i =" "forwprop1" } } */
|
||||
/* We should have propagated &locp->i into its dereference. */
|
||||
|
||||
/* { dg-final { scan-tree-dump "locp_\[^\\n\]* =" "forwprop1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "forwprop1" } } */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fno-tree-ccp -fdump-tree-alias" } */
|
||||
/* { dg-options "-O2 -fno-tree-ccp -fdump-tree-ealias" } */
|
||||
|
||||
extern void abort (void);
|
||||
struct X {
|
||||
|
|
@ -22,5 +22,5 @@ foo(int i, int j, int k, int off)
|
|||
return *q;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "q_., points-to vars: { k }" "alias" } } */
|
||||
/* { dg-final { cleanup-tree-dump "alias" } } */
|
||||
/* { dg-final { scan-tree-dump "q_., points-to vars: { k }" "ealias" } } */
|
||||
/* { dg-final { cleanup-tree-dump "ealias" } } */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fno-tree-ccp -fdump-tree-alias" } */
|
||||
/* { dg-options "-O2 -fno-tree-ccp -fdump-tree-ealias" } */
|
||||
|
||||
extern void abort (void);
|
||||
struct X {
|
||||
|
|
@ -22,5 +22,5 @@ foo(int i, int j, int k, int off)
|
|||
return *q;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "q_., points-to vars: { i }" "alias" } } */
|
||||
/* { dg-final { cleanup-tree-dump "alias" } } */
|
||||
/* { dg-final { scan-tree-dump "q_., points-to vars: { i }" "ealias" } } */
|
||||
/* { dg-final { cleanup-tree-dump "ealias" } } */
|
||||
|
|
|
|||
|
|
@ -21,5 +21,9 @@ int bar (void)
|
|||
return q->i;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "a.b.i" 2 "ccp1" } } */
|
||||
/* The first access is through struct A, so a.b.i is fine,
|
||||
the second access needs to preserve the original access type struct B. */
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "a.b.i" 1 "ccp1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "MEM\\\[\\\(struct B \\\*\\\)&a\\\].i" 1 "ccp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "ccp1" } } */
|
||||
|
|
|
|||
|
|
@ -15,5 +15,5 @@ int foo (void)
|
|||
return *x;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "a.i\\\[1\\\]" "ccp1" } } */
|
||||
/* { dg-final { scan-tree-dump "MEM\\\[\\\(int \\\*\\\)&a \\\+ 4B\\\]" "ccp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "ccp1" } } */
|
||||
|
|
|
|||
|
|
@ -9,6 +9,6 @@ int foo(int i)
|
|||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "&a\\\[\[iD\]\\\." "ccp1" } } */
|
||||
/* { dg-final { scan-tree-dump "= a\\\[\[iD\]\\\." "forwprop1" } } */
|
||||
/* { dg-final { scan-tree-dump "= .*&a\\\]\\\[\[iD\]\\\." "forwprop1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "ccp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "forwprop1" } } */
|
||||
|
|
|
|||
|
|
@ -7,5 +7,5 @@ int foo(int i)
|
|||
return (a + 1)[i];
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "= a\\\[D\\\." "forwprop1" } } */
|
||||
/* { dg-final { scan-tree-dump "=.*&a\\\]\\\[D\\\." "forwprop1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "forwprop1" } } */
|
||||
|
|
|
|||
|
|
@ -11,6 +11,5 @@ int f(int *a)
|
|||
return *c + t;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "Replaced \\\(int \\\*\\\) b_.*with a_" "fre" } } */
|
||||
/* { dg-final { scan-tree-dump "Replaced \\\*c_.*with t_" "fre" } } */
|
||||
/* { dg-final { scan-tree-dump "Replaced \\\*a_\[^\n\].*with t_" "fre" } } */
|
||||
/* { dg-final { cleanup-tree-dump "fre" } } */
|
||||
|
|
|
|||
|
|
@ -23,6 +23,5 @@ void foo(double (*q)[4], struct Foo *tmp1)
|
|||
}
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "Inserted .* &a" "fre" } } */
|
||||
/* { dg-final { scan-tree-dump "Replaced tmp1_.\\\(D\\\)->data" "fre" } } */
|
||||
/* { dg-final { scan-tree-dump "Replaced tmp1_.\\\(D\\\)->data with &a" "fre" } } */
|
||||
/* { dg-final { cleanup-tree-dump "fre" } } */
|
||||
|
|
|
|||
|
|
@ -27,6 +27,5 @@ void foo(double (*q)[4])
|
|||
bar(a);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "Inserted .* &a" "fre" } } */
|
||||
/* { dg-final { scan-tree-dump "Replaced tmp1.data" "fre" } } */
|
||||
/* { dg-final { scan-tree-dump "Replaced tmp1.data with &a" "fre" } } */
|
||||
/* { dg-final { cleanup-tree-dump "fre" } } */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-Os -fdump-tree-pre-details" } */
|
||||
/* { dg-options "-O -fdump-tree-fre-details" } */
|
||||
|
||||
typedef union
|
||||
{
|
||||
|
|
@ -23,5 +23,5 @@ void foo(SA* pResult, SB* method, SC* self)
|
|||
pResult->data = pResult->data;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "Deleted redundant store" "pre" } } */
|
||||
/* { dg-final { cleanup-tree-dump "pre" } } */
|
||||
/* { dg-final { scan-tree-dump "Deleted redundant store" "fre" } } */
|
||||
/* { dg-final { cleanup-tree-dump "fre" } } */
|
||||
|
|
|
|||
|
|
@ -7,6 +7,6 @@ foo (int *array)
|
|||
return array[1];
|
||||
return 0;
|
||||
}
|
||||
/* We should eliminate one address calculation, and one load. */
|
||||
/* { dg-final { scan-tree-dump-times "Eliminated: 2" 1 "fre"} } */
|
||||
/* We should eliminate one load. */
|
||||
/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "fre"} } */
|
||||
/* { dg-final { cleanup-tree-dump "fre" } } */
|
||||
|
|
|
|||
|
|
@ -23,5 +23,5 @@ int vnum_test8(int *data)
|
|||
}
|
||||
/* We should eliminate m - n, n + k, set data[5] = 0, eliminate the
|
||||
address arithmetic for data[5], and set p = 0.
|
||||
/* { dg-final { scan-tree-dump-times "Eliminated: 7" 1 "fre"} } */
|
||||
/* { dg-final { scan-tree-dump-times "Eliminated: 5" 1 "fre"} } */
|
||||
/* { dg-final { cleanup-tree-dump "fre" } } */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do "compile" } */
|
||||
/* { dg-options "-O2 -fdump-tree-fre" } */
|
||||
/* { dg-options "-O2 -fdump-tree-fre-details" } */
|
||||
|
||||
struct S { float f; };
|
||||
int __attribute__((noinline))
|
||||
|
|
@ -11,5 +11,5 @@ foo (float *r, struct S *p)
|
|||
return i + *q;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "\\\*q" 1 "fre" } } */
|
||||
/* { dg-final { scan-tree-dump "Replaced\[^\n\]*with i_." "fre" } } */
|
||||
/* { dg-final { cleanup-tree-dump "fre" } } */
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ foo ( struct S *p)
|
|||
}
|
||||
|
||||
|
||||
/* There should only be one load of p->f because fwprop can change *(int *)&p->f into just (int)p->f. */
|
||||
/* { dg-final { scan-tree-dump-times "p_.\\\(D\\\)->f" 1 "fre" } } */
|
||||
/* There should only be one load of p->f because fwprop can change
|
||||
*(int *)&p->f into just (int)p->f. */
|
||||
/* { dg-final { scan-tree-dump-times "= \[^\n\]*p_.\\\(D\\\)" 1 "fre" } } */
|
||||
/* { dg-final { cleanup-tree-dump "fre" } } */
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-gimple -fdump-tree-optimized" } */
|
||||
/* { dg-options "-O2 -fdump-tree-optimized" } */
|
||||
|
||||
struct GTeth_desc
|
||||
{
|
||||
|
|
@ -12,14 +12,11 @@ struct GTeth_softc
|
|||
|
||||
void foo(struct GTeth_softc *sc)
|
||||
{
|
||||
/* Verify that we retain the cast to (volatile struct GTeth_desc *)
|
||||
after gimplification and that we keep the volatileness on the
|
||||
/* Verify that we retain the volatileness on the
|
||||
store until after optimization. */
|
||||
volatile struct GTeth_desc *p = &sc->txq_desc[0];
|
||||
p->ed_cmdsts = 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "\\(volatile struct GTeth_desc \\*\\) D" "gimple" } } */
|
||||
/* { dg-final { scan-tree-dump "{v}" "optimized" } } */
|
||||
/* { dg-final { cleanup-tree-dump "gimple" } } */
|
||||
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
||||
|
|
|
|||
|
|
@ -11,5 +11,5 @@ subroutine bar(x)
|
|||
x = (/ 3, 1, 4, 1 /)
|
||||
end subroutine
|
||||
|
||||
! { dg-final { scan-tree-dump-times "memcpy|ref-all" 2 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "memcpy|(ref-all.*ref-all)" 2 "original" } }
|
||||
! { dg-final { cleanup-tree-dump "original" } }
|
||||
|
|
|
|||
|
|
@ -9,5 +9,5 @@
|
|||
|
||||
d = s
|
||||
end
|
||||
! { dg-final { scan-tree-dump-times "d = " 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "MEM.*d\\\] = MEM" 1 "original" } }
|
||||
! { dg-final { cleanup-tree-dump "original" } }
|
||||
|
|
|
|||
|
|
@ -309,6 +309,15 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
|
|||
return;
|
||||
|
||||
case ADDR_EXPR:
|
||||
/* Handle &MEM[ptr + CST] which is equivalent to POINTER_PLUS_EXPR. */
|
||||
if (TREE_CODE (TREE_OPERAND (expr, 0)) == MEM_REF)
|
||||
{
|
||||
expr = TREE_OPERAND (expr, 0);
|
||||
tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
|
||||
tree_to_aff_combination (TREE_OPERAND (expr, 1), sizetype, &tmp);
|
||||
aff_combination_add (comb, &tmp);
|
||||
return;
|
||||
}
|
||||
core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos,
|
||||
&toffset, &mode, &unsignedp, &volatilep,
|
||||
false);
|
||||
|
|
@ -331,6 +340,25 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
|
|||
}
|
||||
return;
|
||||
|
||||
case MEM_REF:
|
||||
if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR)
|
||||
tree_to_aff_combination (TREE_OPERAND (TREE_OPERAND (expr, 0), 0),
|
||||
type, comb);
|
||||
else if (integer_zerop (TREE_OPERAND (expr, 1)))
|
||||
{
|
||||
aff_combination_elt (comb, type, expr);
|
||||
return;
|
||||
}
|
||||
else
|
||||
aff_combination_elt (comb, type,
|
||||
build2 (MEM_REF, TREE_TYPE (expr),
|
||||
TREE_OPERAND (expr, 0),
|
||||
build_int_cst
|
||||
(TREE_TYPE (TREE_OPERAND (expr, 1)), 0)));
|
||||
tree_to_aff_combination (TREE_OPERAND (expr, 1), sizetype, &tmp);
|
||||
aff_combination_add (comb, &tmp);
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
138
gcc/tree-cfg.c
138
gcc/tree-cfg.c
|
|
@ -2533,6 +2533,49 @@ gimple_split_edge (edge edge_in)
|
|||
return new_bb;
|
||||
}
|
||||
|
||||
|
||||
/* Verify properties of the address expression T with base object BASE. */
|
||||
|
||||
static tree
|
||||
verify_address (tree t, tree base)
|
||||
{
|
||||
bool old_constant;
|
||||
bool old_side_effects;
|
||||
bool new_constant;
|
||||
bool new_side_effects;
|
||||
|
||||
old_constant = TREE_CONSTANT (t);
|
||||
old_side_effects = TREE_SIDE_EFFECTS (t);
|
||||
|
||||
recompute_tree_invariant_for_addr_expr (t);
|
||||
new_side_effects = TREE_SIDE_EFFECTS (t);
|
||||
new_constant = TREE_CONSTANT (t);
|
||||
|
||||
if (old_constant != new_constant)
|
||||
{
|
||||
error ("constant not recomputed when ADDR_EXPR changed");
|
||||
return t;
|
||||
}
|
||||
if (old_side_effects != new_side_effects)
|
||||
{
|
||||
error ("side effects not recomputed when ADDR_EXPR changed");
|
||||
return t;
|
||||
}
|
||||
|
||||
if (!(TREE_CODE (base) == VAR_DECL
|
||||
|| TREE_CODE (base) == PARM_DECL
|
||||
|| TREE_CODE (base) == RESULT_DECL))
|
||||
return NULL_TREE;
|
||||
|
||||
if (DECL_GIMPLE_REG_P (base))
|
||||
{
|
||||
error ("DECL_GIMPLE_REG_P set on a variable with address taken");
|
||||
return base;
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Callback for walk_tree, check that all elements with address taken are
|
||||
properly noticed as such. The DATA is an int* that is 1 if TP was seen
|
||||
inside a PHI node. */
|
||||
|
|
@ -2561,12 +2604,26 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
|
|||
break;
|
||||
|
||||
case INDIRECT_REF:
|
||||
error ("INDIRECT_REF in gimple IL");
|
||||
return t;
|
||||
|
||||
case MEM_REF:
|
||||
x = TREE_OPERAND (t, 0);
|
||||
if (!is_gimple_reg (x) && !is_gimple_min_invariant (x))
|
||||
if (!is_gimple_mem_ref_addr (x))
|
||||
{
|
||||
error ("Indirect reference's operand is not a register or a constant.");
|
||||
error ("Invalid first operand of MEM_REF.");
|
||||
return x;
|
||||
}
|
||||
if (TREE_CODE (TREE_OPERAND (t, 1)) != INTEGER_CST
|
||||
|| !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 1))))
|
||||
{
|
||||
error ("Invalid offset operand of MEM_REF.");
|
||||
return TREE_OPERAND (t, 1);
|
||||
}
|
||||
if (TREE_CODE (x) == ADDR_EXPR
|
||||
&& (x = verify_address (x, TREE_OPERAND (x, 0))))
|
||||
return x;
|
||||
*walk_subtrees = 0;
|
||||
break;
|
||||
|
||||
case ASSERT_EXPR:
|
||||
|
|
@ -2584,31 +2641,10 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
|
|||
|
||||
case ADDR_EXPR:
|
||||
{
|
||||
bool old_constant;
|
||||
bool old_side_effects;
|
||||
bool new_constant;
|
||||
bool new_side_effects;
|
||||
tree tem;
|
||||
|
||||
gcc_assert (is_gimple_address (t));
|
||||
|
||||
old_constant = TREE_CONSTANT (t);
|
||||
old_side_effects = TREE_SIDE_EFFECTS (t);
|
||||
|
||||
recompute_tree_invariant_for_addr_expr (t);
|
||||
new_side_effects = TREE_SIDE_EFFECTS (t);
|
||||
new_constant = TREE_CONSTANT (t);
|
||||
|
||||
if (old_constant != new_constant)
|
||||
{
|
||||
error ("constant not recomputed when ADDR_EXPR changed");
|
||||
return t;
|
||||
}
|
||||
if (old_side_effects != new_side_effects)
|
||||
{
|
||||
error ("side effects not recomputed when ADDR_EXPR changed");
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Skip any references (they will be checked when we recurse down the
|
||||
tree) and ensure that any variable used as a prefix is marked
|
||||
addressable. */
|
||||
|
|
@ -2617,20 +2653,19 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
|
|||
x = TREE_OPERAND (x, 0))
|
||||
;
|
||||
|
||||
if ((tem = verify_address (t, x)))
|
||||
return tem;
|
||||
|
||||
if (!(TREE_CODE (x) == VAR_DECL
|
||||
|| TREE_CODE (x) == PARM_DECL
|
||||
|| TREE_CODE (x) == RESULT_DECL))
|
||||
return NULL;
|
||||
|
||||
if (!TREE_ADDRESSABLE (x))
|
||||
{
|
||||
error ("address taken, but ADDRESSABLE bit not set");
|
||||
return x;
|
||||
}
|
||||
if (DECL_GIMPLE_REG_P (x))
|
||||
{
|
||||
error ("DECL_GIMPLE_REG_P set on a variable with address taken");
|
||||
return x;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
@ -2815,8 +2850,10 @@ verify_types_in_gimple_min_lval (tree expr)
|
|||
if (is_gimple_id (expr))
|
||||
return false;
|
||||
|
||||
if (!INDIRECT_REF_P (expr)
|
||||
&& TREE_CODE (expr) != TARGET_MEM_REF)
|
||||
if (TREE_CODE (expr) != ALIGN_INDIRECT_REF
|
||||
&& TREE_CODE (expr) != MISALIGNED_INDIRECT_REF
|
||||
&& TREE_CODE (expr) != TARGET_MEM_REF
|
||||
&& TREE_CODE (expr) != MEM_REF)
|
||||
{
|
||||
error ("invalid expression for min lvalue");
|
||||
return true;
|
||||
|
|
@ -2833,14 +2870,7 @@ verify_types_in_gimple_min_lval (tree expr)
|
|||
debug_generic_stmt (op);
|
||||
return true;
|
||||
}
|
||||
if (!useless_type_conversion_p (TREE_TYPE (expr),
|
||||
TREE_TYPE (TREE_TYPE (op))))
|
||||
{
|
||||
error ("type mismatch in indirect reference");
|
||||
debug_generic_stmt (TREE_TYPE (expr));
|
||||
debug_generic_stmt (TREE_TYPE (TREE_TYPE (op)));
|
||||
return true;
|
||||
}
|
||||
/* Memory references now generally can involve a value conversion. */
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2927,6 +2957,13 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
|
|||
debug_generic_stmt (expr);
|
||||
return true;
|
||||
}
|
||||
else if (TREE_CODE (op) == SSA_NAME
|
||||
&& TYPE_SIZE (TREE_TYPE (expr)) != TYPE_SIZE (TREE_TYPE (op)))
|
||||
{
|
||||
error ("Conversion of register to a different size.");
|
||||
debug_generic_stmt (expr);
|
||||
return true;
|
||||
}
|
||||
else if (!handled_component_p (op))
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2934,6 +2971,23 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
|
|||
expr = op;
|
||||
}
|
||||
|
||||
if (TREE_CODE (expr) == MEM_REF)
|
||||
{
|
||||
if (!is_gimple_mem_ref_addr (TREE_OPERAND (expr, 0)))
|
||||
{
|
||||
error ("Invalid address operand in MEM_REF.");
|
||||
debug_generic_stmt (expr);
|
||||
return true;
|
||||
}
|
||||
if (TREE_CODE (TREE_OPERAND (expr, 1)) != INTEGER_CST
|
||||
|| !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1))))
|
||||
{
|
||||
error ("Invalid offset operand in MEM_REF.");
|
||||
debug_generic_stmt (expr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return ((require_lvalue || !is_gimple_min_invariant (expr))
|
||||
&& verify_types_in_gimple_min_lval (expr));
|
||||
}
|
||||
|
|
@ -3642,9 +3696,12 @@ verify_gimple_assign_single (gimple stmt)
|
|||
}
|
||||
|
||||
/* tcc_reference */
|
||||
case INDIRECT_REF:
|
||||
error ("INDIRECT_REF in gimple IL");
|
||||
return true;
|
||||
|
||||
case COMPONENT_REF:
|
||||
case BIT_FIELD_REF:
|
||||
case INDIRECT_REF:
|
||||
case ALIGN_INDIRECT_REF:
|
||||
case MISALIGNED_INDIRECT_REF:
|
||||
case ARRAY_REF:
|
||||
|
|
@ -3653,6 +3710,7 @@ verify_gimple_assign_single (gimple stmt)
|
|||
case REALPART_EXPR:
|
||||
case IMAGPART_EXPR:
|
||||
case TARGET_MEM_REF:
|
||||
case MEM_REF:
|
||||
if (!is_gimple_reg (lhs)
|
||||
&& is_gimple_reg_type (TREE_TYPE (lhs)))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -596,10 +596,10 @@ extract_component (gimple_stmt_iterator *gsi, tree t, bool imagpart_p,
|
|||
case VAR_DECL:
|
||||
case RESULT_DECL:
|
||||
case PARM_DECL:
|
||||
case INDIRECT_REF:
|
||||
case COMPONENT_REF:
|
||||
case ARRAY_REF:
|
||||
case VIEW_CONVERT_EXPR:
|
||||
case MEM_REF:
|
||||
{
|
||||
tree inner_type = TREE_TYPE (TREE_TYPE (t));
|
||||
|
||||
|
|
|
|||
|
|
@ -746,7 +746,22 @@ dr_analyze_innermost (struct data_reference *dr)
|
|||
return false;
|
||||
}
|
||||
|
||||
base = build_fold_addr_expr (base);
|
||||
if (TREE_CODE (base) == MEM_REF)
|
||||
{
|
||||
if (!integer_zerop (TREE_OPERAND (base, 1)))
|
||||
{
|
||||
if (!poffset)
|
||||
{
|
||||
double_int moff = mem_ref_offset (base);
|
||||
poffset = double_int_to_tree (sizetype, moff);
|
||||
}
|
||||
else
|
||||
poffset = size_binop (PLUS_EXPR, poffset, TREE_OPERAND (base, 1));
|
||||
}
|
||||
base = TREE_OPERAND (base, 0);
|
||||
}
|
||||
else
|
||||
base = build_fold_addr_expr (base);
|
||||
if (in_loop)
|
||||
{
|
||||
if (!simple_iv (loop, loop_containing_stmt (stmt), base, &base_iv,
|
||||
|
|
@ -844,13 +859,18 @@ dr_analyze_indices (struct data_reference *dr, struct loop *nest)
|
|||
aref = TREE_OPERAND (aref, 0);
|
||||
}
|
||||
|
||||
if (nest && INDIRECT_REF_P (aref))
|
||||
if (nest
|
||||
&& (INDIRECT_REF_P (aref)
|
||||
|| TREE_CODE (aref) == MEM_REF))
|
||||
{
|
||||
op = TREE_OPERAND (aref, 0);
|
||||
access_fn = analyze_scalar_evolution (loop, op);
|
||||
access_fn = instantiate_scev (before_loop, loop, access_fn);
|
||||
base = initial_condition (access_fn);
|
||||
split_constant_offset (base, &base, &off);
|
||||
if (TREE_CODE (aref) == MEM_REF)
|
||||
off = size_binop (PLUS_EXPR, off,
|
||||
fold_convert (ssizetype, TREE_OPERAND (aref, 1)));
|
||||
access_fn = chrec_replace_initial_condition (access_fn,
|
||||
fold_convert (TREE_TYPE (base), off));
|
||||
|
||||
|
|
@ -858,6 +878,22 @@ dr_analyze_indices (struct data_reference *dr, struct loop *nest)
|
|||
VEC_safe_push (tree, heap, access_fns, access_fn);
|
||||
}
|
||||
|
||||
if (TREE_CODE (aref) == MEM_REF)
|
||||
TREE_OPERAND (aref, 1)
|
||||
= build_int_cst (TREE_TYPE (TREE_OPERAND (aref, 1)), 0);
|
||||
|
||||
if (TREE_CODE (ref) == MEM_REF
|
||||
&& TREE_CODE (TREE_OPERAND (ref, 0)) == ADDR_EXPR
|
||||
&& integer_zerop (TREE_OPERAND (ref, 1)))
|
||||
ref = TREE_OPERAND (TREE_OPERAND (ref, 0), 0);
|
||||
|
||||
/* For canonicalization purposes we'd like to strip all outermost
|
||||
zero-offset component-refs.
|
||||
??? For now simply handle zero-index array-refs. */
|
||||
while (TREE_CODE (ref) == ARRAY_REF
|
||||
&& integer_zerop (TREE_OPERAND (ref, 1)))
|
||||
ref = TREE_OPERAND (ref, 0);
|
||||
|
||||
DR_BASE_OBJECT (dr) = ref;
|
||||
DR_ACCESS_FNS (dr) = access_fns;
|
||||
}
|
||||
|
|
@ -870,7 +906,8 @@ dr_analyze_alias (struct data_reference *dr)
|
|||
tree ref = DR_REF (dr);
|
||||
tree base = get_base_address (ref), addr;
|
||||
|
||||
if (INDIRECT_REF_P (base))
|
||||
if (INDIRECT_REF_P (base)
|
||||
|| TREE_CODE (base) == MEM_REF)
|
||||
{
|
||||
addr = TREE_OPERAND (base, 0);
|
||||
if (TREE_CODE (addr) == SSA_NAME)
|
||||
|
|
@ -1188,7 +1225,8 @@ object_address_invariant_in_loop_p (const struct loop *loop, const_tree obj)
|
|||
obj = TREE_OPERAND (obj, 0);
|
||||
}
|
||||
|
||||
if (!INDIRECT_REF_P (obj))
|
||||
if (!INDIRECT_REF_P (obj)
|
||||
&& TREE_CODE (obj) != MEM_REF)
|
||||
return true;
|
||||
|
||||
return !chrec_contains_symbols_defined_in_loop (TREE_OPERAND (obj, 0),
|
||||
|
|
|
|||
122
gcc/tree-dfa.c
122
gcc/tree-dfa.c
|
|
@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "toplev.h"
|
||||
#include "hashtab.h"
|
||||
#include "pointer-set.h"
|
||||
#include "tree.h"
|
||||
|
|
@ -855,6 +856,29 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
|
|||
case VIEW_CONVERT_EXPR:
|
||||
break;
|
||||
|
||||
case MEM_REF:
|
||||
/* Hand back the decl for MEM[&decl, off]. */
|
||||
if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR)
|
||||
{
|
||||
if (integer_zerop (TREE_OPERAND (exp, 1)))
|
||||
exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
|
||||
else
|
||||
{
|
||||
double_int off = mem_ref_offset (exp);
|
||||
off = double_int_lshift (off,
|
||||
BITS_PER_UNIT == 8
|
||||
? 3 : exact_log2 (BITS_PER_UNIT),
|
||||
HOST_BITS_PER_DOUBLE_INT, true);
|
||||
off = double_int_add (off, shwi_to_double_int (bit_offset));
|
||||
if (double_int_fits_in_shwi_p (off))
|
||||
{
|
||||
bit_offset = double_int_to_shwi (off);
|
||||
exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
goto done;
|
||||
|
||||
default:
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -901,6 +925,104 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
|
|||
return exp;
|
||||
}
|
||||
|
||||
/* Returns the base object and a constant BITS_PER_UNIT offset in *POFFSET that
|
||||
denotes the starting address of the memory access EXP.
|
||||
Returns NULL_TREE if the offset is not constant or any component
|
||||
is not BITS_PER_UNIT-aligned. */
|
||||
|
||||
tree
|
||||
get_addr_base_and_unit_offset (tree exp, HOST_WIDE_INT *poffset)
|
||||
{
|
||||
HOST_WIDE_INT byte_offset = 0;
|
||||
|
||||
/* Compute cumulative byte-offset for nested component-refs and array-refs,
|
||||
and find the ultimate containing object. */
|
||||
while (1)
|
||||
{
|
||||
switch (TREE_CODE (exp))
|
||||
{
|
||||
case BIT_FIELD_REF:
|
||||
return NULL_TREE;
|
||||
|
||||
case COMPONENT_REF:
|
||||
{
|
||||
tree field = TREE_OPERAND (exp, 1);
|
||||
tree this_offset = component_ref_field_offset (exp);
|
||||
HOST_WIDE_INT hthis_offset;
|
||||
|
||||
if (!this_offset
|
||||
|| TREE_CODE (this_offset) != INTEGER_CST
|
||||
|| (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field))
|
||||
% BITS_PER_UNIT))
|
||||
return NULL_TREE;
|
||||
|
||||
hthis_offset = TREE_INT_CST_LOW (this_offset);
|
||||
hthis_offset += (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field))
|
||||
/ BITS_PER_UNIT);
|
||||
byte_offset += hthis_offset;
|
||||
}
|
||||
break;
|
||||
|
||||
case ARRAY_REF:
|
||||
case ARRAY_RANGE_REF:
|
||||
{
|
||||
tree index = TREE_OPERAND (exp, 1);
|
||||
tree low_bound, unit_size;
|
||||
|
||||
/* If the resulting bit-offset is constant, track it. */
|
||||
if (TREE_CODE (index) == INTEGER_CST
|
||||
&& (low_bound = array_ref_low_bound (exp),
|
||||
TREE_CODE (low_bound) == INTEGER_CST)
|
||||
&& (unit_size = array_ref_element_size (exp),
|
||||
TREE_CODE (unit_size) == INTEGER_CST))
|
||||
{
|
||||
HOST_WIDE_INT hindex = TREE_INT_CST_LOW (index);
|
||||
|
||||
hindex -= TREE_INT_CST_LOW (low_bound);
|
||||
hindex *= TREE_INT_CST_LOW (unit_size);
|
||||
byte_offset += hindex;
|
||||
}
|
||||
else
|
||||
return NULL_TREE;
|
||||
}
|
||||
break;
|
||||
|
||||
case REALPART_EXPR:
|
||||
break;
|
||||
|
||||
case IMAGPART_EXPR:
|
||||
byte_offset += TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (exp)));
|
||||
break;
|
||||
|
||||
case VIEW_CONVERT_EXPR:
|
||||
break;
|
||||
|
||||
case MEM_REF:
|
||||
/* Hand back the decl for MEM[&decl, off]. */
|
||||
if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR)
|
||||
{
|
||||
if (!integer_zerop (TREE_OPERAND (exp, 1)))
|
||||
{
|
||||
double_int off = mem_ref_offset (exp);
|
||||
gcc_assert (off.high == -1 || off.high == 0);
|
||||
byte_offset += double_int_to_shwi (off);
|
||||
}
|
||||
exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
|
||||
}
|
||||
goto done;
|
||||
|
||||
default:
|
||||
goto done;
|
||||
}
|
||||
|
||||
exp = TREE_OPERAND (exp, 0);
|
||||
}
|
||||
done:
|
||||
|
||||
*poffset = byte_offset;
|
||||
return exp;
|
||||
}
|
||||
|
||||
/* Returns true if STMT references an SSA_NAME that has
|
||||
SSA_NAME_OCCURS_IN_ABNORMAL_PHI set, otherwise false. */
|
||||
|
||||
|
|
|
|||
|
|
@ -2437,6 +2437,10 @@ tree_could_trap_p (tree expr)
|
|||
return false;
|
||||
return !in_array_bounds_p (expr);
|
||||
|
||||
case MEM_REF:
|
||||
if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR)
|
||||
return false;
|
||||
/* Fallthru. */
|
||||
case INDIRECT_REF:
|
||||
case ALIGN_INDIRECT_REF:
|
||||
case MISALIGNED_INDIRECT_REF:
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue