00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "coretypes.h"
00026 #include "tm.h"
00027
00028 #include "rtl.h"
00029 #include "tree.h"
00030 #include "tm_p.h"
00031 #include "regs.h"
00032 #include "flags.h"
00033 #include "debug.h"
00034 #include "insn-config.h"
00035 #include "expr.h"
00036 #include "output.h"
00037 #include "recog.h"
00038 #include "integrate.h"
00039 #include "real.h"
00040 #include "except.h"
00041 #include "function.h"
00042 #include "toplev.h"
00043 #include "intl.h"
00044 #include "params.h"
00045 #include "ggc.h"
00046 #include "target.h"
00047 #include "langhooks.h"
00048 #include "tree-pass.h"
00049
00050
00051 #define CEIL_ROUND(VALUE,ALIGN) (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))
00052
00053
00054
00055 typedef struct initial_value_pair GTY(()) {
00056 rtx hard_reg;
00057 rtx pseudo;
00058 } initial_value_pair;
00059 typedef struct initial_value_struct GTY(()) {
00060 int num_entries;
00061 int max_entries;
00062 initial_value_pair * GTY ((length ("%h.num_entries"))) entries;
00063 } initial_value_struct;
00064
00065 static void set_block_origin_self (tree);
00066 static void set_block_abstract_flags (tree, int);
00067
00068
00069
00070
00071 bool
00072 function_attribute_inlinable_p (tree fndecl)
00073 {
00074 if (targetm.attribute_table)
00075 {
00076 tree a;
00077
00078 for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a))
00079 {
00080 tree name = TREE_PURPOSE (a);
00081 int i;
00082
00083 for (i = 0; targetm.attribute_table[i].name != NULL; i++)
00084 if (is_attribute_p (targetm.attribute_table[i].name, name))
00085 return targetm.function_attribute_inlinable_p (fndecl);
00086 }
00087 }
00088
00089 return true;
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 static void
00103 set_block_origin_self (tree stmt)
00104 {
00105 if (BLOCK_ABSTRACT_ORIGIN (stmt) == NULL_TREE)
00106 {
00107 BLOCK_ABSTRACT_ORIGIN (stmt) = stmt;
00108
00109 {
00110 tree local_decl;
00111
00112 for (local_decl = BLOCK_VARS (stmt);
00113 local_decl != NULL_TREE;
00114 local_decl = TREE_CHAIN (local_decl))
00115 set_decl_origin_self (local_decl);
00116 }
00117
00118 {
00119 tree subblock;
00120
00121 for (subblock = BLOCK_SUBBLOCKS (stmt);
00122 subblock != NULL_TREE;
00123 subblock = BLOCK_CHAIN (subblock))
00124 set_block_origin_self (subblock);
00125 }
00126 }
00127 }
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 void
00141 set_decl_origin_self (tree decl)
00142 {
00143 if (DECL_ABSTRACT_ORIGIN (decl) == NULL_TREE)
00144 {
00145 DECL_ABSTRACT_ORIGIN (decl) = decl;
00146 if (TREE_CODE (decl) == FUNCTION_DECL)
00147 {
00148 tree arg;
00149
00150 for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg))
00151 DECL_ABSTRACT_ORIGIN (arg) = arg;
00152 if (DECL_INITIAL (decl) != NULL_TREE
00153 && DECL_INITIAL (decl) != error_mark_node)
00154 set_block_origin_self (DECL_INITIAL (decl));
00155 }
00156 }
00157 }
00158
00159
00160
00161
00162
00163
00164 static void
00165 set_block_abstract_flags (tree stmt, int setting)
00166 {
00167 tree local_decl;
00168 tree subblock;
00169
00170 BLOCK_ABSTRACT (stmt) = setting;
00171
00172 for (local_decl = BLOCK_VARS (stmt);
00173 local_decl != NULL_TREE;
00174 local_decl = TREE_CHAIN (local_decl))
00175 set_decl_abstract_flags (local_decl, setting);
00176
00177 for (subblock = BLOCK_SUBBLOCKS (stmt);
00178 subblock != NULL_TREE;
00179 subblock = BLOCK_CHAIN (subblock))
00180 set_block_abstract_flags (subblock, setting);
00181 }
00182
00183
00184
00185
00186
00187
00188
00189 void
00190 set_decl_abstract_flags (tree decl, int setting)
00191 {
00192 DECL_ABSTRACT (decl) = setting;
00193 if (TREE_CODE (decl) == FUNCTION_DECL)
00194 {
00195 tree arg;
00196
00197 for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg))
00198 DECL_ABSTRACT (arg) = setting;
00199 if (DECL_INITIAL (decl) != NULL_TREE
00200 && DECL_INITIAL (decl) != error_mark_node)
00201 set_block_abstract_flags (DECL_INITIAL (decl), setting);
00202 }
00203 }
00204
00205
00206
00207
00208 rtx
00209 get_hard_reg_initial_reg (struct function *fun, rtx reg)
00210 {
00211 struct initial_value_struct *ivs = fun->hard_reg_initial_vals;
00212 int i;
00213
00214 if (ivs == 0)
00215 return NULL_RTX;
00216
00217 for (i = 0; i < ivs->num_entries; i++)
00218 if (rtx_equal_p (ivs->entries[i].pseudo, reg))
00219 return ivs->entries[i].hard_reg;
00220
00221 return NULL_RTX;
00222 }
00223
00224
00225
00226
00227 rtx
00228 get_hard_reg_initial_val (enum machine_mode mode, unsigned int regno)
00229 {
00230 struct initial_value_struct *ivs;
00231 rtx rv;
00232
00233 rv = has_hard_reg_initial_val (mode, regno);
00234 if (rv)
00235 return rv;
00236
00237 ivs = cfun->hard_reg_initial_vals;
00238 if (ivs == 0)
00239 {
00240 ivs = ggc_alloc (sizeof (initial_value_struct));
00241 ivs->num_entries = 0;
00242 ivs->max_entries = 5;
00243 ivs->entries = ggc_alloc (5 * sizeof (initial_value_pair));
00244 cfun->hard_reg_initial_vals = ivs;
00245 }
00246
00247 if (ivs->num_entries >= ivs->max_entries)
00248 {
00249 ivs->max_entries += 5;
00250 ivs->entries = ggc_realloc (ivs->entries,
00251 ivs->max_entries
00252 * sizeof (initial_value_pair));
00253 }
00254
00255 ivs->entries[ivs->num_entries].hard_reg = gen_rtx_REG (mode, regno);
00256 ivs->entries[ivs->num_entries].pseudo = gen_reg_rtx (mode);
00257
00258 return ivs->entries[ivs->num_entries++].pseudo;
00259 }
00260
00261
00262
00263
00264
00265 rtx
00266 has_hard_reg_initial_val (enum machine_mode mode, unsigned int regno)
00267 {
00268 struct initial_value_struct *ivs;
00269 int i;
00270
00271 ivs = cfun->hard_reg_initial_vals;
00272 if (ivs != 0)
00273 for (i = 0; i < ivs->num_entries; i++)
00274 if (GET_MODE (ivs->entries[i].hard_reg) == mode
00275 && REGNO (ivs->entries[i].hard_reg) == regno)
00276 return ivs->entries[i].pseudo;
00277
00278 return NULL_RTX;
00279 }
00280
00281 unsigned int
00282 emit_initial_value_sets (void)
00283 {
00284 struct initial_value_struct *ivs = cfun->hard_reg_initial_vals;
00285 int i;
00286 rtx seq;
00287
00288 if (ivs == 0)
00289 return 0;
00290
00291 start_sequence ();
00292 for (i = 0; i < ivs->num_entries; i++)
00293 emit_move_insn (ivs->entries[i].pseudo, ivs->entries[i].hard_reg);
00294 seq = get_insns ();
00295 end_sequence ();
00296
00297 emit_insn_at_entry (seq);
00298 return 0;
00299 }
00300
00301 struct tree_opt_pass pass_initial_value_sets =
00302 {
00303 "initvals",
00304 NULL,
00305 emit_initial_value_sets,
00306 NULL,
00307 NULL,
00308 0,
00309 0,
00310 0,
00311 0,
00312 0,
00313 0,
00314 TODO_dump_func,
00315 0
00316 };
00317
00318
00319
00320 void
00321 allocate_initial_values (rtx *reg_equiv_memory_loc ATTRIBUTE_UNUSED)
00322 {
00323 if (targetm.allocate_initial_value)
00324 {
00325 struct initial_value_struct *ivs = cfun->hard_reg_initial_vals;
00326 int i;
00327
00328 if (ivs == 0)
00329 return;
00330
00331 for (i = 0; i < ivs->num_entries; i++)
00332 {
00333 int regno = REGNO (ivs->entries[i].pseudo);
00334 rtx x = targetm.allocate_initial_value (ivs->entries[i].hard_reg);
00335
00336 if (x && REG_N_SETS (REGNO (ivs->entries[i].pseudo)) <= 1)
00337 {
00338 if (MEM_P (x))
00339 reg_equiv_memory_loc[regno] = x;
00340 else
00341 {
00342 basic_block bb;
00343 int new_regno;
00344
00345 gcc_assert (REG_P (x));
00346 new_regno = REGNO (x);
00347 reg_renumber[regno] = new_regno;
00348
00349
00350 REGNO (ivs->entries[i].pseudo) = new_regno;
00351
00352 FOR_EACH_BB (bb)
00353 {
00354 struct rtl_bb_info *info = bb->il.rtl;
00355
00356 if (REGNO_REG_SET_P(info->global_live_at_start, regno))
00357 SET_REGNO_REG_SET (info->global_live_at_start,
00358 new_regno);
00359 if (REGNO_REG_SET_P(info->global_live_at_end, regno))
00360 SET_REGNO_REG_SET (info->global_live_at_end,
00361 new_regno);
00362 }
00363 }
00364 }
00365 }
00366 }
00367 }
00368
00369 #include "gt-integrate.h"