OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [integrate.c] - Blame information for rev 774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 684 jeremybenn
/* Procedure integration for GCC.
2
   Copyright (C) 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3
   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
4
   Free Software Foundation, Inc.
5
   Contributed by Michael Tiemann (tiemann@cygnus.com)
6
 
7
This file is part of GCC.
8
 
9
GCC is free software; you can redistribute it and/or modify it under
10
the terms of the GNU General Public License as published by the Free
11
Software Foundation; either version 3, or (at your option) any later
12
version.
13
 
14
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15
WARRANTY; without even the implied warranty of MERCHANTABILITY or
16
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17
for more details.
18
 
19
You should have received a copy of the GNU General Public License
20
along with GCC; see the file COPYING3.  If not see
21
<http://www.gnu.org/licenses/>.  */
22
 
23
#include "config.h"
24
#include "system.h"
25
#include "coretypes.h"
26
#include "tm.h"
27
 
28
#include "rtl.h"
29
#include "tree.h"
30
#include "tm_p.h"
31
#include "regs.h"
32
#include "flags.h"
33
#include "debug.h"
34
#include "insn-config.h"
35
#include "expr.h"
36
#include "output.h"
37
#include "recog.h"
38
/* For reg_equivs.  */
39
#include "reload.h"
40
#include "integrate.h"
41
#include "except.h"
42
#include "function.h"
43
#include "diagnostic-core.h"
44
#include "intl.h"
45
#include "params.h"
46
#include "ggc.h"
47
#include "target.h"
48
#include "langhooks.h"
49
#include "tree-pass.h"
50
#include "df.h"
51
 
52
/* Round to the next highest integer that meets the alignment.  */
53
#define CEIL_ROUND(VALUE,ALIGN) (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))
54
 
55
 
56
/* Private type used by {get/has}_hard_reg_initial_val.  */
57
typedef struct GTY(()) initial_value_pair {
58
  rtx hard_reg;
59
  rtx pseudo;
60
} initial_value_pair;
61
typedef struct GTY(()) initial_value_struct {
62
  int num_entries;
63
  int max_entries;
64
  initial_value_pair * GTY ((length ("%h.num_entries"))) entries;
65
} initial_value_struct;
66
 
67
static void set_block_origin_self (tree);
68
static void set_block_abstract_flags (tree, int);
69
 
70
 
71
/* Return false if the function FNDECL cannot be inlined on account of its
72
   attributes, true otherwise.  */
73
bool
74
function_attribute_inlinable_p (const_tree fndecl)
75
{
76
  if (targetm.attribute_table)
77
    {
78
      const_tree a;
79
 
80
      for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a))
81
        {
82
          const_tree name = TREE_PURPOSE (a);
83
          int i;
84
 
85
          for (i = 0; targetm.attribute_table[i].name != NULL; i++)
86
            if (is_attribute_p (targetm.attribute_table[i].name, name))
87
              return targetm.function_attribute_inlinable_p (fndecl);
88
        }
89
    }
90
 
91
  return true;
92
}
93
 
94
/* Given a pointer to some BLOCK node, if the BLOCK_ABSTRACT_ORIGIN for the
95
   given BLOCK node is NULL, set the BLOCK_ABSTRACT_ORIGIN for the node so
96
   that it points to the node itself, thus indicating that the node is its
97
   own (abstract) origin.  Additionally, if the BLOCK_ABSTRACT_ORIGIN for
98
   the given node is NULL, recursively descend the decl/block tree which
99
   it is the root of, and for each other ..._DECL or BLOCK node contained
100
   therein whose DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also
101
   still NULL, set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN
102
   values to point to themselves.  */
103
 
104
static void
105
set_block_origin_self (tree stmt)
106
{
107
  if (BLOCK_ABSTRACT_ORIGIN (stmt) == NULL_TREE)
108
    {
109
      BLOCK_ABSTRACT_ORIGIN (stmt) = stmt;
110
 
111
      {
112
        tree local_decl;
113
 
114
        for (local_decl = BLOCK_VARS (stmt);
115
             local_decl != NULL_TREE;
116
             local_decl = DECL_CHAIN (local_decl))
117
          if (! DECL_EXTERNAL (local_decl))
118
            set_decl_origin_self (local_decl);  /* Potential recursion.  */
119
      }
120
 
121
      {
122
        tree subblock;
123
 
124
        for (subblock = BLOCK_SUBBLOCKS (stmt);
125
             subblock != NULL_TREE;
126
             subblock = BLOCK_CHAIN (subblock))
127
          set_block_origin_self (subblock);     /* Recurse.  */
128
      }
129
    }
130
}
131
 
132
/* Given a pointer to some ..._DECL node, if the DECL_ABSTRACT_ORIGIN for
133
   the given ..._DECL node is NULL, set the DECL_ABSTRACT_ORIGIN for the
134
   node to so that it points to the node itself, thus indicating that the
135
   node represents its own (abstract) origin.  Additionally, if the
136
   DECL_ABSTRACT_ORIGIN for the given node is NULL, recursively descend
137
   the decl/block tree of which the given node is the root of, and for
138
   each other ..._DECL or BLOCK node contained therein whose
139
   DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also still NULL,
140
   set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN values to
141
   point to themselves.  */
142
 
143
void
144
set_decl_origin_self (tree decl)
145
{
146
  if (DECL_ABSTRACT_ORIGIN (decl) == NULL_TREE)
147
    {
148
      DECL_ABSTRACT_ORIGIN (decl) = decl;
149
      if (TREE_CODE (decl) == FUNCTION_DECL)
150
        {
151
          tree arg;
152
 
153
          for (arg = DECL_ARGUMENTS (decl); arg; arg = DECL_CHAIN (arg))
154
            DECL_ABSTRACT_ORIGIN (arg) = arg;
155
          if (DECL_INITIAL (decl) != NULL_TREE
156
              && DECL_INITIAL (decl) != error_mark_node)
157
            set_block_origin_self (DECL_INITIAL (decl));
158
        }
159
    }
160
}
161
 
162
/* Given a pointer to some BLOCK node, and a boolean value to set the
163
   "abstract" flags to, set that value into the BLOCK_ABSTRACT flag for
164
   the given block, and for all local decls and all local sub-blocks
165
   (recursively) which are contained therein.  */
166
 
167
static void
168
set_block_abstract_flags (tree stmt, int setting)
169
{
170
  tree local_decl;
171
  tree subblock;
172
  unsigned int i;
173
 
174
  BLOCK_ABSTRACT (stmt) = setting;
175
 
176
  for (local_decl = BLOCK_VARS (stmt);
177
       local_decl != NULL_TREE;
178
       local_decl = DECL_CHAIN (local_decl))
179
    if (! DECL_EXTERNAL (local_decl))
180
      set_decl_abstract_flags (local_decl, setting);
181
 
182
  for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++)
183
    {
184
      local_decl = BLOCK_NONLOCALIZED_VAR (stmt, i);
185
      if ((TREE_CODE (local_decl) == VAR_DECL && !TREE_STATIC (local_decl))
186
          || TREE_CODE (local_decl) == PARM_DECL)
187
        set_decl_abstract_flags (local_decl, setting);
188
    }
189
 
190
  for (subblock = BLOCK_SUBBLOCKS (stmt);
191
       subblock != NULL_TREE;
192
       subblock = BLOCK_CHAIN (subblock))
193
    set_block_abstract_flags (subblock, setting);
194
}
195
 
196
/* Given a pointer to some ..._DECL node, and a boolean value to set the
197
   "abstract" flags to, set that value into the DECL_ABSTRACT flag for the
198
   given decl, and (in the case where the decl is a FUNCTION_DECL) also
199
   set the abstract flags for all of the parameters, local vars, local
200
   blocks and sub-blocks (recursively) to the same setting.  */
201
 
202
void
203
set_decl_abstract_flags (tree decl, int setting)
204
{
205
  DECL_ABSTRACT (decl) = setting;
206
  if (TREE_CODE (decl) == FUNCTION_DECL)
207
    {
208
      tree arg;
209
 
210
      for (arg = DECL_ARGUMENTS (decl); arg; arg = DECL_CHAIN (arg))
211
        DECL_ABSTRACT (arg) = setting;
212
      if (DECL_INITIAL (decl) != NULL_TREE
213
          && DECL_INITIAL (decl) != error_mark_node)
214
        set_block_abstract_flags (DECL_INITIAL (decl), setting);
215
    }
216
}
217
 
218
/* Functions to keep track of the values hard regs had at the start of
219
   the function.  */
220
 
221
rtx
222
get_hard_reg_initial_reg (rtx reg)
223
{
224
  struct initial_value_struct *ivs = crtl->hard_reg_initial_vals;
225
  int i;
226
 
227
  if (ivs == 0)
228
    return NULL_RTX;
229
 
230
  for (i = 0; i < ivs->num_entries; i++)
231
    if (rtx_equal_p (ivs->entries[i].pseudo, reg))
232
      return ivs->entries[i].hard_reg;
233
 
234
  return NULL_RTX;
235
}
236
 
237
/* Make sure that there's a pseudo register of mode MODE that stores the
238
   initial value of hard register REGNO.  Return an rtx for such a pseudo.  */
239
 
240
rtx
241
get_hard_reg_initial_val (enum machine_mode mode, unsigned int regno)
242
{
243
  struct initial_value_struct *ivs;
244
  rtx rv;
245
 
246
  rv = has_hard_reg_initial_val (mode, regno);
247
  if (rv)
248
    return rv;
249
 
250
  ivs = crtl->hard_reg_initial_vals;
251
  if (ivs == 0)
252
    {
253
      ivs = ggc_alloc_initial_value_struct ();
254
      ivs->num_entries = 0;
255
      ivs->max_entries = 5;
256
      ivs->entries = ggc_alloc_vec_initial_value_pair (5);
257
      crtl->hard_reg_initial_vals = ivs;
258
    }
259
 
260
  if (ivs->num_entries >= ivs->max_entries)
261
    {
262
      ivs->max_entries += 5;
263
      ivs->entries = GGC_RESIZEVEC (initial_value_pair, ivs->entries,
264
                                    ivs->max_entries);
265
    }
266
 
267
  ivs->entries[ivs->num_entries].hard_reg = gen_rtx_REG (mode, regno);
268
  ivs->entries[ivs->num_entries].pseudo = gen_reg_rtx (mode);
269
 
270
  return ivs->entries[ivs->num_entries++].pseudo;
271
}
272
 
273
/* See if get_hard_reg_initial_val has been used to create a pseudo
274
   for the initial value of hard register REGNO in mode MODE.  Return
275
   the associated pseudo if so, otherwise return NULL.  */
276
 
277
rtx
278
has_hard_reg_initial_val (enum machine_mode mode, unsigned int regno)
279
{
280
  struct initial_value_struct *ivs;
281
  int i;
282
 
283
  ivs = crtl->hard_reg_initial_vals;
284
  if (ivs != 0)
285
    for (i = 0; i < ivs->num_entries; i++)
286
      if (GET_MODE (ivs->entries[i].hard_reg) == mode
287
          && REGNO (ivs->entries[i].hard_reg) == regno)
288
        return ivs->entries[i].pseudo;
289
 
290
  return NULL_RTX;
291
}
292
 
293
unsigned int
294
emit_initial_value_sets (void)
295
{
296
  struct initial_value_struct *ivs = crtl->hard_reg_initial_vals;
297
  int i;
298
  rtx seq;
299
 
300
  if (ivs == 0)
301
    return 0;
302
 
303
  start_sequence ();
304
  for (i = 0; i < ivs->num_entries; i++)
305
    emit_move_insn (ivs->entries[i].pseudo, ivs->entries[i].hard_reg);
306
  seq = get_insns ();
307
  end_sequence ();
308
 
309
  emit_insn_at_entry (seq);
310
  return 0;
311
}
312
 
313
struct rtl_opt_pass pass_initial_value_sets =
314
{
315
 {
316
  RTL_PASS,
317
  "initvals",                           /* name */
318
  NULL,                                 /* gate */
319
  emit_initial_value_sets,              /* execute */
320
  NULL,                                 /* sub */
321
  NULL,                                 /* next */
322
  0,                                    /* static_pass_number */
323
  TV_NONE,                              /* tv_id */
324
  0,                                    /* properties_required */
325
  0,                                    /* properties_provided */
326
  0,                                    /* properties_destroyed */
327
  0,                                    /* todo_flags_start */
328
 
329
 }
330
};
331
 
332
/* If the backend knows where to allocate pseudos for hard
333
   register initial values, register these allocations now.  */
334
void
335
allocate_initial_values (VEC (reg_equivs_t, gc) *reg_equivs)
336
{
337
  if (targetm.allocate_initial_value)
338
    {
339
      struct initial_value_struct *ivs = crtl->hard_reg_initial_vals;
340
      int i;
341
 
342
      if (ivs == 0)
343
        return;
344
 
345
      for (i = 0; i < ivs->num_entries; i++)
346
        {
347
          int regno = REGNO (ivs->entries[i].pseudo);
348
          rtx x = targetm.allocate_initial_value (ivs->entries[i].hard_reg);
349
 
350
          if (x && REG_N_SETS (REGNO (ivs->entries[i].pseudo)) <= 1)
351
            {
352
              if (MEM_P (x))
353
                reg_equiv_memory_loc (regno) = x;
354
              else
355
                {
356
                  basic_block bb;
357
                  int new_regno;
358
 
359
                  gcc_assert (REG_P (x));
360
                  new_regno = REGNO (x);
361
                  reg_renumber[regno] = new_regno;
362
                  /* Poke the regno right into regno_reg_rtx so that even
363
                     fixed regs are accepted.  */
364
                  SET_REGNO (ivs->entries[i].pseudo, new_regno);
365
                  /* Update global register liveness information.  */
366
                  FOR_EACH_BB (bb)
367
                    {
368
                      if (REGNO_REG_SET_P(df_get_live_in (bb), regno))
369
                        SET_REGNO_REG_SET (df_get_live_in (bb), new_regno);
370
                      if (REGNO_REG_SET_P(df_get_live_out (bb), regno))
371
                        SET_REGNO_REG_SET (df_get_live_out (bb), new_regno);
372
                    }
373
                }
374
            }
375
        }
376
    }
377
}
378
 
379
#include "gt-integrate.h"

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.