Mercurial > hg > CbC > CbC_gcc
diff gcc/final.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
line wrap: on
line diff
--- a/gcc/final.c Thu Oct 25 07:37:49 2018 +0900 +++ b/gcc/final.c Thu Feb 13 11:34:05 2020 +0900 @@ -1,5 +1,5 @@ /* Convert RTL to assembler code and output it, for GNU compiler. - Copyright (C) 1987-2018 Free Software Foundation, Inc. + Copyright (C) 1987-2020 Free Software Foundation, Inc. This file is part of GCC. @@ -75,12 +75,12 @@ #include "tree-pass.h" #include "tree-ssa.h" #include "cfgloop.h" -#include "params.h" #include "stringpool.h" #include "attribs.h" #include "asan.h" #include "rtl-iter.h" #include "print-rtl.h" +#include "function-abi.h" #ifdef XCOFF_DEBUGGING_INFO #include "xcoffout.h" /* Needed for external data declarations. */ @@ -128,6 +128,7 @@ /* Discriminator to be written to assembly for current instruction. Note: actual usage depends on loc_discriminator_kind setting. */ static int discriminator; +static inline int compute_discriminator (location_t loc); /* Discriminator identifying current basic block among others sharing the same locus. */ @@ -149,6 +150,7 @@ static const char *override_filename; static int override_linenum; static int override_columnnum; +static int override_discriminator; /* Whether to force emission of a line note before the next insn. */ static bool force_source_line = false; @@ -228,7 +230,6 @@ #endif static int align_fuzz (rtx, rtx, int, unsigned); static void collect_fn_hard_reg_usage (void); -static tree get_call_fndecl (rtx_insn *); /* Initialize data in final at the beginning of a compilation. */ @@ -604,7 +605,7 @@ rtx_insn *seq = NEXT_INSN (PREV_INSN (branch)); seq_uid = INSN_UID (seq); - if (!JUMP_P (branch)) + if (!jump_to_label_p (branch)) /* This can happen for example on the PA; the objective is to know the offset to address something in front of the start of the function. Thus, we can treat it like a backward branch. @@ -655,7 +656,7 @@ } loop_optimizer_init (AVOID_CFG_MODIFICATIONS); profile_count count_threshold = cfun->cfg->count_max.apply_scale - (1, PARAM_VALUE (PARAM_ALIGN_THRESHOLD)); + (1, param_align_threshold); if (dump_file) { @@ -741,7 +742,7 @@ && branch_count + fallthru_count > count_threshold && (branch_count > fallthru_count.apply_scale - (PARAM_VALUE (PARAM_ALIGN_LOOP_ITERATIONS), 1))) + (param_align_loop_iterations, 1))) { align_flags alignment = LOOP_ALIGN (label); if (dump_file) @@ -2342,6 +2343,7 @@ override_filename = LOCATION_FILE (*locus_ptr); override_linenum = LOCATION_LINE (*locus_ptr); override_columnnum = LOCATION_COLUMN (*locus_ptr); + override_discriminator = compute_discriminator (*locus_ptr); } } break; @@ -2379,12 +2381,14 @@ override_filename = LOCATION_FILE (*locus_ptr); override_linenum = LOCATION_LINE (*locus_ptr); override_columnnum = LOCATION_COLUMN (*locus_ptr); + override_discriminator = compute_discriminator (*locus_ptr); } else { override_filename = NULL; override_linenum = 0; override_columnnum = 0; + override_discriminator = 0; } } break; @@ -2425,10 +2429,9 @@ case NOTE_INSN_INLINE_ENTRY: gcc_checking_assert (cfun->debug_nonbind_markers); - if (!DECL_IGNORED_P (current_function_decl)) + if (!DECL_IGNORED_P (current_function_decl) + && notice_source_line (insn, NULL)) { - if (!notice_source_line (insn, NULL)) - break; (*debug_hooks->inline_entry) (LOCATION_BLOCK (NOTE_MARKER_LOCATION (insn))); goto output_source_line; @@ -3185,9 +3188,11 @@ /* Set DISCRIMINATOR to the appropriate value, possibly derived from LOC. */ -static inline void -maybe_set_discriminator (location_t loc) +static inline int +compute_discriminator (location_t loc) { + int discriminator; + if (!decl_to_instance_map) discriminator = bb_discriminator; else @@ -3209,6 +3214,8 @@ discriminator = map_decl_to_instance (decl); } + + return discriminator; } /* Return whether a source line note needs to be emitted before INSN. @@ -3234,7 +3241,7 @@ filename = xloc.file; linenum = xloc.line; columnnum = xloc.column; - maybe_set_discriminator (loc); + discriminator = compute_discriminator (loc); force_source_line = true; } else if (override_filename) @@ -3242,6 +3249,7 @@ filename = override_filename; linenum = override_linenum; columnnum = override_columnnum; + discriminator = override_discriminator; } else if (INSN_HAS_LOCATION (insn)) { @@ -3249,13 +3257,14 @@ filename = xloc.file; linenum = xloc.line; columnnum = xloc.column; - maybe_set_discriminator (INSN_LOCATION (insn)); + discriminator = compute_discriminator (INSN_LOCATION (insn)); } else { filename = NULL; linenum = 0; columnnum = 0; + discriminator = 0; } if (filename == NULL) @@ -4648,7 +4657,11 @@ final_start_function_1 (&first, asm_out_file, &seen, optimize); final_1 (first, asm_out_file, seen, optimize); if (flag_ipa_ra - && !lookup_attribute ("noipa", DECL_ATTRIBUTES (current_function_decl))) + && !lookup_attribute ("noipa", DECL_ATTRIBUTES (current_function_decl)) + /* Functions with naked attributes are supported only with basic asm + statements in the body, thus for supported use cases the information + on clobbered registers is not available. */ + && !lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl))) collect_fn_hard_reg_usage (); final_end_function (); @@ -4890,7 +4903,8 @@ /* We can reduce stack alignment on call site only when we are sure that the function body just produced will be actually used in the final executable. */ - if (decl_binds_to_current_def_p (current_function_decl)) + if (flag_ipa_stack_alignment + && decl_binds_to_current_def_p (current_function_decl)) { unsigned int pref = crtl->preferred_stack_boundary; if (crtl->stack_alignment_needed > crtl->preferred_stack_boundary) @@ -4979,7 +4993,16 @@ if (!targetm.call_fusage_contains_non_callee_clobbers) return; - CLEAR_HARD_REG_SET (function_used_regs); + /* Be conservative - mark fixed and global registers as used. */ + function_used_regs = fixed_reg_set; + +#ifdef STACK_REGS + /* Handle STACK_REGS conservatively, since the df-framework does not + provide accurate information for them. */ + + for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++) + SET_HARD_REG_BIT (function_used_regs, i); +#endif for (insn = get_insns (); insn != NULL_RTX; insn = next_insn (insn)) { @@ -4990,97 +5013,23 @@ if (CALL_P (insn) && !self_recursive_call_p (insn)) - { - if (!get_call_reg_set_usage (insn, &insn_used_regs, - call_used_reg_set)) - return; - - IOR_HARD_REG_SET (function_used_regs, insn_used_regs); - } + function_used_regs + |= insn_callee_abi (insn).full_and_partial_reg_clobbers (); find_all_hard_reg_sets (insn, &insn_used_regs, false); - IOR_HARD_REG_SET (function_used_regs, insn_used_regs); + function_used_regs |= insn_used_regs; + + if (hard_reg_set_subset_p (crtl->abi->full_and_partial_reg_clobbers (), + function_used_regs)) + return; } - /* Be conservative - mark fixed and global registers as used. */ - IOR_HARD_REG_SET (function_used_regs, fixed_reg_set); - -#ifdef STACK_REGS - /* Handle STACK_REGS conservatively, since the df-framework does not - provide accurate information for them. */ - - for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++) - SET_HARD_REG_BIT (function_used_regs, i); -#endif - - /* The information we have gathered is only interesting if it exposes a - register from the call_used_regs that is not used in this function. */ - if (hard_reg_set_subset_p (call_used_reg_set, function_used_regs)) - return; + /* Mask out fully-saved registers, so that they don't affect equality + comparisons between function_abis. */ + function_used_regs &= crtl->abi->full_and_partial_reg_clobbers (); node = cgraph_node::rtl_info (current_function_decl); gcc_assert (node != NULL); - COPY_HARD_REG_SET (node->function_used_regs, function_used_regs); - node->function_used_regs_valid = 1; -} - -/* Get the declaration of the function called by INSN. */ - -static tree -get_call_fndecl (rtx_insn *insn) -{ - rtx note, datum; - - note = find_reg_note (insn, REG_CALL_DECL, NULL_RTX); - if (note == NULL_RTX) - return NULL_TREE; - - datum = XEXP (note, 0); - if (datum != NULL_RTX) - return SYMBOL_REF_DECL (datum); - - return NULL_TREE; + node->function_used_regs = function_used_regs; } - -/* Return the cgraph_rtl_info of the function called by INSN. Returns NULL for - call targets that can be overwritten. */ - -static struct cgraph_rtl_info * -get_call_cgraph_rtl_info (rtx_insn *insn) -{ - tree fndecl; - - if (insn == NULL_RTX) - return NULL; - - fndecl = get_call_fndecl (insn); - if (fndecl == NULL_TREE - || !decl_binds_to_current_def_p (fndecl)) - return NULL; - - return cgraph_node::rtl_info (fndecl); -} - -/* Find hard registers used by function call instruction INSN, and return them - in REG_SET. Return DEFAULT_SET in REG_SET if not found. */ - -bool -get_call_reg_set_usage (rtx_insn *insn, HARD_REG_SET *reg_set, - HARD_REG_SET default_set) -{ - if (flag_ipa_ra) - { - struct cgraph_rtl_info *node = get_call_cgraph_rtl_info (insn); - if (node != NULL - && node->function_used_regs_valid) - { - COPY_HARD_REG_SET (*reg_set, node->function_used_regs); - AND_HARD_REG_SET (*reg_set, default_set); - return true; - } - } - - COPY_HARD_REG_SET (*reg_set, default_set); - return false; -}