190075Sobrien/* Procedure integration for GCC. 2132718Skan Copyright (C) 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 3169689Skan 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 418334Speter Contributed by Michael Tiemann (tiemann@cygnus.com) 518334Speter 690075SobrienThis file is part of GCC. 718334Speter 890075SobrienGCC is free software; you can redistribute it and/or modify it under 990075Sobrienthe terms of the GNU General Public License as published by the Free 1090075SobrienSoftware Foundation; either version 2, or (at your option) any later 1190075Sobrienversion. 1218334Speter 1390075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1490075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1590075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1690075Sobrienfor more details. 1718334Speter 1818334SpeterYou should have received a copy of the GNU General Public License 1990075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 21169689Skan02110-1301, USA. */ 2218334Speter 2350397Sobrien#include "config.h" 2450397Sobrien#include "system.h" 25132718Skan#include "coretypes.h" 26132718Skan#include "tm.h" 2718334Speter 2818334Speter#include "rtl.h" 2918334Speter#include "tree.h" 3090075Sobrien#include "tm_p.h" 3150397Sobrien#include "regs.h" 3218334Speter#include "flags.h" 3390075Sobrien#include "debug.h" 3418334Speter#include "insn-config.h" 3518334Speter#include "expr.h" 3618334Speter#include "output.h" 3750397Sobrien#include "recog.h" 3818334Speter#include "integrate.h" 3918334Speter#include "real.h" 4050397Sobrien#include "except.h" 4118334Speter#include "function.h" 4250397Sobrien#include "toplev.h" 4352284Sobrien#include "intl.h" 4490075Sobrien#include "params.h" 4590075Sobrien#include "ggc.h" 4690075Sobrien#include "target.h" 47117395Skan#include "langhooks.h" 48169689Skan#include "tree-pass.h" 4918334Speter 50169689Skan/* Round to the next highest integer that meets the alignment. */ 5118334Speter#define CEIL_ROUND(VALUE,ALIGN) (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1)) 5218334Speter 5318334Speter 54169689Skan/* Private type used by {get/has}_hard_reg_initial_val. */ 55117395Skantypedef struct initial_value_pair GTY(()) { 5690075Sobrien rtx hard_reg; 5790075Sobrien rtx pseudo; 5890075Sobrien} initial_value_pair; 59117395Skantypedef struct initial_value_struct GTY(()) { 6090075Sobrien int num_entries; 6190075Sobrien int max_entries; 62117395Skan initial_value_pair * GTY ((length ("%h.num_entries"))) entries; 6390075Sobrien} initial_value_struct; 6452284Sobrien 65132718Skanstatic void set_block_origin_self (tree); 66132718Skanstatic void set_block_abstract_flags (tree, int); 6718334Speter 6850397Sobrien 6990075Sobrien/* Return false if the function FNDECL cannot be inlined on account of its 7090075Sobrien attributes, true otherwise. */ 7190075Sobrienbool 72132718Skanfunction_attribute_inlinable_p (tree fndecl) 7390075Sobrien{ 74117395Skan if (targetm.attribute_table) 7590075Sobrien { 76117395Skan tree a; 7790075Sobrien 78117395Skan for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a)) 7990075Sobrien { 80117395Skan tree name = TREE_PURPOSE (a); 81117395Skan int i; 82117395Skan 83117395Skan for (i = 0; targetm.attribute_table[i].name != NULL; i++) 84117395Skan if (is_attribute_p (targetm.attribute_table[i].name, name)) 85169689Skan return targetm.function_attribute_inlinable_p (fndecl); 8690075Sobrien } 8790075Sobrien } 8890075Sobrien 89117395Skan return true; 9090075Sobrien} 9118334Speter 9218334Speter/* Given a pointer to some BLOCK node, if the BLOCK_ABSTRACT_ORIGIN for the 9318334Speter given BLOCK node is NULL, set the BLOCK_ABSTRACT_ORIGIN for the node so 9418334Speter that it points to the node itself, thus indicating that the node is its 9518334Speter own (abstract) origin. Additionally, if the BLOCK_ABSTRACT_ORIGIN for 9618334Speter the given node is NULL, recursively descend the decl/block tree which 9718334Speter it is the root of, and for each other ..._DECL or BLOCK node contained 9818334Speter therein whose DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also 9918334Speter still NULL, set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN 10018334Speter values to point to themselves. */ 10118334Speter 10218334Speterstatic void 103132718Skanset_block_origin_self (tree stmt) 10418334Speter{ 10518334Speter if (BLOCK_ABSTRACT_ORIGIN (stmt) == NULL_TREE) 10618334Speter { 10718334Speter BLOCK_ABSTRACT_ORIGIN (stmt) = stmt; 10818334Speter 10918334Speter { 11090075Sobrien tree local_decl; 11118334Speter 11290075Sobrien for (local_decl = BLOCK_VARS (stmt); 11318334Speter local_decl != NULL_TREE; 11418334Speter local_decl = TREE_CHAIN (local_decl)) 11590075Sobrien set_decl_origin_self (local_decl); /* Potential recursion. */ 11618334Speter } 11718334Speter 11818334Speter { 11990075Sobrien tree subblock; 12018334Speter 12190075Sobrien for (subblock = BLOCK_SUBBLOCKS (stmt); 12218334Speter subblock != NULL_TREE; 12318334Speter subblock = BLOCK_CHAIN (subblock)) 12490075Sobrien set_block_origin_self (subblock); /* Recurse. */ 12518334Speter } 12618334Speter } 12718334Speter} 12818334Speter 12918334Speter/* Given a pointer to some ..._DECL node, if the DECL_ABSTRACT_ORIGIN for 13018334Speter the given ..._DECL node is NULL, set the DECL_ABSTRACT_ORIGIN for the 13118334Speter node to so that it points to the node itself, thus indicating that the 13218334Speter node represents its own (abstract) origin. Additionally, if the 13318334Speter DECL_ABSTRACT_ORIGIN for the given node is NULL, recursively descend 13418334Speter the decl/block tree of which the given node is the root of, and for 13518334Speter each other ..._DECL or BLOCK node contained therein whose 13618334Speter DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also still NULL, 13718334Speter set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN values to 13818334Speter point to themselves. */ 13918334Speter 14090075Sobrienvoid 141132718Skanset_decl_origin_self (tree decl) 14218334Speter{ 14318334Speter if (DECL_ABSTRACT_ORIGIN (decl) == NULL_TREE) 14418334Speter { 14518334Speter DECL_ABSTRACT_ORIGIN (decl) = decl; 14618334Speter if (TREE_CODE (decl) == FUNCTION_DECL) 14718334Speter { 14890075Sobrien tree arg; 14918334Speter 15018334Speter for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg)) 15118334Speter DECL_ABSTRACT_ORIGIN (arg) = arg; 15218334Speter if (DECL_INITIAL (decl) != NULL_TREE 15318334Speter && DECL_INITIAL (decl) != error_mark_node) 15418334Speter set_block_origin_self (DECL_INITIAL (decl)); 15518334Speter } 15618334Speter } 15718334Speter} 15818334Speter 15918334Speter/* Given a pointer to some BLOCK node, and a boolean value to set the 16018334Speter "abstract" flags to, set that value into the BLOCK_ABSTRACT flag for 16118334Speter the given block, and for all local decls and all local sub-blocks 16218334Speter (recursively) which are contained therein. */ 16318334Speter 16418334Speterstatic void 165132718Skanset_block_abstract_flags (tree stmt, int setting) 16618334Speter{ 16790075Sobrien tree local_decl; 16890075Sobrien tree subblock; 16950397Sobrien 17018334Speter BLOCK_ABSTRACT (stmt) = setting; 17118334Speter 17250397Sobrien for (local_decl = BLOCK_VARS (stmt); 17350397Sobrien local_decl != NULL_TREE; 17450397Sobrien local_decl = TREE_CHAIN (local_decl)) 17550397Sobrien set_decl_abstract_flags (local_decl, setting); 17618334Speter 17750397Sobrien for (subblock = BLOCK_SUBBLOCKS (stmt); 17850397Sobrien subblock != NULL_TREE; 17950397Sobrien subblock = BLOCK_CHAIN (subblock)) 18050397Sobrien set_block_abstract_flags (subblock, setting); 18118334Speter} 18218334Speter 18318334Speter/* Given a pointer to some ..._DECL node, and a boolean value to set the 18418334Speter "abstract" flags to, set that value into the DECL_ABSTRACT flag for the 18518334Speter given decl, and (in the case where the decl is a FUNCTION_DECL) also 18618334Speter set the abstract flags for all of the parameters, local vars, local 18718334Speter blocks and sub-blocks (recursively) to the same setting. */ 18818334Speter 18918334Spetervoid 190132718Skanset_decl_abstract_flags (tree decl, int setting) 19118334Speter{ 19218334Speter DECL_ABSTRACT (decl) = setting; 19318334Speter if (TREE_CODE (decl) == FUNCTION_DECL) 19418334Speter { 19590075Sobrien tree arg; 19618334Speter 19718334Speter for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg)) 19818334Speter DECL_ABSTRACT (arg) = setting; 19918334Speter if (DECL_INITIAL (decl) != NULL_TREE 20018334Speter && DECL_INITIAL (decl) != error_mark_node) 20118334Speter set_block_abstract_flags (DECL_INITIAL (decl), setting); 20218334Speter } 20318334Speter} 20418334Speter 20590075Sobrien/* Functions to keep track of the values hard regs had at the start of 20690075Sobrien the function. */ 20718334Speter 20890075Sobrienrtx 209132718Skanget_hard_reg_initial_reg (struct function *fun, rtx reg) 21090075Sobrien{ 21190075Sobrien struct initial_value_struct *ivs = fun->hard_reg_initial_vals; 21290075Sobrien int i; 21318334Speter 21490075Sobrien if (ivs == 0) 21590075Sobrien return NULL_RTX; 21618334Speter 21790075Sobrien for (i = 0; i < ivs->num_entries; i++) 21890075Sobrien if (rtx_equal_p (ivs->entries[i].pseudo, reg)) 21990075Sobrien return ivs->entries[i].hard_reg; 22018334Speter 22190075Sobrien return NULL_RTX; 22290075Sobrien} 22318334Speter 224169689Skan/* Make sure that there's a pseudo register of mode MODE that stores the 225169689Skan initial value of hard register REGNO. Return an rtx for such a pseudo. */ 22618334Speter 22790075Sobrienrtx 228169689Skanget_hard_reg_initial_val (enum machine_mode mode, unsigned int regno) 22990075Sobrien{ 230169689Skan struct initial_value_struct *ivs; 231169689Skan rtx rv; 23218334Speter 233169689Skan rv = has_hard_reg_initial_val (mode, regno); 23490075Sobrien if (rv) 23590075Sobrien return rv; 23618334Speter 237169689Skan ivs = cfun->hard_reg_initial_vals; 23890075Sobrien if (ivs == 0) 23990075Sobrien { 240169689Skan ivs = ggc_alloc (sizeof (initial_value_struct)); 24190075Sobrien ivs->num_entries = 0; 24290075Sobrien ivs->max_entries = 5; 243132718Skan ivs->entries = ggc_alloc (5 * sizeof (initial_value_pair)); 244169689Skan cfun->hard_reg_initial_vals = ivs; 24590075Sobrien } 24618334Speter 24790075Sobrien if (ivs->num_entries >= ivs->max_entries) 24818334Speter { 24990075Sobrien ivs->max_entries += 5; 250132718Skan ivs->entries = ggc_realloc (ivs->entries, 251132718Skan ivs->max_entries 252132718Skan * sizeof (initial_value_pair)); 25318334Speter } 25418334Speter 255169689Skan ivs->entries[ivs->num_entries].hard_reg = gen_rtx_REG (mode, regno); 256169689Skan ivs->entries[ivs->num_entries].pseudo = gen_reg_rtx (mode); 25718334Speter 25890075Sobrien return ivs->entries[ivs->num_entries++].pseudo; 25990075Sobrien} 26018334Speter 261169689Skan/* See if get_hard_reg_initial_val has been used to create a pseudo 262169689Skan for the initial value of hard register REGNO in mode MODE. Return 263169689Skan the associated pseudo if so, otherwise return NULL. */ 26418334Speter 26590075Sobrienrtx 266169689Skanhas_hard_reg_initial_val (enum machine_mode mode, unsigned int regno) 26790075Sobrien{ 268169689Skan struct initial_value_struct *ivs; 26990075Sobrien int i; 27090075Sobrien 271169689Skan ivs = cfun->hard_reg_initial_vals; 272169689Skan if (ivs != 0) 273169689Skan for (i = 0; i < ivs->num_entries; i++) 274169689Skan if (GET_MODE (ivs->entries[i].hard_reg) == mode 275169689Skan && REGNO (ivs->entries[i].hard_reg) == regno) 276169689Skan return ivs->entries[i].pseudo; 27790075Sobrien 278169689Skan return NULL_RTX; 27990075Sobrien} 28090075Sobrien 281169689Skanunsigned int 282132718Skanemit_initial_value_sets (void) 28390075Sobrien{ 28490075Sobrien struct initial_value_struct *ivs = cfun->hard_reg_initial_vals; 28590075Sobrien int i; 28690075Sobrien rtx seq; 28790075Sobrien 28890075Sobrien if (ivs == 0) 289169689Skan return 0; 29090075Sobrien 29190075Sobrien start_sequence (); 29290075Sobrien for (i = 0; i < ivs->num_entries; i++) 29390075Sobrien emit_move_insn (ivs->entries[i].pseudo, ivs->entries[i].hard_reg); 29490075Sobrien seq = get_insns (); 29590075Sobrien end_sequence (); 29690075Sobrien 297169689Skan emit_insn_at_entry (seq); 298169689Skan return 0; 29990075Sobrien} 30090075Sobrien 301169689Skanstruct tree_opt_pass pass_initial_value_sets = 302169689Skan{ 303169689Skan "initvals", /* name */ 304169689Skan NULL, /* gate */ 305169689Skan emit_initial_value_sets, /* execute */ 306169689Skan NULL, /* sub */ 307169689Skan NULL, /* next */ 308169689Skan 0, /* static_pass_number */ 309169689Skan 0, /* tv_id */ 310169689Skan 0, /* properties_required */ 311169689Skan 0, /* properties_provided */ 312169689Skan 0, /* properties_destroyed */ 313169689Skan 0, /* todo_flags_start */ 314169689Skan TODO_dump_func, /* todo_flags_finish */ 315169689Skan 0 /* letter */ 316169689Skan}; 317169689Skan 31890075Sobrien/* If the backend knows where to allocate pseudos for hard 31990075Sobrien register initial values, register these allocations now. */ 32090075Sobrienvoid 321132718Skanallocate_initial_values (rtx *reg_equiv_memory_loc ATTRIBUTE_UNUSED) 32290075Sobrien{ 323169689Skan if (targetm.allocate_initial_value) 324169689Skan { 325169689Skan struct initial_value_struct *ivs = cfun->hard_reg_initial_vals; 326169689Skan int i; 32790075Sobrien 328169689Skan if (ivs == 0) 329169689Skan return; 33090075Sobrien 331169689Skan for (i = 0; i < ivs->num_entries; i++) 332169689Skan { 333169689Skan int regno = REGNO (ivs->entries[i].pseudo); 334169689Skan rtx x = targetm.allocate_initial_value (ivs->entries[i].hard_reg); 335169689Skan 336169689Skan if (x && REG_N_SETS (REGNO (ivs->entries[i].pseudo)) <= 1) 337169689Skan { 338169689Skan if (MEM_P (x)) 339169689Skan reg_equiv_memory_loc[regno] = x; 340169689Skan else 341169689Skan { 342169689Skan basic_block bb; 343169689Skan int new_regno; 34490075Sobrien 345169689Skan gcc_assert (REG_P (x)); 346169689Skan new_regno = REGNO (x); 347169689Skan reg_renumber[regno] = new_regno; 348169689Skan /* Poke the regno right into regno_reg_rtx so that even 349169689Skan fixed regs are accepted. */ 350169689Skan REGNO (ivs->entries[i].pseudo) = new_regno; 351169689Skan /* Update global register liveness information. */ 352169689Skan FOR_EACH_BB (bb) 353169689Skan { 354169689Skan struct rtl_bb_info *info = bb->il.rtl; 355169689Skan 356169689Skan if (REGNO_REG_SET_P(info->global_live_at_start, regno)) 357169689Skan SET_REGNO_REG_SET (info->global_live_at_start, 358169689Skan new_regno); 359169689Skan if (REGNO_REG_SET_P(info->global_live_at_end, regno)) 360169689Skan SET_REGNO_REG_SET (info->global_live_at_end, 361169689Skan new_regno); 362169689Skan } 363169689Skan } 364169689Skan } 36590075Sobrien } 36690075Sobrien } 36790075Sobrien} 368117395Skan 369117395Skan#include "gt-integrate.h" 370