1 /* Analyze functions to determine if callers need to allocate a frame header 2 on the stack. The frame header is used by callees to save their arguments. 3 This optimization is specific to TARGET_OLDABI targets. For TARGET_NEWABI 4 targets, if a frame header is required, it is allocated by the callee. 5 6 7 Copyright (C) 2015-2016 Free Software Foundation, Inc. 8 9 This file is part of GCC. 10 11 GCC is free software; you can redistribute it and/or modify it 12 under the terms of the GNU General Public License as published by the 13 Free Software Foundation; either version 3, or (at your option) any 14 later version. 15 16 GCC is distributed in the hope that it will be useful, but WITHOUT 17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 19 for more details. 20 21 You should have received a copy of the GNU General Public License 22 along with GCC; see the file COPYING3. If not see 23 <http://www.gnu.org/licenses/>. */ 24 25 26 #include "config.h" 27 #include "system.h" 28 #include "context.h" 29 #include "coretypes.h" 30 #include "tree.h" 31 #include "tree-core.h" 32 #include "tree-pass.h" 33 #include "target.h" 34 #include "target-globals.h" 35 #include "cfg.h" 36 #include "cgraph.h" 37 #include "function.h" 38 #include "basic-block.h" 39 #include "gimple.h" 40 #include "gimple-iterator.h" 41 #include "gimple-walk.h" 42 43 static unsigned int frame_header_opt (void); 44 45 namespace { 46 47 const pass_data pass_data_ipa_frame_header_opt = 48 { 49 IPA_PASS, /* type */ 50 "frame-header-opt", /* name */ 51 OPTGROUP_NONE, /* optinfo_flags */ 52 TV_CGRAPHOPT, /* tv_id */ 53 0, /* properties_required */ 54 0, /* properties_provided */ 55 0, /* properties_destroyed */ 56 0, /* todo_flags_start */ 57 0, /* todo_flags_finish */ 58 }; 59 60 class pass_ipa_frame_header_opt : public ipa_opt_pass_d 61 { 62 public: 63 pass_ipa_frame_header_opt (gcc::context *ctxt) 64 : ipa_opt_pass_d (pass_data_ipa_frame_header_opt, ctxt, 65 NULL, /* generate_summary */ 66 NULL, /* write_summary */ 67 NULL, /* read_summary */ 68 NULL, /* write_optimization_summary */ 69 NULL, /* read_optimization_summary */ 70 NULL, /* stmt_fixup */ 71 0, /* function_transform_todo_flags_start */ 72 NULL, /* function_transform */ 73 NULL) /* variable_transform */ 74 {} 75 76 /* opt_pass methods: */ 77 virtual bool gate (function *) 78 { 79 /* This optimization has no affect if TARGET_NEWABI. If optimize 80 is not at least 1 then the data needed for the optimization is 81 not available and nothing will be done anyway. */ 82 return TARGET_OLDABI && flag_frame_header_optimization && optimize > 0; 83 } 84 85 virtual unsigned int execute (function *) { return frame_header_opt (); } 86 87 }; // class pass_ipa_frame_header_opt 88 89 } // anon namespace 90 91 static ipa_opt_pass_d * 92 make_pass_ipa_frame_header_opt (gcc::context *ctxt) 93 { 94 return new pass_ipa_frame_header_opt (ctxt); 95 } 96 97 void 98 mips_register_frame_header_opt (void) 99 { 100 opt_pass *p = make_pass_ipa_frame_header_opt (g); 101 struct register_pass_info f = { p, "comdats", 1, PASS_POS_INSERT_AFTER }; 102 register_pass (&f); 103 } 104 105 106 /* Return true if it is certain that this is a leaf function. False if it is 107 not a leaf function or if it is impossible to tell. */ 108 109 static bool 110 is_leaf_function (function *fn) 111 { 112 basic_block bb; 113 gimple_stmt_iterator gsi; 114 115 /* If we do not have a cfg for this function be conservative and assume 116 it is not a leaf function. */ 117 if (fn->cfg == NULL) 118 return false; 119 120 FOR_EACH_BB_FN (bb, fn) 121 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 122 if (is_gimple_call (gsi_stmt (gsi))) 123 return false; 124 return true; 125 } 126 127 /* Return true if this function has inline assembly code or if we cannot 128 be certain that it does not. False if we know that there is no inline 129 assembly. */ 130 131 static bool 132 has_inlined_assembly (function *fn) 133 { 134 basic_block bb; 135 gimple_stmt_iterator gsi; 136 137 /* If we do not have a cfg for this function be conservative and assume 138 it is may have inline assembly. */ 139 if (fn->cfg == NULL) 140 return true; 141 142 FOR_EACH_BB_FN (bb, fn) 143 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 144 if (gimple_code (gsi_stmt (gsi)) == GIMPLE_ASM) 145 return true; 146 147 return false; 148 } 149 150 /* Return true if this function will use the stack space allocated by its 151 caller or if we cannot determine for certain that it does not. */ 152 153 static bool 154 needs_frame_header_p (function *fn) 155 { 156 tree t; 157 158 if (fn->decl == NULL) 159 return true; 160 161 if (fn->stdarg) 162 return true; 163 164 for (t = DECL_ARGUMENTS (fn->decl); t; t = TREE_CHAIN (t)) 165 { 166 if (!use_register_for_decl (t)) 167 return true; 168 169 /* Some 64-bit types may get copied to general registers using the frame 170 header, see mips_output_64bit_xfer. Checking for SImode only may be 171 overly restrictive but it is guaranteed to be safe. */ 172 if (DECL_MODE (t) != SImode) 173 return true; 174 } 175 176 return false; 177 } 178 179 /* Return true if the argument stack space allocated by function FN is used. 180 Return false if the space is needed or if the need for the space cannot 181 be determined. */ 182 183 static bool 184 callees_functions_use_frame_header (function *fn) 185 { 186 basic_block bb; 187 gimple_stmt_iterator gsi; 188 gimple *stmt; 189 tree called_fn_tree; 190 function *called_fn; 191 192 if (fn->cfg == NULL) 193 return true; 194 195 FOR_EACH_BB_FN (bb, fn) 196 { 197 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 198 { 199 stmt = gsi_stmt (gsi); 200 if (is_gimple_call (stmt)) 201 { 202 called_fn_tree = gimple_call_fndecl (stmt); 203 if (called_fn_tree != NULL) 204 { 205 called_fn = DECL_STRUCT_FUNCTION (called_fn_tree); 206 if (called_fn == NULL 207 || DECL_WEAK (called_fn_tree) 208 || has_inlined_assembly (called_fn) 209 || !is_leaf_function (called_fn) 210 || !called_fn->machine->does_not_use_frame_header) 211 return true; 212 } 213 else 214 return true; 215 } 216 } 217 } 218 return false; 219 } 220 221 /* Set the callers_may_not_allocate_frame flag for any function which 222 function FN calls because FN may not allocate a frame header. */ 223 224 static void 225 set_callers_may_not_allocate_frame (function *fn) 226 { 227 basic_block bb; 228 gimple_stmt_iterator gsi; 229 gimple *stmt; 230 tree called_fn_tree; 231 function *called_fn; 232 233 if (fn->cfg == NULL) 234 return; 235 236 FOR_EACH_BB_FN (bb, fn) 237 { 238 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 239 { 240 stmt = gsi_stmt (gsi); 241 if (is_gimple_call (stmt)) 242 { 243 called_fn_tree = gimple_call_fndecl (stmt); 244 if (called_fn_tree != NULL) 245 { 246 called_fn = DECL_STRUCT_FUNCTION (called_fn_tree); 247 if (called_fn != NULL) 248 called_fn->machine->callers_may_not_allocate_frame = true; 249 } 250 } 251 } 252 } 253 return; 254 } 255 256 /* Scan each function to determine those that need its frame headers. Perform 257 a second scan to determine if the allocation can be skipped because none of 258 their callees require the frame header. */ 259 260 static unsigned int 261 frame_header_opt () 262 { 263 struct cgraph_node *node; 264 function *fn; 265 266 FOR_EACH_DEFINED_FUNCTION (node) 267 { 268 fn = node->get_fun (); 269 if (fn != NULL) 270 fn->machine->does_not_use_frame_header = !needs_frame_header_p (fn); 271 } 272 273 FOR_EACH_DEFINED_FUNCTION (node) 274 { 275 fn = node->get_fun (); 276 if (fn != NULL) 277 fn->machine->optimize_call_stack 278 = !callees_functions_use_frame_header (fn) && !is_leaf_function (fn); 279 } 280 281 FOR_EACH_DEFINED_FUNCTION (node) 282 { 283 fn = node->get_fun (); 284 if (fn != NULL && fn->machine->optimize_call_stack) 285 set_callers_may_not_allocate_frame (fn); 286 } 287 288 return 0; 289 } 290