2018-06-08 Martin Liska <mliska@suse.cz> * MAINTAINERS: Remove MPX-related entries. * Makefile.def: Remove libmpx support. * Makefile.in: Likewise. * configure: Remove removed files. * configure.ac: Likewise. * libmpx/ChangeLog: Remove. * libmpx/Makefile.am: Remove. * libmpx/Makefile.in: Remove. * libmpx/acinclude.m4: Remove. * libmpx/aclocal.m4: Remove. * libmpx/config.h.in: Remove. * libmpx/configure: Remove. * libmpx/configure.ac: Remove. * libmpx/configure.tgt: Remove. * libmpx/libmpx.spec.in: Remove. * libmpx/mpxrt/Makefile.am: Remove. * libmpx/mpxrt/Makefile.in: Remove. * libmpx/mpxrt/libmpx.map: Remove. * libmpx/mpxrt/libtool-version: Remove. * libmpx/mpxrt/mpxrt-utils.c: Remove. * libmpx/mpxrt/mpxrt-utils.h: Remove. * libmpx/mpxrt/mpxrt.c: Remove. * libmpx/mpxrt/mpxrt.h: Remove. * libmpx/mpxwrap/Makefile.am: Remove. * libmpx/mpxwrap/Makefile.in: Remove. * libmpx/mpxwrap/libmpxwrappers.map: Remove. * libmpx/mpxwrap/libtool-version: Remove. * libmpx/mpxwrap/mpx_wrappers.c: Remove. 2018-06-08 Martin Liska <mliska@suse.cz> * bootstrap-mpx.mk: Remove. 2018-06-08 Martin Liska <mliska@suse.cz> * Makefile.in: Remove support for MPX (macros, related functions, fields in cgraph_node, ...). * builtin-types.def (BT_BND): Likewise. (BT_FN_BND_CONST_PTR): Likewise. (BT_FN_CONST_PTR_BND): Likewise. (BT_FN_VOID_PTR_BND): Likewise. (BT_FN_BND_CONST_PTR_SIZE): Likewise. (BT_FN_VOID_CONST_PTR_BND_CONST_PTR): Likewise. * builtins.c (expand_builtin_memcpy_with_bounds): Likewise. (expand_builtin_mempcpy_with_bounds): Likewise. (expand_builtin_memset_with_bounds): Likewise. (expand_builtin_memset_args): Likewise. (std_expand_builtin_va_start): Likewise. (expand_builtin): Likewise. (expand_builtin_with_bounds): Likewise. * builtins.def (DEF_BUILTIN_CHKP): Likewise. (DEF_LIB_BUILTIN_CHKP): Likewise. (DEF_EXT_LIB_BUILTIN_CHKP): Likewise. (DEF_CHKP_BUILTIN): Likewise. (BUILT_IN_MEMCPY): Likewise. (BUILT_IN_MEMMOVE): Likewise. (BUILT_IN_MEMPCPY): Likewise. (BUILT_IN_MEMSET): Likewise. (BUILT_IN_STPCPY): Likewise. (BUILT_IN_STRCAT): Likewise. (BUILT_IN_STRCHR): Likewise. (BUILT_IN_STRCPY): Likewise. (BUILT_IN_STRLEN): Likewise. (BUILT_IN_MEMCPY_CHK): Likewise. (BUILT_IN_MEMMOVE_CHK): Likewise. (BUILT_IN_MEMPCPY_CHK): Likewise. (BUILT_IN_MEMSET_CHK): Likewise. (BUILT_IN_STPCPY_CHK): Likewise. (BUILT_IN_STRCAT_CHK): Likewise. (BUILT_IN_STRCPY_CHK): Likewise. * calls.c (store_bounds): Likewise. (emit_call_1): Likewise. (special_function_p): Likewise. (maybe_warn_nonstring_arg): Likewise. (initialize_argument_information): Likewise. (finalize_must_preallocate): Likewise. (compute_argument_addresses): Likewise. (expand_call): Likewise. * cfgexpand.c (expand_call_stmt): Likewise. (expand_return): Likewise. (expand_gimple_stmt_1): Likewise. (pass_expand::execute): Likewise. * cgraph.c (cgraph_edge::redirect_call_stmt_to_callee): Likewise. (cgraph_node::remove): Likewise. (cgraph_node::dump): Likewise. (cgraph_node::verify_node): Likewise. * cgraph.h (chkp_function_instrumented_p): Likewise. (symtab_node::get_alias_target): Likewise. (cgraph_node::can_remove_if_no_direct_calls_and_refs_p): Likewise. (cgraph_local_p): Likewise. * cgraphbuild.c (cgraph_edge::rebuild_edges): Likewise. (cgraph_edge::rebuild_references): Likewise. * cgraphunit.c (varpool_node::finalize_decl): Likewise. (walk_polymorphic_call_targets): Likewise. (cgraph_node::expand_thunk): Likewise. (symbol_table::output_weakrefs): Likewise. * common/config/i386/i386-common.c (OPTION_MASK_ISA2_GENERAL_REGS_ONLY_UNSET): Likewise. (ix86_handle_option): Likewise. * config/i386/constraints.md: Likewise. * config/i386/i386-builtin-types.def (BND): Likewise. (VOID): Likewise. (PVOID): Likewise. (ULONG): Likewise. * config/i386/i386-builtin.def (BDESC_END): Likewise. (BDESC_FIRST): Likewise. (BDESC): Likewise. * config/i386/i386-c.c (ix86_target_macros_internal): Likewise. * config/i386/i386-protos.h (ix86_bnd_prefixed_insn_p): Likewise. * config/i386/i386.c (enum reg_class): Likewise. (ix86_target_string): Likewise. (ix86_option_override_internal): Likewise. (ix86_conditional_register_usage): Likewise. (ix86_valid_target_attribute_inner_p): Likewise. (ix86_set_indirect_branch_type): Likewise. (ix86_set_current_function): Likewise. (ix86_function_arg_regno_p): Likewise. (init_cumulative_args): Likewise. (ix86_function_arg_advance): Likewise. (ix86_function_arg): Likewise. (ix86_pass_by_reference): Likewise. (ix86_function_value_regno_p): Likewise. (ix86_function_value_1): Likewise. (ix86_function_value_bounds): Likewise. (ix86_return_in_memory): Likewise. (ix86_setup_incoming_vararg_bounds): Likewise. (ix86_va_start): Likewise. (indirect_thunk_need_prefix): Likewise. (print_reg): Likewise. (ix86_print_operand): Likewise. (ix86_expand_call): Likewise. (ix86_output_function_return): Likewise. (reg_encoded_number): Likewise. (BDESC_VERIFYS): Likewise. (ix86_init_mpx_builtins): Likewise. (ix86_init_builtins): Likewise. (ix86_emit_cmove): Likewise. (ix86_emit_move_max): Likewise. (ix86_expand_builtin): Likewise. (ix86_builtin_mpx_function): Likewise. (ix86_get_arg_address_for_bt): Likewise. (ix86_load_bounds): Likewise. (ix86_store_bounds): Likewise. (ix86_load_returned_bounds): Likewise. (ix86_store_returned_bounds): Likewise. (ix86_class_likely_spilled_p): Likewise. (ix86_hard_regno_mode_ok): Likewise. (x86_order_regs_for_local_alloc): Likewise. (ix86_mitigate_rop): Likewise. (ix86_bnd_prefixed_insn_p): Likewise. (ix86_mpx_bound_mode): Likewise. (ix86_make_bounds_constant): Likewise. (ix86_initialize_bounds): Likewise. (TARGET_LOAD_BOUNDS_FOR_ARG): Likewise. (TARGET_STORE_BOUNDS_FOR_ARG): Likewise. (TARGET_LOAD_RETURNED_BOUNDS): Likewise. (TARGET_STORE_RETURNED_BOUNDS): Likewise. (TARGET_CHKP_BOUND_MODE): Likewise. (TARGET_BUILTIN_CHKP_FUNCTION): Likewise. (TARGET_CHKP_FUNCTION_VALUE_BOUNDS): Likewise. (TARGET_CHKP_MAKE_BOUNDS_CONSTANT): Likewise. (TARGET_CHKP_INITIALIZE_BOUNDS): Likewise. * config/i386/i386.h (TARGET_MPX): Likewise. (TARGET_MPX_P): Likewise. (VALID_BND_REG_MODE): Likewise. (FIRST_BND_REG): Likewise. (LAST_BND_REG): Likewise. (enum reg_class): Likewise. (BND_REG_P): Likewise. (BND_REGNO_P): Likewise. (BNDmode): Likewise. (ADJUST_INSN_LENGTH): Likewise. * config/i386/i386.md: Likewise. * config/i386/i386.opt: Likewise. * config/i386/linux-common.h (LIBMPX_LIBS): Likewise. (defined): Likewise. (LINK_MPX): Likewise. (MPX_SPEC): Likewise. (LIBMPX_SPEC): Likewise. (LIBMPXWRAPPERS_SPEC): Likewise. (CHKP_SPEC): Likewise. * config/i386/predicates.md: Likewise. * dbxout.c (dbxout_type): Likewise. * doc/extend.texi: Likewise. * doc/invoke.texi: Likewise. * doc/md.texi: Likewise. * doc/tm.texi: Likewise. * doc/tm.texi.in: Likewise. * dwarf2out.c (is_base_type): Likewise. (gen_formal_types_die): Likewise. (gen_subprogram_die): Likewise. (gen_type_die_with_usage): Likewise. (gen_decl_die): Likewise. (dwarf2out_late_global_decl): Likewise. * expr.c (expand_assignment): Likewise. (emit_storent_insn): Likewise. (store_expr_with_bounds): Likewise. (store_expr): Likewise. (expand_expr_real_1): Likewise. * expr.h (store_expr_with_bounds): Likewise. * function.c (use_register_for_decl): Likewise. (struct bounds_parm_data): Likewise. (assign_parms_augmented_arg_list): Likewise. (assign_parm_find_entry_rtl): Likewise. (assign_parm_is_stack_parm): Likewise. (assign_parm_load_bounds): Likewise. (assign_bounds): Likewise. (assign_parms): Likewise. (expand_function_start): Likewise. * gcc.c (CHKP_SPEC): Likewise. * gimple-fold.c (gimple_fold_builtin_memory_op): Likewise. * gimple-ssa-warn-restrict.c (builtin_access::builtin_access): Likewise. (wrestrict_dom_walker::check_call): Likewise. * gimple.c (gimple_build_call_from_tree): Likewise. * gimple.h (enum gf_mask): Likewise. (gimple_call_with_bounds_p): Likewise. (gimple_call_set_with_bounds): Likewise. * gimplify.c (gimplify_init_constructor): Likewise. * ipa-cp.c (initialize_node_lattices): Likewise. (propagate_constants_across_call): Likewise. (find_more_scalar_values_for_callers_subset): Likewise. * ipa-hsa.c (process_hsa_functions): Likewise. * ipa-icf-gimple.c (func_checker::compare_gimple_call): Likewise. * ipa-icf.c (sem_function::merge): Likewise. * ipa-inline.c (early_inliner): Likewise. * ipa-pure-const.c (warn_function_noreturn): Likewise. (warn_function_cold): Likewise. (propagate_pure_const): Likewise. * ipa-ref.h (enum GTY): Likewise. * ipa-split.c (find_retbnd): Likewise. (consider_split): Likewise. (split_function): Likewise. * ipa-visibility.c (cgraph_externally_visible_p): Likewise. * ipa.c (walk_polymorphic_call_targets): Likewise. (symbol_table::remove_unreachable_nodes): Likewise. (process_references): Likewise. (cgraph_build_static_cdtor_1): Likewise. * lto-cgraph.c (lto_output_node): Likewise. (output_refs): Likewise. (compute_ltrans_boundary): Likewise. (input_overwrite_node): Likewise. (input_node): Likewise. (input_cgraph_1): Likewise. * params.def (PARAM_CHKP_MAX_CTOR_SIZE): Likewise. * passes.c (pass_manager::execute_early_local_passes): Likewise. (class pass_chkp_instrumentation_passes): Likewise. (make_pass_chkp_instrumentation_passes): Likewise. * passes.def: Likewise. * rtl.h (struct GTY): Likewise. (CALL_EXPR_WITH_BOUNDS_P): Likewise. * stor-layout.c (layout_type): Likewise. * symtab.c: Likewise. * target.def: Likewise. * targhooks.c (default_chkp_bound_type): Likewise. (default_chkp_bound_mode): Likewise. (default_builtin_chkp_function): Likewise. (default_chkp_function_value_bounds): Likewise. (default_chkp_make_bounds_constant): Likewise. (default_chkp_initialize_bounds): Likewise. * targhooks.h (default_chkp_bound_type): Likewise. (default_chkp_bound_mode): Likewise. (default_builtin_chkp_function): Likewise. (default_chkp_function_value_bounds): Likewise. (default_chkp_make_bounds_constant): Likewise. (default_chkp_initialize_bounds): Likewise. * toplev.c (compile_file): Likewise. (process_options): Likewise. * tree-core.h (DEF_BUILTIN): Likewise. (DEF_BUILTIN_CHKP): Likewise. * tree-inline.c (declare_return_variable): Likewise. (remap_gimple_stmt): Likewise. (copy_bb): Likewise. (initialize_inlined_parameters): Likewise. (expand_call_inline): Likewise. * tree-pass.h (make_pass_ipa_chkp_versioning): Likewise. (make_pass_ipa_chkp_early_produce_thunks): Likewise. (make_pass_ipa_chkp_produce_thunks): Likewise. (make_pass_chkp): Likewise. (make_pass_chkp_opt): Likewise. (make_pass_chkp_instrumentation_passes): Likewise. * tree-pretty-print.c (dump_generic_node): Likewise. * tree-ssa-ccp.c (insert_clobber_before_stack_restore): Likewise. * tree-ssa-dce.c (propagate_necessity): Likewise. (eliminate_unnecessary_stmts): Likewise. * tree-ssa-pre.c (create_expression_by_pieces): Likewise. * tree-ssa-sccvn.c (copy_reference_ops_from_call): Likewise. * tree-ssa-sccvn.h: Likewise. * tree-ssa-strlen.c (get_string_length): Likewise. (valid_builtin_call): Likewise. (adjust_last_stmt): Likewise. (handle_builtin_strchr): Likewise. (handle_builtin_strcpy): Likewise. (handle_builtin_stxncpy): Likewise. (handle_builtin_memcpy): Likewise. (handle_builtin_strcat): Likewise. (strlen_check_and_optimize_stmt): Likewise. * tree-stdarg.c (expand_ifn_va_arg_1): Likewise. * tree-streamer-in.c: Likewise. * tree-streamer.c (record_common_node): Likewise. * tree.c (tree_code_size): Likewise. (wide_int_to_tree_1): Likewise. (type_contains_placeholder_1): Likewise. (build_common_tree_nodes): Likewise. * tree.def (POINTER_BOUNDS_TYPE): Likewise. * tree.h (POINTER_BOUNDS_TYPE_P): Likewise. (POINTER_BOUNDS_P): Likewise. (BOUNDED_TYPE_P): Likewise. (BOUNDED_P): Likewise. (CALL_WITH_BOUNDS_P): Likewise. (pointer_bounds_type_node): Likewise. * value-prof.c (gimple_ic): Likewise. * var-tracking.c (vt_add_function_parameters): Likewise. * varasm.c (make_decl_rtl): Likewise. (assemble_start_function): Likewise. (output_constant): Likewise. (maybe_assemble_visibility): Likewise. * varpool.c (ctor_for_folding): Likewise. * chkp-builtins.def: Remove. * ipa-chkp.c: Remove. * ipa-chkp.h: Remove. * rtl-chkp.c: Remove. * rtl-chkp.h: Remove. * tree-chkp-opt.c: Remove. * tree-chkp.c: Remove. * tree-chkp.h: Remove. 2018-06-08 Martin Liska <mliska@suse.cz> * c-attribs.c (handle_bnd_variable_size_attribute): Remove support for MPX (macros, related functions, fields in cgraph_node, ...). (handle_bnd_legacy): Likewise. (handle_bnd_instrument): Likewise. * c.opt: Likewise. 2018-06-08 Martin Liska <mliska@suse.cz> * lto-partition.c (add_references_to_partition): Remove support for MPX (macros, related functions, fields in cgraph_node, ...). (add_symbol_to_partition_1): Likewise. (privatize_symbol_name): Likewise. * lto-symtab.c (lto_cgraph_replace_node): Likewise. 2018-06-08 Martin Liska <mliska@suse.cz> * g++.dg/dg.exp: Do not use mpx.exp. * g++.dg/lto/lto.exp: Likewise. * g++.dg/lto/pr69729_0.C: Remove. * g++.dg/opt/pr71529.C: Remove. * g++.dg/pr63995-1.C: Remove. * g++.dg/pr68270.C: Remove. * g++.dg/pr71624.C: Remove. * g++.dg/pr71633.C: Remove. * g++.dg/pr79761.C: Remove. * g++.dg/pr79764.C: Remove. * g++.dg/pr79769.C: Remove. * gcc.dg/lto/chkp-privatize-1_0.c: Remove. * gcc.dg/lto/chkp-privatize-2_0.c: Remove. * gcc.dg/lto/chkp-privatize_0.c: Remove. * gcc.dg/lto/chkp-removed-alias_0.c: Remove. * gcc.dg/lto/chkp-static-bounds_0.c: Remove. * gcc.dg/lto/chkp-wrap-asm-name_0.c: Remove. * gcc.dg/lto/lto.exp: Do not use mpx.exp. * gcc.dg/lto/pr66221_0.c: Remove. * gcc.target/i386/chkp-always_inline.c: Remove. * gcc.target/i386/chkp-bndret.c: Remove. * gcc.target/i386/chkp-builtins-1.c: Remove. * gcc.target/i386/chkp-builtins-2.c: Remove. * gcc.target/i386/chkp-builtins-3.c: Remove. * gcc.target/i386/chkp-builtins-4.c: Remove. * gcc.target/i386/chkp-const-check-1.c: Remove. * gcc.target/i386/chkp-const-check-2.c: Remove. * gcc.target/i386/chkp-hidden-def.c: Remove. * gcc.target/i386/chkp-label-address.c: Remove. * gcc.target/i386/chkp-lifetime-1.c: Remove. * gcc.target/i386/chkp-narrow-bounds.c: Remove. * gcc.target/i386/chkp-pr69044.c: Remove. * gcc.target/i386/chkp-remove-bndint-1.c: Remove. * gcc.target/i386/chkp-remove-bndint-2.c: Remove. * gcc.target/i386/chkp-strchr.c: Remove. * gcc.target/i386/chkp-strlen-1.c: Remove. * gcc.target/i386/chkp-strlen-2.c: Remove. * gcc.target/i386/chkp-strlen-3.c: Remove. * gcc.target/i386/chkp-strlen-4.c: Remove. * gcc.target/i386/chkp-strlen-5.c: Remove. * gcc.target/i386/chkp-stropt-1.c: Remove. * gcc.target/i386/chkp-stropt-10.c: Remove. * gcc.target/i386/chkp-stropt-11.c: Remove. * gcc.target/i386/chkp-stropt-12.c: Remove. * gcc.target/i386/chkp-stropt-13.c: Remove. * gcc.target/i386/chkp-stropt-14.c: Remove. * gcc.target/i386/chkp-stropt-15.c: Remove. * gcc.target/i386/chkp-stropt-16.c: Remove. * gcc.target/i386/chkp-stropt-17.c: Remove. * gcc.target/i386/chkp-stropt-2.c: Remove. * gcc.target/i386/chkp-stropt-3.c: Remove. * gcc.target/i386/chkp-stropt-4.c: Remove. * gcc.target/i386/chkp-stropt-5.c: Remove. * gcc.target/i386/chkp-stropt-6.c: Remove. * gcc.target/i386/chkp-stropt-7.c: Remove. * gcc.target/i386/chkp-stropt-8.c: Remove. * gcc.target/i386/chkp-stropt-9.c: Remove. * gcc.target/i386/i386.exp: Do not use mpx.exp. * gcc.target/i386/indirect-thunk-11.c: Remove. * gcc.target/i386/indirect-thunk-12.c: Remove. * gcc.target/i386/indirect-thunk-attr-12.c: Remove. * gcc.target/i386/indirect-thunk-attr-13.c: Remove. * gcc.target/i386/indirect-thunk-bnd-1.c: Remove. * gcc.target/i386/indirect-thunk-bnd-2.c: Remove. * gcc.target/i386/indirect-thunk-bnd-3.c: Remove. * gcc.target/i386/indirect-thunk-bnd-4.c: Remove. * gcc.target/i386/interrupt-bnd-err-1.c: Remove. * gcc.target/i386/interrupt-bnd-err-2.c: Remove. * gcc.target/i386/mpx/alloca-1-lbv.c: Remove. * gcc.target/i386/mpx/alloca-1-nov.c: Remove. * gcc.target/i386/mpx/alloca-1-ubv.c: Remove. * gcc.target/i386/mpx/arg-addr-1-lbv.c: Remove. * gcc.target/i386/mpx/arg-addr-1-nov.c: Remove. * gcc.target/i386/mpx/arg-addr-1-ubv.c: Remove. * gcc.target/i386/mpx/bitfields-1-lbv.c: Remove. * gcc.target/i386/mpx/bitfields-1-nov.c: Remove. * gcc.target/i386/mpx/bitfields-1-ubv.c: Remove. * gcc.target/i386/mpx/builtin-bnd-chk-ptr-bounds-1-lbv.c: Remove. * gcc.target/i386/mpx/builtin-bnd-chk-ptr-bounds-1-nov.c: Remove. * gcc.target/i386/mpx/builtin-bnd-chk-ptr-bounds-1-ubv.c: Remove. * gcc.target/i386/mpx/builtin-bnd-chk-ptr-bounds-2.c: Remove. * gcc.target/i386/mpx/builtin-bnd-chk-ptr-lbounds-1-lbv.c: Remove. * gcc.target/i386/mpx/builtin-bnd-chk-ptr-lbounds-1-nov.c: Remove. * gcc.target/i386/mpx/builtin-bnd-chk-ptr-lbounds-2.c: Remove. * gcc.target/i386/mpx/builtin-bnd-chk-ptr-ubounds-1-nov.c: Remove. * gcc.target/i386/mpx/builtin-bnd-chk-ptr-ubounds-1-ubv.c: Remove. * gcc.target/i386/mpx/builtin-bnd-chk-ptr-ubounds-2.c: Remove. * gcc.target/i386/mpx/builtin-bnd-copy-ptr-bounds-1.c: Remove. * gcc.target/i386/mpx/builtin-bnd-copy-ptr-bounds-2-lbv.c: Remove. * gcc.target/i386/mpx/builtin-bnd-copy-ptr-bounds-2-nov.c: Remove. * gcc.target/i386/mpx/builtin-bnd-copy-ptr-bounds-2-ubv.c: Remove. * gcc.target/i386/mpx/builtin-bnd-copy-ptr-bounds-3.c: Remove. * gcc.target/i386/mpx/builtin-bnd-get-ptr-lbound-1.c: Remove. * gcc.target/i386/mpx/builtin-bnd-get-ptr-lbound-2.c: Remove. * gcc.target/i386/mpx/builtin-bnd-get-ptr-ubound-1.c: Remove. * gcc.target/i386/mpx/builtin-bnd-get-ptr-ubound-2.c: Remove. * gcc.target/i386/mpx/builtin-bnd-init-ptr-bounds-1.c: Remove. * gcc.target/i386/mpx/builtin-bnd-init-ptr-bounds-2-nov.c: Remove. * gcc.target/i386/mpx/builtin-bnd-init-ptr-bounds-3.c: Remove. * gcc.target/i386/mpx/builtin-bnd-narrow-ptr-bounds-1.c: Remove. * gcc.target/i386/mpx/builtin-bnd-narrow-ptr-bounds-2-lbv.c: Remove. * gcc.target/i386/mpx/builtin-bnd-narrow-ptr-bounds-2-nov.c: Remove. * gcc.target/i386/mpx/builtin-bnd-narrow-ptr-bounds-2-ubv.c: Remove. * gcc.target/i386/mpx/builtin-bnd-narrow-ptr-bounds-3-lbv.c: Remove. * gcc.target/i386/mpx/builtin-bnd-narrow-ptr-bounds-3-nov.c: Remove. * gcc.target/i386/mpx/builtin-bnd-narrow-ptr-bounds-3-ubv.c: Remove. * gcc.target/i386/mpx/builtin-bnd-narrow-ptr-bounds-4.c: Remove. * gcc.target/i386/mpx/builtin-bnd-null-ptr-bounds-1-bbv.c: Remove. * gcc.target/i386/mpx/builtin-bnd-set-ptr-bounds-1.c: Remove. * gcc.target/i386/mpx/builtin-bnd-set-ptr-bounds-2-lbv.c: Remove. * gcc.target/i386/mpx/builtin-bnd-set-ptr-bounds-2-nov.c: Remove. * gcc.target/i386/mpx/builtin-bnd-set-ptr-bounds-2-ubv.c: Remove. * gcc.target/i386/mpx/builtin-bnd-set-ptr-bounds-3.c: Remove. * gcc.target/i386/mpx/builtin-bnd-store-ptr-bounds-1-lbv.c: Remove. * gcc.target/i386/mpx/builtin-bnd-store-ptr-bounds-1-nov.c: Remove. * gcc.target/i386/mpx/builtin-bnd-store-ptr-bounds-1-ubv.c: Remove. * gcc.target/i386/mpx/builtin-bnd-store-ptr-bounds-2.c: Remove. * gcc.target/i386/mpx/calloc-1-lbv.c: Remove. * gcc.target/i386/mpx/calloc-1-nov.c: Remove. * gcc.target/i386/mpx/calloc-1-ubv.c: Remove. * gcc.target/i386/mpx/chkp-fix-calls-1.c: Remove. * gcc.target/i386/mpx/chkp-fix-calls-2.c: Remove. * gcc.target/i386/mpx/chkp-fix-calls-3.c: Remove. * gcc.target/i386/mpx/chkp-fix-calls-4.c: Remove. * gcc.target/i386/mpx/chkp-thunk-comdat-1.cc: Remove. * gcc.target/i386/mpx/chkp-thunk-comdat-2.cc: Remove. * gcc.target/i386/mpx/chkp-thunk-comdat-3.c: Remove. * gcc.target/i386/mpx/fastcall-1-lbv.c: Remove. * gcc.target/i386/mpx/fastcall-1-nov.c: Remove. * gcc.target/i386/mpx/fastcall-1-ubv.c: Remove. * gcc.target/i386/mpx/fastcall-2-lbv.c: Remove. * gcc.target/i386/mpx/fastcall-2-nov.c: Remove. * gcc.target/i386/mpx/fastcall-2-ubv.c: Remove. * gcc.target/i386/mpx/field-addr-1-lbv.c: Remove. * gcc.target/i386/mpx/field-addr-1-nov.c: Remove. * gcc.target/i386/mpx/field-addr-1-ubv.c: Remove. * gcc.target/i386/mpx/field-addr-10-lbv.c: Remove. * gcc.target/i386/mpx/field-addr-10-nov.c: Remove. * gcc.target/i386/mpx/field-addr-10-ubv.c: Remove. * gcc.target/i386/mpx/field-addr-2-lbv.c: Remove. * gcc.target/i386/mpx/field-addr-2-nov.c: Remove. * gcc.target/i386/mpx/field-addr-2-ubv.c: Remove. * gcc.target/i386/mpx/field-addr-3-lbv.c: Remove. * gcc.target/i386/mpx/field-addr-3-nov.c: Remove. * gcc.target/i386/mpx/field-addr-3-ubv.c: Remove. * gcc.target/i386/mpx/field-addr-4-lbv.c: Remove. * gcc.target/i386/mpx/field-addr-4-nov.c: Remove. * gcc.target/i386/mpx/field-addr-4-ubv.c: Remove. * gcc.target/i386/mpx/field-addr-5-lbv.c: Remove. * gcc.target/i386/mpx/field-addr-5-nov.c: Remove. * gcc.target/i386/mpx/field-addr-5-ubv.c: Remove. * gcc.target/i386/mpx/field-addr-6-lbv.c: Remove. * gcc.target/i386/mpx/field-addr-6-nov.c: Remove. * gcc.target/i386/mpx/field-addr-6-ubv.c: Remove. * gcc.target/i386/mpx/field-addr-7-lbv.c: Remove. * gcc.target/i386/mpx/field-addr-7-nov.c: Remove. * gcc.target/i386/mpx/field-addr-7-ubv.c: Remove. * gcc.target/i386/mpx/field-addr-8-lbv.c: Remove. * gcc.target/i386/mpx/field-addr-8-nov.c: Remove. * gcc.target/i386/mpx/field-addr-8-ubv.c: Remove. * gcc.target/i386/mpx/field-addr-9-lbv.c: Remove. * gcc.target/i386/mpx/field-addr-9-nov.c: Remove. * gcc.target/i386/mpx/field-addr-9-ubv.c: Remove. * gcc.target/i386/mpx/frame-address-1-nov.c: Remove. * gcc.target/i386/mpx/hard-reg-1-nov.c: Remove. * gcc.target/i386/mpx/hard-reg-2-lbv.c: Remove. * gcc.target/i386/mpx/hard-reg-2-nov.c: Remove. * gcc.target/i386/mpx/hard-reg-2-ubv.c: Remove. * gcc.target/i386/mpx/if-stmt-1-lbv.c: Remove. * gcc.target/i386/mpx/if-stmt-1-nov.c: Remove. * gcc.target/i386/mpx/if-stmt-1-ubv.c: Remove. * gcc.target/i386/mpx/if-stmt-2-lbv.c: Remove. * gcc.target/i386/mpx/if-stmt-2-nov.c: Remove. * gcc.target/i386/mpx/if-stmt-2-ubv.c: Remove. * gcc.target/i386/mpx/label-address-1.c: Remove. * gcc.target/i386/mpx/legacy-1-nov.c: Remove. * gcc.target/i386/mpx/macro.c: Remove. * gcc.target/i386/mpx/malloc-1-lbv.c: Remove. * gcc.target/i386/mpx/malloc-1-nov.c: Remove. * gcc.target/i386/mpx/malloc-1-ubv.c: Remove. * gcc.target/i386/mpx/memcpy-1.c: Remove. * gcc.target/i386/mpx/memmove-1.c: Remove. * gcc.target/i386/mpx/memmove-2.c: Remove. * gcc.target/i386/mpx/memmove-zero-length.c: Remove. * gcc.target/i386/mpx/mpx-check.h: Remove. * gcc.target/i386/mpx/mpx-os-support.h: Remove. * gcc.target/i386/mpx/mpx.exp: Remove. * gcc.target/i386/mpx/nested-function-1-lbv.c: Remove. * gcc.target/i386/mpx/nested-function-1-nov.c: Remove. * gcc.target/i386/mpx/nested-function-1-ubv.c: Remove. * gcc.target/i386/mpx/pointer-arg-1-lbv.c: Remove. * gcc.target/i386/mpx/pointer-arg-1-nov.c: Remove. * gcc.target/i386/mpx/pointer-arg-1-ubv.c: Remove. * gcc.target/i386/mpx/pointer-arg-2-lbv.c: Remove. * gcc.target/i386/mpx/pointer-arg-2-nov.c: Remove. * gcc.target/i386/mpx/pointer-arg-2-ubv.c: Remove. * gcc.target/i386/mpx/pointer-arg-3-lbv.c: Remove. * gcc.target/i386/mpx/pointer-arg-3-nov.c: Remove. * gcc.target/i386/mpx/pointer-arg-3-ubv.c: Remove. * gcc.target/i386/mpx/pointer-arg-4-lbv.c: Remove. * gcc.target/i386/mpx/pointer-arg-4-nov.c: Remove. * gcc.target/i386/mpx/pointer-arg-4-ubv.c: Remove. * gcc.target/i386/mpx/pointer-arg-5-lbv.c: Remove. * gcc.target/i386/mpx/pointer-arg-5-nov.c: Remove. * gcc.target/i386/mpx/pointer-arg-5-ubv.c: Remove. * gcc.target/i386/mpx/pointer-diff-1.c: Remove. * gcc.target/i386/mpx/pointer-store-1-lbv.c: Remove. * gcc.target/i386/mpx/pointer-store-1-nov.c: Remove. * gcc.target/i386/mpx/pointer-store-1-ubv.c: Remove. * gcc.target/i386/mpx/pr65508.c: Remove. * gcc.target/i386/mpx/pr65531.cc: Remove. * gcc.target/i386/mpx/pr66048.cc: Remove. * gcc.target/i386/mpx/pr66134.c: Remove. * gcc.target/i386/mpx/pr66566.c: Remove. * gcc.target/i386/mpx/pr66567.c: Remove. * gcc.target/i386/mpx/pr66568.c: Remove. * gcc.target/i386/mpx/pr66569.c: Remove. * gcc.target/i386/mpx/pr66581.c: Remove. * gcc.target/i386/mpx/pr68337-1.c: Remove. * gcc.target/i386/mpx/pr68337-2.c: Remove. * gcc.target/i386/mpx/pr68416.c: Remove. * gcc.target/i386/mpx/pr78339.c: Remove. * gcc.target/i386/mpx/pr79631.c: Remove. * gcc.target/i386/mpx/pr79633.c: Remove. * gcc.target/i386/mpx/pr79753.c: Remove. * gcc.target/i386/mpx/pr79770.c: Remove. * gcc.target/i386/mpx/pr79987.c: Remove. * gcc.target/i386/mpx/pr79988.c: Remove. * gcc.target/i386/mpx/realloc-1-lbv.c: Remove. * gcc.target/i386/mpx/realloc-1-nov.c: Remove. * gcc.target/i386/mpx/realloc-1-ubv.c: Remove. * gcc.target/i386/mpx/realloc-2-lbv.c: Remove. * gcc.target/i386/mpx/realloc-2-nov.c: Remove. * gcc.target/i386/mpx/realloc-2-ubv.c: Remove. * gcc.target/i386/mpx/reference-1-lbv.cpp: Remove. * gcc.target/i386/mpx/reference-1-nov.cpp: Remove. * gcc.target/i386/mpx/reference-1-ubv.cpp: Remove. * gcc.target/i386/mpx/reference-2-lbv.cpp: Remove. * gcc.target/i386/mpx/reference-2-nov.cpp: Remove. * gcc.target/i386/mpx/reference-2-ubv.cpp: Remove. * gcc.target/i386/mpx/reference-3-lbv.cpp: Remove. * gcc.target/i386/mpx/reference-3-nov.cpp: Remove. * gcc.target/i386/mpx/reference-3-ubv.cpp: Remove. * gcc.target/i386/mpx/reference-4-lbv.cpp: Remove. * gcc.target/i386/mpx/reference-4-nov.cpp: Remove. * gcc.target/i386/mpx/reference-4-ubv.cpp: Remove. * gcc.target/i386/mpx/return-pointer-1-lbv.c: Remove. * gcc.target/i386/mpx/return-pointer-1-nov.c: Remove. * gcc.target/i386/mpx/return-pointer-1-ubv.c: Remove. * gcc.target/i386/mpx/return-struct-1-lbv.c: Remove. * gcc.target/i386/mpx/return-struct-1-nov.c: Remove. * gcc.target/i386/mpx/return-struct-1-ubv.c: Remove. * gcc.target/i386/mpx/return-struct-2-lbv.c: Remove. * gcc.target/i386/mpx/return-struct-2-nov.c: Remove. * gcc.target/i386/mpx/return-struct-2-ubv.c: Remove. * gcc.target/i386/mpx/return-struct-3-lbv.c: Remove. * gcc.target/i386/mpx/return-struct-3-nov.c: Remove. * gcc.target/i386/mpx/return-struct-3-ubv.c: Remove. * gcc.target/i386/mpx/return-struct-4-lbv.c: Remove. * gcc.target/i386/mpx/return-struct-4-nov.c: Remove. * gcc.target/i386/mpx/return-struct-4-ubv.c: Remove. * gcc.target/i386/mpx/return-struct-5-lbv.c: Remove. * gcc.target/i386/mpx/return-struct-5-nov.c: Remove. * gcc.target/i386/mpx/return-struct-5-ubv.c: Remove. * gcc.target/i386/mpx/return-struct-6-lbv.c: Remove. * gcc.target/i386/mpx/return-struct-6-nov.c: Remove. * gcc.target/i386/mpx/return-struct-6-ubv.c: Remove. * gcc.target/i386/mpx/sincos-1-nov.c: Remove. * gcc.target/i386/mpx/static-array-1-lbv.c: Remove. * gcc.target/i386/mpx/static-array-1-nov.c: Remove. * gcc.target/i386/mpx/static-array-1-ubv.c: Remove. * gcc.target/i386/mpx/static-init-1-lbv.c: Remove. * gcc.target/i386/mpx/static-init-1-nov.c: Remove. * gcc.target/i386/mpx/static-init-1-ubv.c: Remove. * gcc.target/i386/mpx/static-init-2-lbv.c: Remove. * gcc.target/i386/mpx/static-init-2-nov.c: Remove. * gcc.target/i386/mpx/static-init-2-ubv.c: Remove. * gcc.target/i386/mpx/static-init-3-lbv.c: Remove. * gcc.target/i386/mpx/static-init-3-nov.c: Remove. * gcc.target/i386/mpx/static-init-3-ubv.c: Remove. * gcc.target/i386/mpx/static-init-4-lbv.c: Remove. * gcc.target/i386/mpx/static-init-4-nov.c: Remove. * gcc.target/i386/mpx/static-init-4-ubv.c: Remove. * gcc.target/i386/mpx/static-init-5-lbv.c: Remove. * gcc.target/i386/mpx/static-init-5-nov.c: Remove. * gcc.target/i386/mpx/static-init-5-ubv.c: Remove. * gcc.target/i386/mpx/static-init-6-lbv.c: Remove. * gcc.target/i386/mpx/static-init-6-nov.c: Remove. * gcc.target/i386/mpx/static-init-6-ubv.c: Remove. * gcc.target/i386/mpx/static-string-1-lbv.c: Remove. * gcc.target/i386/mpx/static-string-1-nov.c: Remove. * gcc.target/i386/mpx/static-string-1-ubv.c: Remove. * gcc.target/i386/mpx/struct-arg-1-lbv.c: Remove. * gcc.target/i386/mpx/struct-arg-1-nov.c: Remove. * gcc.target/i386/mpx/struct-arg-1-ubv.c: Remove. * gcc.target/i386/mpx/struct-arg-10-lbv.c: Remove. * gcc.target/i386/mpx/struct-arg-10-nov.c: Remove. * gcc.target/i386/mpx/struct-arg-10-ubv.c: Remove. * gcc.target/i386/mpx/struct-arg-2-lbv.c: Remove. * gcc.target/i386/mpx/struct-arg-2-nov.c: Remove. * gcc.target/i386/mpx/struct-arg-2-ubv.c: Remove. * gcc.target/i386/mpx/struct-arg-3-lbv.c: Remove. * gcc.target/i386/mpx/struct-arg-3-nov.c: Remove. * gcc.target/i386/mpx/struct-arg-3-ubv.c: Remove. * gcc.target/i386/mpx/struct-arg-4-lbv.c: Remove. * gcc.target/i386/mpx/struct-arg-4-nov.c: Remove. * gcc.target/i386/mpx/struct-arg-4-ubv.c: Remove. * gcc.target/i386/mpx/struct-arg-5-lbv.c: Remove. * gcc.target/i386/mpx/struct-arg-5-nov.c: Remove. * gcc.target/i386/mpx/struct-arg-5-ubv.c: Remove. * gcc.target/i386/mpx/struct-arg-6-lbv.c: Remove. * gcc.target/i386/mpx/struct-arg-6-nov.c: Remove. * gcc.target/i386/mpx/struct-arg-6-ubv.c: Remove. * gcc.target/i386/mpx/struct-arg-7-lbv.c: Remove. * gcc.target/i386/mpx/struct-arg-7-nov.c: Remove. * gcc.target/i386/mpx/struct-arg-7-ubv.c: Remove. * gcc.target/i386/mpx/struct-arg-8-lbv.c: Remove. * gcc.target/i386/mpx/struct-arg-8-nov.c: Remove. * gcc.target/i386/mpx/struct-arg-8-ubv.c: Remove. * gcc.target/i386/mpx/struct-arg-9-lbv.c: Remove. * gcc.target/i386/mpx/struct-arg-9-nov.c: Remove. * gcc.target/i386/mpx/struct-arg-9-ubv.c: Remove. * gcc.target/i386/mpx/struct-copy-1-lbv.c: Remove. * gcc.target/i386/mpx/struct-copy-1-nov.c: Remove. * gcc.target/i386/mpx/struct-copy-1-ubv.c: Remove. * gcc.target/i386/mpx/struct-copy-2-lbv.c: Remove. * gcc.target/i386/mpx/struct-copy-2-nov.c: Remove. * gcc.target/i386/mpx/struct-copy-2-ubv.c: Remove. * gcc.target/i386/mpx/thread-local-var-1-lbv.c: Remove. * gcc.target/i386/mpx/thread-local-var-1-nov.c: Remove. * gcc.target/i386/mpx/thread-local-var-1-ubv.c: Remove. * gcc.target/i386/mpx/union-arg-1-lbv.c: Remove. * gcc.target/i386/mpx/union-arg-1-nov.c: Remove. * gcc.target/i386/mpx/union-arg-1-ubv.c: Remove. * gcc.target/i386/mpx/va-arg-pack-1-lbv.c: Remove. * gcc.target/i386/mpx/va-arg-pack-1-nov.c: Remove. * gcc.target/i386/mpx/va-arg-pack-1-ubv.c: Remove. * gcc.target/i386/mpx/va-arg-pack-2-lbv.c: Remove. * gcc.target/i386/mpx/va-arg-pack-2-nov.c: Remove. * gcc.target/i386/mpx/va-arg-pack-2-ubv.c: Remove. * gcc.target/i386/mpx/vararg-1-lbv.c: Remove. * gcc.target/i386/mpx/vararg-1-nov.c: Remove. * gcc.target/i386/mpx/vararg-1-ubv.c: Remove. * gcc.target/i386/mpx/vararg-2-lbv.c: Remove. * gcc.target/i386/mpx/vararg-2-nov.c: Remove. * gcc.target/i386/mpx/vararg-2-ubv.c: Remove. * gcc.target/i386/mpx/vararg-3-lbv.c: Remove. * gcc.target/i386/mpx/vararg-3-nov.c: Remove. * gcc.target/i386/mpx/vararg-3-ubv.c: Remove. * gcc.target/i386/mpx/vararg-4-lbv.c: Remove. * gcc.target/i386/mpx/vararg-4-nov.c: Remove. * gcc.target/i386/mpx/vararg-4-ubv.c: Remove. * gcc.target/i386/mpx/vararg-5-lbv.c: Remove. * gcc.target/i386/mpx/vararg-5-nov.c: Remove. * gcc.target/i386/mpx/vararg-5-ubv.c: Remove. * gcc.target/i386/mpx/vararg-6-lbv.c: Remove. * gcc.target/i386/mpx/vararg-6-nov.c: Remove. * gcc.target/i386/mpx/vararg-6-ubv.c: Remove. * gcc.target/i386/mpx/vararg-7-lbv.c: Remove. * gcc.target/i386/mpx/vararg-7-nov.c: Remove. * gcc.target/i386/mpx/vararg-7-ubv.c: Remove. * gcc.target/i386/mpx/vararg-8-lbv.c: Remove. * gcc.target/i386/mpx/vararg-8-nov.c: Remove. * gcc.target/i386/mpx/vararg-8-ubv.c: Remove. * gcc.target/i386/mpx/vla-1-lbv.c: Remove. * gcc.target/i386/mpx/vla-1-nov.c: Remove. * gcc.target/i386/mpx/vla-1-ubv.c: Remove. * gcc.target/i386/mpx/vla-2-lbv.c: Remove. * gcc.target/i386/mpx/vla-2-nov.c: Remove. * gcc.target/i386/mpx/vla-2-ubv.c: Remove. * gcc.target/i386/mpx/vla-trailing-1-lbv.c: Remove. * gcc.target/i386/mpx/vla-trailing-1-nov.c: Remove. * gcc.target/i386/mpx/vla-trailing-1-ubv.c: Remove. * gcc.target/i386/pr63995-2.c: Remove. * gcc.target/i386/pr64805.c: Remove. * gcc.target/i386/pr65044.c: Remove. * gcc.target/i386/pr65167.c: Remove. * gcc.target/i386/pr65183.c: Remove. * gcc.target/i386/pr65184.c: Remove. * gcc.target/i386/pr65523.c: Remove. * gcc.target/i386/pr70876.c: Remove. * gcc.target/i386/pr70877.c: Remove. * gcc.target/i386/pr71458.c: Remove. * gcc.target/i386/pr80880.c: Remove. * gcc.target/i386/ret-thunk-25.c: Remove. * gcc.target/i386/thunk-retbnd.c: Remove. * lib/mpx-dg.exp: Remove. * gcc.target/i386/funcspec-56.inc: Adjust test case. From-SVN: r261304
1044 lines
28 KiB
C
1044 lines
28 KiB
C
/* Interprocedural Identical Code Folding pass
|
|
Copyright (C) 2014-2018 Free Software Foundation, Inc.
|
|
|
|
Contributed by Jan Hubicka <hubicka@ucw.cz> and Martin Liska <mliska@suse.cz>
|
|
|
|
This file is part of GCC.
|
|
|
|
GCC is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free
|
|
Software Foundation; either version 3, or (at your option) any later
|
|
version.
|
|
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GCC; see the file COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#include "config.h"
|
|
#include "system.h"
|
|
#include "coretypes.h"
|
|
#include "backend.h"
|
|
#include "rtl.h"
|
|
#include "tree.h"
|
|
#include "gimple.h"
|
|
#include "tree-pass.h"
|
|
#include "ssa.h"
|
|
#include "cgraph.h"
|
|
#include "data-streamer.h"
|
|
#include "gimple-pretty-print.h"
|
|
#include "alias.h"
|
|
#include "fold-const.h"
|
|
#include "gimple-iterator.h"
|
|
#include "ipa-utils.h"
|
|
#include "tree-eh.h"
|
|
#include "builtins.h"
|
|
|
|
#include "ipa-icf-gimple.h"
|
|
|
|
namespace ipa_icf_gimple {
|
|
|
|
/* Initialize internal structures for a given SOURCE_FUNC_DECL and
|
|
TARGET_FUNC_DECL. Strict polymorphic comparison is processed if
|
|
an option COMPARE_POLYMORPHIC is true. For special cases, one can
|
|
set IGNORE_LABELS to skip label comparison.
|
|
Similarly, IGNORE_SOURCE_DECLS and IGNORE_TARGET_DECLS are sets
|
|
of declarations that can be skipped. */
|
|
|
|
func_checker::func_checker (tree source_func_decl, tree target_func_decl,
|
|
bool compare_polymorphic,
|
|
bool ignore_labels,
|
|
hash_set<symtab_node *> *ignored_source_nodes,
|
|
hash_set<symtab_node *> *ignored_target_nodes)
|
|
: m_source_func_decl (source_func_decl), m_target_func_decl (target_func_decl),
|
|
m_ignored_source_nodes (ignored_source_nodes),
|
|
m_ignored_target_nodes (ignored_target_nodes),
|
|
m_compare_polymorphic (compare_polymorphic),
|
|
m_ignore_labels (ignore_labels)
|
|
{
|
|
function *source_func = DECL_STRUCT_FUNCTION (source_func_decl);
|
|
function *target_func = DECL_STRUCT_FUNCTION (target_func_decl);
|
|
|
|
unsigned ssa_source = SSANAMES (source_func)->length ();
|
|
unsigned ssa_target = SSANAMES (target_func)->length ();
|
|
|
|
m_source_ssa_names.create (ssa_source);
|
|
m_target_ssa_names.create (ssa_target);
|
|
|
|
for (unsigned i = 0; i < ssa_source; i++)
|
|
m_source_ssa_names.safe_push (-1);
|
|
|
|
for (unsigned i = 0; i < ssa_target; i++)
|
|
m_target_ssa_names.safe_push (-1);
|
|
}
|
|
|
|
/* Memory release routine. */
|
|
|
|
func_checker::~func_checker ()
|
|
{
|
|
m_source_ssa_names.release();
|
|
m_target_ssa_names.release();
|
|
}
|
|
|
|
/* Verifies that trees T1 and T2 are equivalent from perspective of ICF. */
|
|
|
|
bool
|
|
func_checker::compare_ssa_name (tree t1, tree t2)
|
|
{
|
|
gcc_assert (TREE_CODE (t1) == SSA_NAME);
|
|
gcc_assert (TREE_CODE (t2) == SSA_NAME);
|
|
|
|
unsigned i1 = SSA_NAME_VERSION (t1);
|
|
unsigned i2 = SSA_NAME_VERSION (t2);
|
|
|
|
if (m_source_ssa_names[i1] == -1)
|
|
m_source_ssa_names[i1] = i2;
|
|
else if (m_source_ssa_names[i1] != (int) i2)
|
|
return false;
|
|
|
|
if(m_target_ssa_names[i2] == -1)
|
|
m_target_ssa_names[i2] = i1;
|
|
else if (m_target_ssa_names[i2] != (int) i1)
|
|
return false;
|
|
|
|
if (SSA_NAME_IS_DEFAULT_DEF (t1))
|
|
{
|
|
tree b1 = SSA_NAME_VAR (t1);
|
|
tree b2 = SSA_NAME_VAR (t2);
|
|
|
|
if (b1 == NULL && b2 == NULL)
|
|
return true;
|
|
|
|
if (b1 == NULL || b2 == NULL || TREE_CODE (b1) != TREE_CODE (b2))
|
|
return return_false ();
|
|
|
|
return compare_cst_or_decl (b1, b2);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/* Verification function for edges E1 and E2. */
|
|
|
|
bool
|
|
func_checker::compare_edge (edge e1, edge e2)
|
|
{
|
|
if (e1->flags != e2->flags)
|
|
return false;
|
|
|
|
bool existed_p;
|
|
|
|
edge &slot = m_edge_map.get_or_insert (e1, &existed_p);
|
|
if (existed_p)
|
|
return return_with_debug (slot == e2);
|
|
else
|
|
slot = e2;
|
|
|
|
/* TODO: filter edge probabilities for profile feedback match. */
|
|
|
|
return true;
|
|
}
|
|
|
|
/* Verification function for declaration trees T1 and T2 that
|
|
come from functions FUNC1 and FUNC2. */
|
|
|
|
bool
|
|
func_checker::compare_decl (tree t1, tree t2)
|
|
{
|
|
if (!auto_var_in_fn_p (t1, m_source_func_decl)
|
|
|| !auto_var_in_fn_p (t2, m_target_func_decl))
|
|
return return_with_debug (t1 == t2);
|
|
|
|
tree_code t = TREE_CODE (t1);
|
|
if ((t == VAR_DECL || t == PARM_DECL || t == RESULT_DECL)
|
|
&& DECL_BY_REFERENCE (t1) != DECL_BY_REFERENCE (t2))
|
|
return return_false_with_msg ("DECL_BY_REFERENCE flags are different");
|
|
|
|
if (!compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2)))
|
|
return return_false ();
|
|
|
|
/* TODO: we are actually too strict here. We only need to compare if
|
|
T1 can be used in polymorphic call. */
|
|
if (TREE_ADDRESSABLE (t1)
|
|
&& m_compare_polymorphic
|
|
&& !compatible_polymorphic_types_p (TREE_TYPE (t1), TREE_TYPE (t2),
|
|
false))
|
|
return return_false ();
|
|
|
|
if ((t == VAR_DECL || t == PARM_DECL || t == RESULT_DECL)
|
|
&& DECL_BY_REFERENCE (t1)
|
|
&& m_compare_polymorphic
|
|
&& !compatible_polymorphic_types_p (TREE_TYPE (t1), TREE_TYPE (t2),
|
|
true))
|
|
return return_false ();
|
|
|
|
bool existed_p;
|
|
|
|
tree &slot = m_decl_map.get_or_insert (t1, &existed_p);
|
|
if (existed_p)
|
|
return return_with_debug (slot == t2);
|
|
else
|
|
slot = t2;
|
|
|
|
return true;
|
|
}
|
|
|
|
/* Return true if T1 and T2 are same for purposes of ipa-polymorphic-call
|
|
analysis. COMPARE_PTR indicates if types of pointers needs to be
|
|
considered. */
|
|
|
|
bool
|
|
func_checker::compatible_polymorphic_types_p (tree t1, tree t2,
|
|
bool compare_ptr)
|
|
{
|
|
gcc_assert (TREE_CODE (t1) != FUNCTION_TYPE && TREE_CODE (t1) != METHOD_TYPE);
|
|
|
|
/* Pointer types generally give no information. */
|
|
if (POINTER_TYPE_P (t1))
|
|
{
|
|
if (!compare_ptr)
|
|
return true;
|
|
return func_checker::compatible_polymorphic_types_p (TREE_TYPE (t1),
|
|
TREE_TYPE (t2),
|
|
false);
|
|
}
|
|
|
|
/* If types contain a polymorphic types, match them. */
|
|
bool c1 = contains_polymorphic_type_p (t1);
|
|
bool c2 = contains_polymorphic_type_p (t2);
|
|
if (!c1 && !c2)
|
|
return true;
|
|
if (!c1 || !c2)
|
|
return return_false_with_msg ("one type is not polymorphic");
|
|
if (!types_must_be_same_for_odr (t1, t2))
|
|
return return_false_with_msg ("types are not same for ODR");
|
|
return true;
|
|
}
|
|
|
|
/* Return true if types are compatible from perspective of ICF. */
|
|
bool
|
|
func_checker::compatible_types_p (tree t1, tree t2)
|
|
{
|
|
if (TREE_CODE (t1) != TREE_CODE (t2))
|
|
return return_false_with_msg ("different tree types");
|
|
|
|
if (TYPE_RESTRICT (t1) != TYPE_RESTRICT (t2))
|
|
return return_false_with_msg ("restrict flags are different");
|
|
|
|
if (!types_compatible_p (t1, t2))
|
|
return return_false_with_msg ("types are not compatible");
|
|
|
|
/* We do a lot of unnecesary matching of types that are not being
|
|
accessed and thus do not need to be compatible. In longer term we should
|
|
remove these checks on all types which are not accessed as memory
|
|
locations.
|
|
|
|
For time being just avoid calling get_alias_set on types that are not
|
|
having alias sets defined at all. */
|
|
if (type_with_alias_set_p (t1) && type_with_alias_set_p (t2)
|
|
&& get_alias_set (t1) != get_alias_set (t2))
|
|
return return_false_with_msg ("alias sets are different");
|
|
|
|
return true;
|
|
}
|
|
|
|
/* Function compare for equality given memory operands T1 and T2. */
|
|
|
|
bool
|
|
func_checker::compare_memory_operand (tree t1, tree t2)
|
|
{
|
|
if (!t1 && !t2)
|
|
return true;
|
|
else if (!t1 || !t2)
|
|
return false;
|
|
|
|
ao_ref r1, r2;
|
|
ao_ref_init (&r1, t1);
|
|
ao_ref_init (&r2, t2);
|
|
|
|
tree b1 = ao_ref_base (&r1);
|
|
tree b2 = ao_ref_base (&r2);
|
|
|
|
bool source_is_memop = DECL_P (b1) || INDIRECT_REF_P (b1)
|
|
|| TREE_CODE (b1) == MEM_REF
|
|
|| TREE_CODE (b1) == TARGET_MEM_REF;
|
|
|
|
bool target_is_memop = DECL_P (b2) || INDIRECT_REF_P (b2)
|
|
|| TREE_CODE (b2) == MEM_REF
|
|
|| TREE_CODE (b2) == TARGET_MEM_REF;
|
|
|
|
/* Compare alias sets for memory operands. */
|
|
if (source_is_memop && target_is_memop)
|
|
{
|
|
if (TREE_THIS_VOLATILE (t1) != TREE_THIS_VOLATILE (t2))
|
|
return return_false_with_msg ("different operand volatility");
|
|
|
|
if (ao_ref_alias_set (&r1) != ao_ref_alias_set (&r2)
|
|
|| ao_ref_base_alias_set (&r1) != ao_ref_base_alias_set (&r2))
|
|
return return_false_with_msg ("ao alias sets are different");
|
|
|
|
/* We can't simply use get_object_alignment_1 on the full
|
|
reference as for accesses with variable indexes this reports
|
|
too conservative alignment. We also can't use the ao_ref_base
|
|
base objects as ao_ref_base happily strips MEM_REFs around
|
|
decls even though that may carry alignment info. */
|
|
b1 = t1;
|
|
while (handled_component_p (b1))
|
|
b1 = TREE_OPERAND (b1, 0);
|
|
b2 = t2;
|
|
while (handled_component_p (b2))
|
|
b2 = TREE_OPERAND (b2, 0);
|
|
unsigned int align1, align2;
|
|
unsigned HOST_WIDE_INT tem;
|
|
get_object_alignment_1 (b1, &align1, &tem);
|
|
get_object_alignment_1 (b2, &align2, &tem);
|
|
if (align1 != align2)
|
|
return return_false_with_msg ("different access alignment");
|
|
|
|
/* Similarly we have to compare dependence info where equality
|
|
tells us we are safe (even some unequal values would be safe
|
|
but then we have to maintain a map of bases and cliques). */
|
|
unsigned short clique1 = 0, base1 = 0, clique2 = 0, base2 = 0;
|
|
if (TREE_CODE (b1) == MEM_REF)
|
|
{
|
|
clique1 = MR_DEPENDENCE_CLIQUE (b1);
|
|
base1 = MR_DEPENDENCE_BASE (b1);
|
|
}
|
|
if (TREE_CODE (b2) == MEM_REF)
|
|
{
|
|
clique2 = MR_DEPENDENCE_CLIQUE (b2);
|
|
base2 = MR_DEPENDENCE_BASE (b2);
|
|
}
|
|
if (clique1 != clique2 || base1 != base2)
|
|
return return_false_with_msg ("different dependence info");
|
|
}
|
|
|
|
return compare_operand (t1, t2);
|
|
}
|
|
|
|
/* Function compare for equality given trees T1 and T2 which
|
|
can be either a constant or a declaration type. */
|
|
|
|
bool
|
|
func_checker::compare_cst_or_decl (tree t1, tree t2)
|
|
{
|
|
bool ret;
|
|
|
|
switch (TREE_CODE (t1))
|
|
{
|
|
case INTEGER_CST:
|
|
case COMPLEX_CST:
|
|
case VECTOR_CST:
|
|
case STRING_CST:
|
|
case REAL_CST:
|
|
{
|
|
ret = compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2))
|
|
&& operand_equal_p (t1, t2, OEP_ONLY_CONST);
|
|
return return_with_debug (ret);
|
|
}
|
|
case FUNCTION_DECL:
|
|
/* All function decls are in the symbol table and known to match
|
|
before we start comparing bodies. */
|
|
return true;
|
|
case VAR_DECL:
|
|
return return_with_debug (compare_variable_decl (t1, t2));
|
|
case FIELD_DECL:
|
|
{
|
|
tree offset1 = DECL_FIELD_OFFSET (t1);
|
|
tree offset2 = DECL_FIELD_OFFSET (t2);
|
|
|
|
tree bit_offset1 = DECL_FIELD_BIT_OFFSET (t1);
|
|
tree bit_offset2 = DECL_FIELD_BIT_OFFSET (t2);
|
|
|
|
ret = compare_operand (offset1, offset2)
|
|
&& compare_operand (bit_offset1, bit_offset2);
|
|
|
|
return return_with_debug (ret);
|
|
}
|
|
case LABEL_DECL:
|
|
{
|
|
if (t1 == t2)
|
|
return true;
|
|
|
|
int *bb1 = m_label_bb_map.get (t1);
|
|
int *bb2 = m_label_bb_map.get (t2);
|
|
|
|
/* Labels can point to another function (non-local GOTOs). */
|
|
return return_with_debug (bb1 != NULL && bb2 != NULL && *bb1 == *bb2);
|
|
}
|
|
case PARM_DECL:
|
|
case RESULT_DECL:
|
|
case CONST_DECL:
|
|
{
|
|
ret = compare_decl (t1, t2);
|
|
return return_with_debug (ret);
|
|
}
|
|
default:
|
|
gcc_unreachable ();
|
|
}
|
|
}
|
|
|
|
/* Function responsible for comparison of various operands T1 and T2.
|
|
If these components, from functions FUNC1 and FUNC2, are equal, true
|
|
is returned. */
|
|
|
|
bool
|
|
func_checker::compare_operand (tree t1, tree t2)
|
|
{
|
|
tree x1, x2, y1, y2, z1, z2;
|
|
bool ret;
|
|
|
|
if (!t1 && !t2)
|
|
return true;
|
|
else if (!t1 || !t2)
|
|
return false;
|
|
|
|
tree tt1 = TREE_TYPE (t1);
|
|
tree tt2 = TREE_TYPE (t2);
|
|
|
|
if (!func_checker::compatible_types_p (tt1, tt2))
|
|
return false;
|
|
|
|
if (TREE_CODE (t1) != TREE_CODE (t2))
|
|
return return_false ();
|
|
|
|
switch (TREE_CODE (t1))
|
|
{
|
|
case CONSTRUCTOR:
|
|
{
|
|
unsigned length1 = CONSTRUCTOR_NELTS (t1);
|
|
unsigned length2 = CONSTRUCTOR_NELTS (t2);
|
|
|
|
if (length1 != length2)
|
|
return return_false ();
|
|
|
|
for (unsigned i = 0; i < length1; i++)
|
|
if (!compare_operand (CONSTRUCTOR_ELT (t1, i)->value,
|
|
CONSTRUCTOR_ELT (t2, i)->value))
|
|
return return_false();
|
|
|
|
return true;
|
|
}
|
|
case ARRAY_REF:
|
|
case ARRAY_RANGE_REF:
|
|
/* First argument is the array, second is the index. */
|
|
x1 = TREE_OPERAND (t1, 0);
|
|
x2 = TREE_OPERAND (t2, 0);
|
|
y1 = TREE_OPERAND (t1, 1);
|
|
y2 = TREE_OPERAND (t2, 1);
|
|
|
|
if (!compare_operand (array_ref_low_bound (t1),
|
|
array_ref_low_bound (t2)))
|
|
return return_false_with_msg ("");
|
|
if (!compare_operand (array_ref_element_size (t1),
|
|
array_ref_element_size (t2)))
|
|
return return_false_with_msg ("");
|
|
|
|
if (!compare_operand (x1, x2))
|
|
return return_false_with_msg ("");
|
|
return compare_operand (y1, y2);
|
|
case MEM_REF:
|
|
{
|
|
x1 = TREE_OPERAND (t1, 0);
|
|
x2 = TREE_OPERAND (t2, 0);
|
|
y1 = TREE_OPERAND (t1, 1);
|
|
y2 = TREE_OPERAND (t2, 1);
|
|
|
|
/* See if operand is an memory access (the test originate from
|
|
gimple_load_p).
|
|
|
|
In this case the alias set of the function being replaced must
|
|
be subset of the alias set of the other function. At the moment
|
|
we seek for equivalency classes, so simply require inclussion in
|
|
both directions. */
|
|
|
|
if (!func_checker::compatible_types_p (TREE_TYPE (x1), TREE_TYPE (x2)))
|
|
return return_false ();
|
|
|
|
if (!compare_operand (x1, x2))
|
|
return return_false_with_msg ("");
|
|
|
|
/* Type of the offset on MEM_REF does not matter. */
|
|
return known_eq (wi::to_poly_offset (y1), wi::to_poly_offset (y2));
|
|
}
|
|
case COMPONENT_REF:
|
|
{
|
|
x1 = TREE_OPERAND (t1, 0);
|
|
x2 = TREE_OPERAND (t2, 0);
|
|
y1 = TREE_OPERAND (t1, 1);
|
|
y2 = TREE_OPERAND (t2, 1);
|
|
|
|
ret = compare_operand (x1, x2)
|
|
&& compare_cst_or_decl (y1, y2);
|
|
|
|
return return_with_debug (ret);
|
|
}
|
|
/* Virtual table call. */
|
|
case OBJ_TYPE_REF:
|
|
{
|
|
if (!compare_ssa_name (OBJ_TYPE_REF_EXPR (t1), OBJ_TYPE_REF_EXPR (t2)))
|
|
return return_false ();
|
|
if (opt_for_fn (m_source_func_decl, flag_devirtualize)
|
|
&& virtual_method_call_p (t1))
|
|
{
|
|
if (tree_to_uhwi (OBJ_TYPE_REF_TOKEN (t1))
|
|
!= tree_to_uhwi (OBJ_TYPE_REF_TOKEN (t2)))
|
|
return return_false_with_msg ("OBJ_TYPE_REF token mismatch");
|
|
if (!types_same_for_odr (obj_type_ref_class (t1),
|
|
obj_type_ref_class (t2)))
|
|
return return_false_with_msg ("OBJ_TYPE_REF OTR type mismatch");
|
|
if (!compare_operand (OBJ_TYPE_REF_OBJECT (t1),
|
|
OBJ_TYPE_REF_OBJECT (t2)))
|
|
return return_false_with_msg ("OBJ_TYPE_REF object mismatch");
|
|
}
|
|
|
|
return return_with_debug (true);
|
|
}
|
|
case IMAGPART_EXPR:
|
|
case REALPART_EXPR:
|
|
case ADDR_EXPR:
|
|
{
|
|
x1 = TREE_OPERAND (t1, 0);
|
|
x2 = TREE_OPERAND (t2, 0);
|
|
|
|
ret = compare_operand (x1, x2);
|
|
return return_with_debug (ret);
|
|
}
|
|
case BIT_FIELD_REF:
|
|
{
|
|
x1 = TREE_OPERAND (t1, 0);
|
|
x2 = TREE_OPERAND (t2, 0);
|
|
y1 = TREE_OPERAND (t1, 1);
|
|
y2 = TREE_OPERAND (t2, 1);
|
|
z1 = TREE_OPERAND (t1, 2);
|
|
z2 = TREE_OPERAND (t2, 2);
|
|
|
|
ret = compare_operand (x1, x2)
|
|
&& compare_cst_or_decl (y1, y2)
|
|
&& compare_cst_or_decl (z1, z2);
|
|
|
|
return return_with_debug (ret);
|
|
}
|
|
case SSA_NAME:
|
|
return compare_ssa_name (t1, t2);
|
|
case INTEGER_CST:
|
|
case COMPLEX_CST:
|
|
case VECTOR_CST:
|
|
case STRING_CST:
|
|
case REAL_CST:
|
|
case FUNCTION_DECL:
|
|
case VAR_DECL:
|
|
case FIELD_DECL:
|
|
case LABEL_DECL:
|
|
case PARM_DECL:
|
|
case RESULT_DECL:
|
|
case CONST_DECL:
|
|
return compare_cst_or_decl (t1, t2);
|
|
default:
|
|
return return_false_with_msg ("Unknown TREE code reached");
|
|
}
|
|
}
|
|
|
|
bool
|
|
func_checker::compare_asm_inputs_outputs (tree t1, tree t2)
|
|
{
|
|
gcc_assert (TREE_CODE (t1) == TREE_LIST);
|
|
gcc_assert (TREE_CODE (t2) == TREE_LIST);
|
|
|
|
for (; t1; t1 = TREE_CHAIN (t1))
|
|
{
|
|
if (!t2)
|
|
return false;
|
|
|
|
if (!compare_operand (TREE_VALUE (t1), TREE_VALUE (t2)))
|
|
return return_false ();
|
|
|
|
tree p1 = TREE_PURPOSE (t1);
|
|
tree p2 = TREE_PURPOSE (t2);
|
|
|
|
gcc_assert (TREE_CODE (p1) == TREE_LIST);
|
|
gcc_assert (TREE_CODE (p2) == TREE_LIST);
|
|
|
|
if (strcmp (TREE_STRING_POINTER (TREE_VALUE (p1)),
|
|
TREE_STRING_POINTER (TREE_VALUE (p2))) != 0)
|
|
return return_false ();
|
|
|
|
t2 = TREE_CHAIN (t2);
|
|
}
|
|
|
|
if (t2)
|
|
return return_false ();
|
|
|
|
return true;
|
|
}
|
|
|
|
/* Verifies that trees T1 and T2 do correspond. */
|
|
|
|
bool
|
|
func_checker::compare_variable_decl (tree t1, tree t2)
|
|
{
|
|
bool ret = false;
|
|
|
|
if (t1 == t2)
|
|
return true;
|
|
|
|
if (DECL_ALIGN (t1) != DECL_ALIGN (t2))
|
|
return return_false_with_msg ("alignments are different");
|
|
|
|
if (DECL_HARD_REGISTER (t1) != DECL_HARD_REGISTER (t2))
|
|
return return_false_with_msg ("DECL_HARD_REGISTER are different");
|
|
|
|
if (DECL_HARD_REGISTER (t1)
|
|
&& DECL_ASSEMBLER_NAME (t1) != DECL_ASSEMBLER_NAME (t2))
|
|
return return_false_with_msg ("HARD REGISTERS are different");
|
|
|
|
/* Symbol table variables are known to match before we start comparing
|
|
bodies. */
|
|
if (decl_in_symtab_p (t1))
|
|
return decl_in_symtab_p (t2);
|
|
ret = compare_decl (t1, t2);
|
|
|
|
return return_with_debug (ret);
|
|
}
|
|
|
|
|
|
/* Function visits all gimple labels and creates corresponding
|
|
mapping between basic blocks and labels. */
|
|
|
|
void
|
|
func_checker::parse_labels (sem_bb *bb)
|
|
{
|
|
for (gimple_stmt_iterator gsi = gsi_start_bb (bb->bb); !gsi_end_p (gsi);
|
|
gsi_next (&gsi))
|
|
{
|
|
gimple *stmt = gsi_stmt (gsi);
|
|
|
|
if (glabel *label_stmt = dyn_cast <glabel *> (stmt))
|
|
{
|
|
tree t = gimple_label_label (label_stmt);
|
|
gcc_assert (TREE_CODE (t) == LABEL_DECL);
|
|
|
|
m_label_bb_map.put (t, bb->bb->index);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Basic block equivalence comparison function that returns true if
|
|
basic blocks BB1 and BB2 (from functions FUNC1 and FUNC2) correspond.
|
|
|
|
In general, a collection of equivalence dictionaries is built for types
|
|
like SSA names, declarations (VAR_DECL, PARM_DECL, ..). This infrastructure
|
|
is utilized by every statement-by-statement comparison function. */
|
|
|
|
bool
|
|
func_checker::compare_bb (sem_bb *bb1, sem_bb *bb2)
|
|
{
|
|
gimple_stmt_iterator gsi1, gsi2;
|
|
gimple *s1, *s2;
|
|
|
|
gsi1 = gsi_start_nondebug_bb (bb1->bb);
|
|
gsi2 = gsi_start_nondebug_bb (bb2->bb);
|
|
|
|
while (!gsi_end_p (gsi1))
|
|
{
|
|
if (gsi_end_p (gsi2))
|
|
return return_false ();
|
|
|
|
s1 = gsi_stmt (gsi1);
|
|
s2 = gsi_stmt (gsi2);
|
|
|
|
int eh1 = lookup_stmt_eh_lp_fn
|
|
(DECL_STRUCT_FUNCTION (m_source_func_decl), s1);
|
|
int eh2 = lookup_stmt_eh_lp_fn
|
|
(DECL_STRUCT_FUNCTION (m_target_func_decl), s2);
|
|
|
|
if (eh1 != eh2)
|
|
return return_false_with_msg ("EH regions are different");
|
|
|
|
if (gimple_code (s1) != gimple_code (s2))
|
|
return return_false_with_msg ("gimple codes are different");
|
|
|
|
switch (gimple_code (s1))
|
|
{
|
|
case GIMPLE_CALL:
|
|
if (!compare_gimple_call (as_a <gcall *> (s1),
|
|
as_a <gcall *> (s2)))
|
|
return return_different_stmts (s1, s2, "GIMPLE_CALL");
|
|
break;
|
|
case GIMPLE_ASSIGN:
|
|
if (!compare_gimple_assign (s1, s2))
|
|
return return_different_stmts (s1, s2, "GIMPLE_ASSIGN");
|
|
break;
|
|
case GIMPLE_COND:
|
|
if (!compare_gimple_cond (s1, s2))
|
|
return return_different_stmts (s1, s2, "GIMPLE_COND");
|
|
break;
|
|
case GIMPLE_SWITCH:
|
|
if (!compare_gimple_switch (as_a <gswitch *> (s1),
|
|
as_a <gswitch *> (s2)))
|
|
return return_different_stmts (s1, s2, "GIMPLE_SWITCH");
|
|
break;
|
|
case GIMPLE_DEBUG:
|
|
break;
|
|
case GIMPLE_EH_DISPATCH:
|
|
if (gimple_eh_dispatch_region (as_a <geh_dispatch *> (s1))
|
|
!= gimple_eh_dispatch_region (as_a <geh_dispatch *> (s2)))
|
|
return return_different_stmts (s1, s2, "GIMPLE_EH_DISPATCH");
|
|
break;
|
|
case GIMPLE_RESX:
|
|
if (!compare_gimple_resx (as_a <gresx *> (s1),
|
|
as_a <gresx *> (s2)))
|
|
return return_different_stmts (s1, s2, "GIMPLE_RESX");
|
|
break;
|
|
case GIMPLE_LABEL:
|
|
if (!compare_gimple_label (as_a <glabel *> (s1),
|
|
as_a <glabel *> (s2)))
|
|
return return_different_stmts (s1, s2, "GIMPLE_LABEL");
|
|
break;
|
|
case GIMPLE_RETURN:
|
|
if (!compare_gimple_return (as_a <greturn *> (s1),
|
|
as_a <greturn *> (s2)))
|
|
return return_different_stmts (s1, s2, "GIMPLE_RETURN");
|
|
break;
|
|
case GIMPLE_GOTO:
|
|
if (!compare_gimple_goto (s1, s2))
|
|
return return_different_stmts (s1, s2, "GIMPLE_GOTO");
|
|
break;
|
|
case GIMPLE_ASM:
|
|
if (!compare_gimple_asm (as_a <gasm *> (s1),
|
|
as_a <gasm *> (s2)))
|
|
return return_different_stmts (s1, s2, "GIMPLE_ASM");
|
|
break;
|
|
case GIMPLE_PREDICT:
|
|
case GIMPLE_NOP:
|
|
break;
|
|
default:
|
|
return return_false_with_msg ("Unknown GIMPLE code reached");
|
|
}
|
|
|
|
gsi_next_nondebug (&gsi1);
|
|
gsi_next_nondebug (&gsi2);
|
|
}
|
|
|
|
if (!gsi_end_p (gsi2))
|
|
return return_false ();
|
|
|
|
return true;
|
|
}
|
|
|
|
/* Verifies for given GIMPLEs S1 and S2 that
|
|
call statements are semantically equivalent. */
|
|
|
|
bool
|
|
func_checker::compare_gimple_call (gcall *s1, gcall *s2)
|
|
{
|
|
unsigned i;
|
|
tree t1, t2;
|
|
|
|
if (gimple_call_num_args (s1) != gimple_call_num_args (s2))
|
|
return false;
|
|
|
|
t1 = gimple_call_fn (s1);
|
|
t2 = gimple_call_fn (s2);
|
|
if (!compare_operand (t1, t2))
|
|
return return_false ();
|
|
|
|
/* Compare flags. */
|
|
if (gimple_call_internal_p (s1) != gimple_call_internal_p (s2)
|
|
|| gimple_call_ctrl_altering_p (s1) != gimple_call_ctrl_altering_p (s2)
|
|
|| gimple_call_tail_p (s1) != gimple_call_tail_p (s2)
|
|
|| gimple_call_return_slot_opt_p (s1) != gimple_call_return_slot_opt_p (s2)
|
|
|| gimple_call_from_thunk_p (s1) != gimple_call_from_thunk_p (s2)
|
|
|| gimple_call_va_arg_pack_p (s1) != gimple_call_va_arg_pack_p (s2)
|
|
|| gimple_call_alloca_for_var_p (s1) != gimple_call_alloca_for_var_p (s2))
|
|
return false;
|
|
|
|
if (gimple_call_internal_p (s1)
|
|
&& gimple_call_internal_fn (s1) != gimple_call_internal_fn (s2))
|
|
return false;
|
|
|
|
tree fntype1 = gimple_call_fntype (s1);
|
|
tree fntype2 = gimple_call_fntype (s2);
|
|
if ((fntype1 && !fntype2)
|
|
|| (!fntype1 && fntype2)
|
|
|| (fntype1 && !types_compatible_p (fntype1, fntype2)))
|
|
return return_false_with_msg ("call function types are not compatible");
|
|
|
|
tree chain1 = gimple_call_chain (s1);
|
|
tree chain2 = gimple_call_chain (s2);
|
|
if ((chain1 && !chain2)
|
|
|| (!chain1 && chain2)
|
|
|| !compare_operand (chain1, chain2))
|
|
return return_false_with_msg ("static call chains are different");
|
|
|
|
/* Checking of argument. */
|
|
for (i = 0; i < gimple_call_num_args (s1); ++i)
|
|
{
|
|
t1 = gimple_call_arg (s1, i);
|
|
t2 = gimple_call_arg (s2, i);
|
|
|
|
if (!compare_memory_operand (t1, t2))
|
|
return return_false_with_msg ("memory operands are different");
|
|
}
|
|
|
|
/* Return value checking. */
|
|
t1 = gimple_get_lhs (s1);
|
|
t2 = gimple_get_lhs (s2);
|
|
|
|
return compare_memory_operand (t1, t2);
|
|
}
|
|
|
|
|
|
/* Verifies for given GIMPLEs S1 and S2 that
|
|
assignment statements are semantically equivalent. */
|
|
|
|
bool
|
|
func_checker::compare_gimple_assign (gimple *s1, gimple *s2)
|
|
{
|
|
tree arg1, arg2;
|
|
tree_code code1, code2;
|
|
unsigned i;
|
|
|
|
code1 = gimple_expr_code (s1);
|
|
code2 = gimple_expr_code (s2);
|
|
|
|
if (code1 != code2)
|
|
return false;
|
|
|
|
code1 = gimple_assign_rhs_code (s1);
|
|
code2 = gimple_assign_rhs_code (s2);
|
|
|
|
if (code1 != code2)
|
|
return false;
|
|
|
|
for (i = 0; i < gimple_num_ops (s1); i++)
|
|
{
|
|
arg1 = gimple_op (s1, i);
|
|
arg2 = gimple_op (s2, i);
|
|
|
|
if (!compare_memory_operand (arg1, arg2))
|
|
return return_false_with_msg ("memory operands are different");
|
|
}
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
/* Verifies for given GIMPLEs S1 and S2 that
|
|
condition statements are semantically equivalent. */
|
|
|
|
bool
|
|
func_checker::compare_gimple_cond (gimple *s1, gimple *s2)
|
|
{
|
|
tree t1, t2;
|
|
tree_code code1, code2;
|
|
|
|
code1 = gimple_expr_code (s1);
|
|
code2 = gimple_expr_code (s2);
|
|
|
|
if (code1 != code2)
|
|
return false;
|
|
|
|
t1 = gimple_cond_lhs (s1);
|
|
t2 = gimple_cond_lhs (s2);
|
|
|
|
if (!compare_operand (t1, t2))
|
|
return false;
|
|
|
|
t1 = gimple_cond_rhs (s1);
|
|
t2 = gimple_cond_rhs (s2);
|
|
|
|
return compare_operand (t1, t2);
|
|
}
|
|
|
|
/* Verifies that tree labels T1 and T2 correspond in FUNC1 and FUNC2. */
|
|
|
|
bool
|
|
func_checker::compare_tree_ssa_label (tree t1, tree t2)
|
|
{
|
|
return compare_operand (t1, t2);
|
|
}
|
|
|
|
/* Verifies for given GIMPLE_LABEL stmts S1 and S2 that
|
|
label statements are semantically equivalent. */
|
|
|
|
bool
|
|
func_checker::compare_gimple_label (const glabel *g1, const glabel *g2)
|
|
{
|
|
if (m_ignore_labels)
|
|
return true;
|
|
|
|
tree t1 = gimple_label_label (g1);
|
|
tree t2 = gimple_label_label (g2);
|
|
|
|
if (FORCED_LABEL (t1) || FORCED_LABEL (t2))
|
|
return return_false_with_msg ("FORCED_LABEL");
|
|
|
|
/* As the pass build BB to label mapping, no further check is needed. */
|
|
return true;
|
|
}
|
|
|
|
/* Verifies for given GIMPLE_SWITCH stmts S1 and S2 that
|
|
switch statements are semantically equivalent. */
|
|
|
|
bool
|
|
func_checker::compare_gimple_switch (const gswitch *g1, const gswitch *g2)
|
|
{
|
|
unsigned lsize1, lsize2, i;
|
|
|
|
lsize1 = gimple_switch_num_labels (g1);
|
|
lsize2 = gimple_switch_num_labels (g2);
|
|
|
|
if (lsize1 != lsize2)
|
|
return false;
|
|
|
|
tree t1 = gimple_switch_index (g1);
|
|
tree t2 = gimple_switch_index (g2);
|
|
|
|
if (!compare_operand (t1, t2))
|
|
return false;
|
|
|
|
for (i = 0; i < lsize1; i++)
|
|
{
|
|
tree label1 = gimple_switch_label (g1, i);
|
|
tree label2 = gimple_switch_label (g2, i);
|
|
|
|
/* Label LOW and HIGH comparison. */
|
|
tree low1 = CASE_LOW (label1);
|
|
tree low2 = CASE_LOW (label2);
|
|
|
|
if (!tree_int_cst_equal (low1, low2))
|
|
return return_false_with_msg ("case low values are different");
|
|
|
|
tree high1 = CASE_HIGH (label1);
|
|
tree high2 = CASE_HIGH (label2);
|
|
|
|
if (!tree_int_cst_equal (high1, high2))
|
|
return return_false_with_msg ("case high values are different");
|
|
|
|
if (TREE_CODE (label1) == CASE_LABEL_EXPR
|
|
&& TREE_CODE (label2) == CASE_LABEL_EXPR)
|
|
{
|
|
label1 = CASE_LABEL (label1);
|
|
label2 = CASE_LABEL (label2);
|
|
|
|
if (!compare_operand (label1, label2))
|
|
return return_false_with_msg ("switch label_exprs are different");
|
|
}
|
|
else if (!tree_int_cst_equal (label1, label2))
|
|
return return_false_with_msg ("switch labels are different");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/* Verifies for given GIMPLE_RETURN stmts S1 and S2 that
|
|
return statements are semantically equivalent. */
|
|
|
|
bool
|
|
func_checker::compare_gimple_return (const greturn *g1, const greturn *g2)
|
|
{
|
|
tree t1, t2;
|
|
|
|
t1 = gimple_return_retval (g1);
|
|
t2 = gimple_return_retval (g2);
|
|
|
|
/* Void return type. */
|
|
if (t1 == NULL && t2 == NULL)
|
|
return true;
|
|
else
|
|
return compare_operand (t1, t2);
|
|
}
|
|
|
|
/* Verifies for given GIMPLEs S1 and S2 that
|
|
goto statements are semantically equivalent. */
|
|
|
|
bool
|
|
func_checker::compare_gimple_goto (gimple *g1, gimple *g2)
|
|
{
|
|
tree dest1, dest2;
|
|
|
|
dest1 = gimple_goto_dest (g1);
|
|
dest2 = gimple_goto_dest (g2);
|
|
|
|
if (TREE_CODE (dest1) != TREE_CODE (dest2) || TREE_CODE (dest1) != SSA_NAME)
|
|
return false;
|
|
|
|
return compare_operand (dest1, dest2);
|
|
}
|
|
|
|
/* Verifies for given GIMPLE_RESX stmts S1 and S2 that
|
|
resx statements are semantically equivalent. */
|
|
|
|
bool
|
|
func_checker::compare_gimple_resx (const gresx *g1, const gresx *g2)
|
|
{
|
|
return gimple_resx_region (g1) == gimple_resx_region (g2);
|
|
}
|
|
|
|
/* Verifies for given GIMPLEs S1 and S2 that ASM statements are equivalent.
|
|
For the beginning, the pass only supports equality for
|
|
'__asm__ __volatile__ ("", "", "", "memory")'. */
|
|
|
|
bool
|
|
func_checker::compare_gimple_asm (const gasm *g1, const gasm *g2)
|
|
{
|
|
if (gimple_asm_volatile_p (g1) != gimple_asm_volatile_p (g2))
|
|
return false;
|
|
|
|
if (gimple_asm_input_p (g1) != gimple_asm_input_p (g2))
|
|
return false;
|
|
|
|
if (gimple_asm_ninputs (g1) != gimple_asm_ninputs (g2))
|
|
return false;
|
|
|
|
if (gimple_asm_noutputs (g1) != gimple_asm_noutputs (g2))
|
|
return false;
|
|
|
|
/* We do not suppport goto ASM statement comparison. */
|
|
if (gimple_asm_nlabels (g1) || gimple_asm_nlabels (g2))
|
|
return false;
|
|
|
|
if (gimple_asm_nclobbers (g1) != gimple_asm_nclobbers (g2))
|
|
return false;
|
|
|
|
if (strcmp (gimple_asm_string (g1), gimple_asm_string (g2)) != 0)
|
|
return return_false_with_msg ("ASM strings are different");
|
|
|
|
for (unsigned i = 0; i < gimple_asm_ninputs (g1); i++)
|
|
{
|
|
tree input1 = gimple_asm_input_op (g1, i);
|
|
tree input2 = gimple_asm_input_op (g2, i);
|
|
|
|
if (!compare_asm_inputs_outputs (input1, input2))
|
|
return return_false_with_msg ("ASM input is different");
|
|
}
|
|
|
|
for (unsigned i = 0; i < gimple_asm_noutputs (g1); i++)
|
|
{
|
|
tree output1 = gimple_asm_output_op (g1, i);
|
|
tree output2 = gimple_asm_output_op (g2, i);
|
|
|
|
if (!compare_asm_inputs_outputs (output1, output2))
|
|
return return_false_with_msg ("ASM output is different");
|
|
}
|
|
|
|
for (unsigned i = 0; i < gimple_asm_nclobbers (g1); i++)
|
|
{
|
|
tree clobber1 = gimple_asm_clobber_op (g1, i);
|
|
tree clobber2 = gimple_asm_clobber_op (g2, i);
|
|
|
|
if (!operand_equal_p (TREE_VALUE (clobber1), TREE_VALUE (clobber2),
|
|
OEP_ONLY_CONST))
|
|
return return_false_with_msg ("ASM clobber is different");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
} // ipa_icf_gimple namespace
|