Mercurial > hg > CbC > CbC_gcc
comparison gcc/final.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
1 /* Convert RTL to assembler code and output it, for GNU compiler. | 1 /* Convert RTL to assembler code and output it, for GNU compiler. |
2 Copyright (C) 1987-2018 Free Software Foundation, Inc. | 2 Copyright (C) 1987-2020 Free Software Foundation, Inc. |
3 | 3 |
4 This file is part of GCC. | 4 This file is part of GCC. |
5 | 5 |
6 GCC is free software; you can redistribute it and/or modify it under | 6 GCC is free software; you can redistribute it and/or modify it under |
7 the terms of the GNU General Public License as published by the Free | 7 the terms of the GNU General Public License as published by the Free |
73 #include "cfgrtl.h" | 73 #include "cfgrtl.h" |
74 #include "debug.h" | 74 #include "debug.h" |
75 #include "tree-pass.h" | 75 #include "tree-pass.h" |
76 #include "tree-ssa.h" | 76 #include "tree-ssa.h" |
77 #include "cfgloop.h" | 77 #include "cfgloop.h" |
78 #include "params.h" | |
79 #include "stringpool.h" | 78 #include "stringpool.h" |
80 #include "attribs.h" | 79 #include "attribs.h" |
81 #include "asan.h" | 80 #include "asan.h" |
82 #include "rtl-iter.h" | 81 #include "rtl-iter.h" |
83 #include "print-rtl.h" | 82 #include "print-rtl.h" |
83 #include "function-abi.h" | |
84 | 84 |
85 #ifdef XCOFF_DEBUGGING_INFO | 85 #ifdef XCOFF_DEBUGGING_INFO |
86 #include "xcoffout.h" /* Needed for external data declarations. */ | 86 #include "xcoffout.h" /* Needed for external data declarations. */ |
87 #endif | 87 #endif |
88 | 88 |
126 static int last_discriminator; | 126 static int last_discriminator; |
127 | 127 |
128 /* Discriminator to be written to assembly for current instruction. | 128 /* Discriminator to be written to assembly for current instruction. |
129 Note: actual usage depends on loc_discriminator_kind setting. */ | 129 Note: actual usage depends on loc_discriminator_kind setting. */ |
130 static int discriminator; | 130 static int discriminator; |
131 static inline int compute_discriminator (location_t loc); | |
131 | 132 |
132 /* Discriminator identifying current basic block among others sharing | 133 /* Discriminator identifying current basic block among others sharing |
133 the same locus. */ | 134 the same locus. */ |
134 static int bb_discriminator; | 135 static int bb_discriminator; |
135 | 136 |
147 | 148 |
148 /* Override filename, line and column number. */ | 149 /* Override filename, line and column number. */ |
149 static const char *override_filename; | 150 static const char *override_filename; |
150 static int override_linenum; | 151 static int override_linenum; |
151 static int override_columnnum; | 152 static int override_columnnum; |
153 static int override_discriminator; | |
152 | 154 |
153 /* Whether to force emission of a line note before the next insn. */ | 155 /* Whether to force emission of a line note before the next insn. */ |
154 static bool force_source_line = false; | 156 static bool force_source_line = false; |
155 | 157 |
156 extern const int length_unit_log; /* This is defined in insn-attrtab.c. */ | 158 extern const int length_unit_log; /* This is defined in insn-attrtab.c. */ |
226 #if HAVE_cc0 | 228 #if HAVE_cc0 |
227 static int alter_cond (rtx); | 229 static int alter_cond (rtx); |
228 #endif | 230 #endif |
229 static int align_fuzz (rtx, rtx, int, unsigned); | 231 static int align_fuzz (rtx, rtx, int, unsigned); |
230 static void collect_fn_hard_reg_usage (void); | 232 static void collect_fn_hard_reg_usage (void); |
231 static tree get_call_fndecl (rtx_insn *); | |
232 | 233 |
233 /* Initialize data in final at the beginning of a compilation. */ | 234 /* Initialize data in final at the beginning of a compilation. */ |
234 | 235 |
235 void | 236 void |
236 init_final (const char *filename ATTRIBUTE_UNUSED) | 237 init_final (const char *filename ATTRIBUTE_UNUSED) |
602 if (! INSN_ADDRESSES_SET_P ()) | 603 if (! INSN_ADDRESSES_SET_P ()) |
603 return 0; | 604 return 0; |
604 | 605 |
605 rtx_insn *seq = NEXT_INSN (PREV_INSN (branch)); | 606 rtx_insn *seq = NEXT_INSN (PREV_INSN (branch)); |
606 seq_uid = INSN_UID (seq); | 607 seq_uid = INSN_UID (seq); |
607 if (!JUMP_P (branch)) | 608 if (!jump_to_label_p (branch)) |
608 /* This can happen for example on the PA; the objective is to know the | 609 /* This can happen for example on the PA; the objective is to know the |
609 offset to address something in front of the start of the function. | 610 offset to address something in front of the start of the function. |
610 Thus, we can treat it like a backward branch. | 611 Thus, we can treat it like a backward branch. |
611 We assume here that FUNCTION_BOUNDARY / BITS_PER_UNIT is larger than | 612 We assume here that FUNCTION_BOUNDARY / BITS_PER_UNIT is larger than |
612 any alignment we'd encounter, so we skip the call to align_fuzz. */ | 613 any alignment we'd encounter, so we skip the call to align_fuzz. */ |
653 dump_flow_info (dump_file, TDF_DETAILS); | 654 dump_flow_info (dump_file, TDF_DETAILS); |
654 flow_loops_dump (dump_file, NULL, 1); | 655 flow_loops_dump (dump_file, NULL, 1); |
655 } | 656 } |
656 loop_optimizer_init (AVOID_CFG_MODIFICATIONS); | 657 loop_optimizer_init (AVOID_CFG_MODIFICATIONS); |
657 profile_count count_threshold = cfun->cfg->count_max.apply_scale | 658 profile_count count_threshold = cfun->cfg->count_max.apply_scale |
658 (1, PARAM_VALUE (PARAM_ALIGN_THRESHOLD)); | 659 (1, param_align_threshold); |
659 | 660 |
660 if (dump_file) | 661 if (dump_file) |
661 { | 662 { |
662 fprintf (dump_file, "count_max: "); | 663 fprintf (dump_file, "count_max: "); |
663 cfun->cfg->count_max.dump (dump_file); | 664 cfun->cfg->count_max.dump (dump_file); |
739 && single_succ (bb) == EXIT_BLOCK_PTR_FOR_FN (cfun)) | 740 && single_succ (bb) == EXIT_BLOCK_PTR_FOR_FN (cfun)) |
740 && optimize_bb_for_speed_p (bb) | 741 && optimize_bb_for_speed_p (bb) |
741 && branch_count + fallthru_count > count_threshold | 742 && branch_count + fallthru_count > count_threshold |
742 && (branch_count | 743 && (branch_count |
743 > fallthru_count.apply_scale | 744 > fallthru_count.apply_scale |
744 (PARAM_VALUE (PARAM_ALIGN_LOOP_ITERATIONS), 1))) | 745 (param_align_loop_iterations, 1))) |
745 { | 746 { |
746 align_flags alignment = LOOP_ALIGN (label); | 747 align_flags alignment = LOOP_ALIGN (label); |
747 if (dump_file) | 748 if (dump_file) |
748 fprintf (dump_file, " internal loop alignment added.\n"); | 749 fprintf (dump_file, " internal loop alignment added.\n"); |
749 max_alignment = align_flags::max (max_alignment, alignment); | 750 max_alignment = align_flags::max (max_alignment, alignment); |
2340 if (locus_ptr != NULL) | 2341 if (locus_ptr != NULL) |
2341 { | 2342 { |
2342 override_filename = LOCATION_FILE (*locus_ptr); | 2343 override_filename = LOCATION_FILE (*locus_ptr); |
2343 override_linenum = LOCATION_LINE (*locus_ptr); | 2344 override_linenum = LOCATION_LINE (*locus_ptr); |
2344 override_columnnum = LOCATION_COLUMN (*locus_ptr); | 2345 override_columnnum = LOCATION_COLUMN (*locus_ptr); |
2346 override_discriminator = compute_discriminator (*locus_ptr); | |
2345 } | 2347 } |
2346 } | 2348 } |
2347 break; | 2349 break; |
2348 | 2350 |
2349 case NOTE_INSN_BLOCK_END: | 2351 case NOTE_INSN_BLOCK_END: |
2377 if (locus_ptr != NULL) | 2379 if (locus_ptr != NULL) |
2378 { | 2380 { |
2379 override_filename = LOCATION_FILE (*locus_ptr); | 2381 override_filename = LOCATION_FILE (*locus_ptr); |
2380 override_linenum = LOCATION_LINE (*locus_ptr); | 2382 override_linenum = LOCATION_LINE (*locus_ptr); |
2381 override_columnnum = LOCATION_COLUMN (*locus_ptr); | 2383 override_columnnum = LOCATION_COLUMN (*locus_ptr); |
2384 override_discriminator = compute_discriminator (*locus_ptr); | |
2382 } | 2385 } |
2383 else | 2386 else |
2384 { | 2387 { |
2385 override_filename = NULL; | 2388 override_filename = NULL; |
2386 override_linenum = 0; | 2389 override_linenum = 0; |
2387 override_columnnum = 0; | 2390 override_columnnum = 0; |
2391 override_discriminator = 0; | |
2388 } | 2392 } |
2389 } | 2393 } |
2390 break; | 2394 break; |
2391 | 2395 |
2392 case NOTE_INSN_DELETED_LABEL: | 2396 case NOTE_INSN_DELETED_LABEL: |
2423 } | 2427 } |
2424 break; | 2428 break; |
2425 | 2429 |
2426 case NOTE_INSN_INLINE_ENTRY: | 2430 case NOTE_INSN_INLINE_ENTRY: |
2427 gcc_checking_assert (cfun->debug_nonbind_markers); | 2431 gcc_checking_assert (cfun->debug_nonbind_markers); |
2428 if (!DECL_IGNORED_P (current_function_decl)) | 2432 if (!DECL_IGNORED_P (current_function_decl) |
2433 && notice_source_line (insn, NULL)) | |
2429 { | 2434 { |
2430 if (!notice_source_line (insn, NULL)) | |
2431 break; | |
2432 (*debug_hooks->inline_entry) (LOCATION_BLOCK | 2435 (*debug_hooks->inline_entry) (LOCATION_BLOCK |
2433 (NOTE_MARKER_LOCATION (insn))); | 2436 (NOTE_MARKER_LOCATION (insn))); |
2434 goto output_source_line; | 2437 goto output_source_line; |
2435 } | 2438 } |
2436 break; | 2439 break; |
3183 return *inst; | 3186 return *inst; |
3184 } | 3187 } |
3185 | 3188 |
3186 /* Set DISCRIMINATOR to the appropriate value, possibly derived from LOC. */ | 3189 /* Set DISCRIMINATOR to the appropriate value, possibly derived from LOC. */ |
3187 | 3190 |
3188 static inline void | 3191 static inline int |
3189 maybe_set_discriminator (location_t loc) | 3192 compute_discriminator (location_t loc) |
3190 { | 3193 { |
3194 int discriminator; | |
3195 | |
3191 if (!decl_to_instance_map) | 3196 if (!decl_to_instance_map) |
3192 discriminator = bb_discriminator; | 3197 discriminator = bb_discriminator; |
3193 else | 3198 else |
3194 { | 3199 { |
3195 tree block = LOCATION_BLOCK (loc); | 3200 tree block = LOCATION_BLOCK (loc); |
3207 else | 3212 else |
3208 decl = block_ultimate_origin (block); | 3213 decl = block_ultimate_origin (block); |
3209 | 3214 |
3210 discriminator = map_decl_to_instance (decl); | 3215 discriminator = map_decl_to_instance (decl); |
3211 } | 3216 } |
3217 | |
3218 return discriminator; | |
3212 } | 3219 } |
3213 | 3220 |
3214 /* Return whether a source line note needs to be emitted before INSN. | 3221 /* Return whether a source line note needs to be emitted before INSN. |
3215 Sets IS_STMT to TRUE if the line should be marked as a possible | 3222 Sets IS_STMT to TRUE if the line should be marked as a possible |
3216 breakpoint location. */ | 3223 breakpoint location. */ |
3232 return false; | 3239 return false; |
3233 } | 3240 } |
3234 filename = xloc.file; | 3241 filename = xloc.file; |
3235 linenum = xloc.line; | 3242 linenum = xloc.line; |
3236 columnnum = xloc.column; | 3243 columnnum = xloc.column; |
3237 maybe_set_discriminator (loc); | 3244 discriminator = compute_discriminator (loc); |
3238 force_source_line = true; | 3245 force_source_line = true; |
3239 } | 3246 } |
3240 else if (override_filename) | 3247 else if (override_filename) |
3241 { | 3248 { |
3242 filename = override_filename; | 3249 filename = override_filename; |
3243 linenum = override_linenum; | 3250 linenum = override_linenum; |
3244 columnnum = override_columnnum; | 3251 columnnum = override_columnnum; |
3252 discriminator = override_discriminator; | |
3245 } | 3253 } |
3246 else if (INSN_HAS_LOCATION (insn)) | 3254 else if (INSN_HAS_LOCATION (insn)) |
3247 { | 3255 { |
3248 expanded_location xloc = insn_location (insn); | 3256 expanded_location xloc = insn_location (insn); |
3249 filename = xloc.file; | 3257 filename = xloc.file; |
3250 linenum = xloc.line; | 3258 linenum = xloc.line; |
3251 columnnum = xloc.column; | 3259 columnnum = xloc.column; |
3252 maybe_set_discriminator (INSN_LOCATION (insn)); | 3260 discriminator = compute_discriminator (INSN_LOCATION (insn)); |
3253 } | 3261 } |
3254 else | 3262 else |
3255 { | 3263 { |
3256 filename = NULL; | 3264 filename = NULL; |
3257 linenum = 0; | 3265 linenum = 0; |
3258 columnnum = 0; | 3266 columnnum = 0; |
3267 discriminator = 0; | |
3259 } | 3268 } |
3260 | 3269 |
3261 if (filename == NULL) | 3270 if (filename == NULL) |
3262 return false; | 3271 return false; |
3263 | 3272 |
4646 rtx_insn *first = get_insns (); | 4655 rtx_insn *first = get_insns (); |
4647 int seen = 0; | 4656 int seen = 0; |
4648 final_start_function_1 (&first, asm_out_file, &seen, optimize); | 4657 final_start_function_1 (&first, asm_out_file, &seen, optimize); |
4649 final_1 (first, asm_out_file, seen, optimize); | 4658 final_1 (first, asm_out_file, seen, optimize); |
4650 if (flag_ipa_ra | 4659 if (flag_ipa_ra |
4651 && !lookup_attribute ("noipa", DECL_ATTRIBUTES (current_function_decl))) | 4660 && !lookup_attribute ("noipa", DECL_ATTRIBUTES (current_function_decl)) |
4661 /* Functions with naked attributes are supported only with basic asm | |
4662 statements in the body, thus for supported use cases the information | |
4663 on clobbered registers is not available. */ | |
4664 && !lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl))) | |
4652 collect_fn_hard_reg_usage (); | 4665 collect_fn_hard_reg_usage (); |
4653 final_end_function (); | 4666 final_end_function (); |
4654 | 4667 |
4655 /* The IA-64 ".handlerdata" directive must be issued before the ".endp" | 4668 /* The IA-64 ".handlerdata" directive must be issued before the ".endp" |
4656 directive that closes the procedure descriptor. Similarly, for x64 SEH. | 4669 directive that closes the procedure descriptor. Similarly, for x64 SEH. |
4888 delete_tree_ssa (cfun); | 4901 delete_tree_ssa (cfun); |
4889 | 4902 |
4890 /* We can reduce stack alignment on call site only when we are sure that | 4903 /* We can reduce stack alignment on call site only when we are sure that |
4891 the function body just produced will be actually used in the final | 4904 the function body just produced will be actually used in the final |
4892 executable. */ | 4905 executable. */ |
4893 if (decl_binds_to_current_def_p (current_function_decl)) | 4906 if (flag_ipa_stack_alignment |
4907 && decl_binds_to_current_def_p (current_function_decl)) | |
4894 { | 4908 { |
4895 unsigned int pref = crtl->preferred_stack_boundary; | 4909 unsigned int pref = crtl->preferred_stack_boundary; |
4896 if (crtl->stack_alignment_needed > crtl->preferred_stack_boundary) | 4910 if (crtl->stack_alignment_needed > crtl->preferred_stack_boundary) |
4897 pref = crtl->stack_alignment_needed; | 4911 pref = crtl->stack_alignment_needed; |
4898 cgraph_node::rtl_info (current_function_decl) | 4912 cgraph_node::rtl_info (current_function_decl) |
4977 | 4991 |
4978 /* ??? To be removed when all the ports have been fixed. */ | 4992 /* ??? To be removed when all the ports have been fixed. */ |
4979 if (!targetm.call_fusage_contains_non_callee_clobbers) | 4993 if (!targetm.call_fusage_contains_non_callee_clobbers) |
4980 return; | 4994 return; |
4981 | 4995 |
4982 CLEAR_HARD_REG_SET (function_used_regs); | |
4983 | |
4984 for (insn = get_insns (); insn != NULL_RTX; insn = next_insn (insn)) | |
4985 { | |
4986 HARD_REG_SET insn_used_regs; | |
4987 | |
4988 if (!NONDEBUG_INSN_P (insn)) | |
4989 continue; | |
4990 | |
4991 if (CALL_P (insn) | |
4992 && !self_recursive_call_p (insn)) | |
4993 { | |
4994 if (!get_call_reg_set_usage (insn, &insn_used_regs, | |
4995 call_used_reg_set)) | |
4996 return; | |
4997 | |
4998 IOR_HARD_REG_SET (function_used_regs, insn_used_regs); | |
4999 } | |
5000 | |
5001 find_all_hard_reg_sets (insn, &insn_used_regs, false); | |
5002 IOR_HARD_REG_SET (function_used_regs, insn_used_regs); | |
5003 } | |
5004 | |
5005 /* Be conservative - mark fixed and global registers as used. */ | 4996 /* Be conservative - mark fixed and global registers as used. */ |
5006 IOR_HARD_REG_SET (function_used_regs, fixed_reg_set); | 4997 function_used_regs = fixed_reg_set; |
5007 | 4998 |
5008 #ifdef STACK_REGS | 4999 #ifdef STACK_REGS |
5009 /* Handle STACK_REGS conservatively, since the df-framework does not | 5000 /* Handle STACK_REGS conservatively, since the df-framework does not |
5010 provide accurate information for them. */ | 5001 provide accurate information for them. */ |
5011 | 5002 |
5012 for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++) | 5003 for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++) |
5013 SET_HARD_REG_BIT (function_used_regs, i); | 5004 SET_HARD_REG_BIT (function_used_regs, i); |
5014 #endif | 5005 #endif |
5015 | 5006 |
5016 /* The information we have gathered is only interesting if it exposes a | 5007 for (insn = get_insns (); insn != NULL_RTX; insn = next_insn (insn)) |
5017 register from the call_used_regs that is not used in this function. */ | 5008 { |
5018 if (hard_reg_set_subset_p (call_used_reg_set, function_used_regs)) | 5009 HARD_REG_SET insn_used_regs; |
5019 return; | 5010 |
5011 if (!NONDEBUG_INSN_P (insn)) | |
5012 continue; | |
5013 | |
5014 if (CALL_P (insn) | |
5015 && !self_recursive_call_p (insn)) | |
5016 function_used_regs | |
5017 |= insn_callee_abi (insn).full_and_partial_reg_clobbers (); | |
5018 | |
5019 find_all_hard_reg_sets (insn, &insn_used_regs, false); | |
5020 function_used_regs |= insn_used_regs; | |
5021 | |
5022 if (hard_reg_set_subset_p (crtl->abi->full_and_partial_reg_clobbers (), | |
5023 function_used_regs)) | |
5024 return; | |
5025 } | |
5026 | |
5027 /* Mask out fully-saved registers, so that they don't affect equality | |
5028 comparisons between function_abis. */ | |
5029 function_used_regs &= crtl->abi->full_and_partial_reg_clobbers (); | |
5020 | 5030 |
5021 node = cgraph_node::rtl_info (current_function_decl); | 5031 node = cgraph_node::rtl_info (current_function_decl); |
5022 gcc_assert (node != NULL); | 5032 gcc_assert (node != NULL); |
5023 | 5033 |
5024 COPY_HARD_REG_SET (node->function_used_regs, function_used_regs); | 5034 node->function_used_regs = function_used_regs; |
5025 node->function_used_regs_valid = 1; | 5035 } |
5026 } | |
5027 | |
5028 /* Get the declaration of the function called by INSN. */ | |
5029 | |
5030 static tree | |
5031 get_call_fndecl (rtx_insn *insn) | |
5032 { | |
5033 rtx note, datum; | |
5034 | |
5035 note = find_reg_note (insn, REG_CALL_DECL, NULL_RTX); | |
5036 if (note == NULL_RTX) | |
5037 return NULL_TREE; | |
5038 | |
5039 datum = XEXP (note, 0); | |
5040 if (datum != NULL_RTX) | |
5041 return SYMBOL_REF_DECL (datum); | |
5042 | |
5043 return NULL_TREE; | |
5044 } | |
5045 | |
5046 /* Return the cgraph_rtl_info of the function called by INSN. Returns NULL for | |
5047 call targets that can be overwritten. */ | |
5048 | |
5049 static struct cgraph_rtl_info * | |
5050 get_call_cgraph_rtl_info (rtx_insn *insn) | |
5051 { | |
5052 tree fndecl; | |
5053 | |
5054 if (insn == NULL_RTX) | |
5055 return NULL; | |
5056 | |
5057 fndecl = get_call_fndecl (insn); | |
5058 if (fndecl == NULL_TREE | |
5059 || !decl_binds_to_current_def_p (fndecl)) | |
5060 return NULL; | |
5061 | |
5062 return cgraph_node::rtl_info (fndecl); | |
5063 } | |
5064 | |
5065 /* Find hard registers used by function call instruction INSN, and return them | |
5066 in REG_SET. Return DEFAULT_SET in REG_SET if not found. */ | |
5067 | |
5068 bool | |
5069 get_call_reg_set_usage (rtx_insn *insn, HARD_REG_SET *reg_set, | |
5070 HARD_REG_SET default_set) | |
5071 { | |
5072 if (flag_ipa_ra) | |
5073 { | |
5074 struct cgraph_rtl_info *node = get_call_cgraph_rtl_info (insn); | |
5075 if (node != NULL | |
5076 && node->function_used_regs_valid) | |
5077 { | |
5078 COPY_HARD_REG_SET (*reg_set, node->function_used_regs); | |
5079 AND_HARD_REG_SET (*reg_set, default_set); | |
5080 return true; | |
5081 } | |
5082 } | |
5083 | |
5084 COPY_HARD_REG_SET (*reg_set, default_set); | |
5085 return false; | |
5086 } |