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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [web.c] - Blame information for rev 18

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

Line No. Rev Author Line
1 12 jlechner
/* Web construction code for GNU compiler.
2
   Contributed by Jan Hubicka.
3
   Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
4
 
5
This file is part of GCC.
6
 
7
GCC is free software; you can redistribute it and/or modify it under
8
the terms of the GNU General Public License as published by the Free
9
Software Foundation; either version 2, or (at your option) any later
10
version.
11
 
12
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13
WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with GCC; see the file COPYING.  If not, write to the Free
19
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20
02110-1301, USA.  */
21
 
22
/* Simple optimization pass that splits independent uses of each pseudo,
23
   increasing effectiveness of other optimizations.  The optimization can
24
   serve as an example of use for the dataflow module.
25
 
26
   We don't split registers with REG_USERVAR set unless -fmessy-debugging
27
   is specified, because debugging information about such split variables
28
   is almost unusable.
29
 
30
   TODO
31
    - Add code to keep debugging up-to-date after splitting user variable
32
      pseudos.  This can be done by keeping track of all the pseudos used
33
      for the variable and using life analysis information before reload
34
      to determine which one is live and, in case more than one are live,
35
      choose the one with the latest definition.
36
 
37
      Other optimization passes can benefit from the infrastructure too.
38
 
39
    - We may use profile information and ignore infrequent use for the
40
      purpose of web unifying, inserting the compensation code later to
41
      implement full induction variable expansion for loops (currently
42
      we expand only if the induction variable is dead afterward, which
43
      is often the case).  */
44
 
45
#include "config.h"
46
#include "system.h"
47
#include "coretypes.h"
48
#include "tm.h"
49
#include "toplev.h"
50
 
51
#include "rtl.h"
52
#include "hard-reg-set.h"
53
#include "flags.h"
54
#include "obstack.h"
55
#include "basic-block.h"
56
#include "output.h"
57
#include "df.h"
58
#include "function.h"
59
#include "timevar.h"
60
#include "tree-pass.h"
61
 
62
 
63
/* This entry is allocated for each reference in the insn stream.  */
64
struct web_entry
65
{
66
  /* Pointer to the parent in the union/find tree.  */
67
  struct web_entry *pred;
68
  /* Newly assigned register to the entry.  Set only for roots.  */
69
  rtx reg;
70
};
71
 
72
static struct web_entry *unionfind_root (struct web_entry *);
73
static void unionfind_union (struct web_entry *, struct web_entry *);
74
static void union_defs (struct df *, struct ref *, struct web_entry *,
75
                        struct web_entry *);
76
static rtx entry_register (struct web_entry *, struct ref *, char *);
77
static void replace_ref (struct ref *, rtx);
78
 
79
/* Find the root of unionfind tree (the representative of set).  */
80
 
81
static struct web_entry *
82
unionfind_root (struct web_entry *element)
83
{
84
  struct web_entry *element1 = element, *element2;
85
 
86
  while (element->pred)
87
    element = element->pred;
88
  while (element1->pred)
89
    {
90
      element2 = element1->pred;
91
      element1->pred = element;
92
      element1 = element2;
93
    }
94
  return element;
95
}
96
 
97
/* Union sets.  */
98
 
99
static void
100
unionfind_union (struct web_entry *first, struct web_entry *second)
101
{
102
  first = unionfind_root (first);
103
  second = unionfind_root (second);
104
  if (first == second)
105
    return;
106
  second->pred = first;
107
}
108
 
109
/* For each use, all possible defs reaching it must come in the same
110
   register, union them.  */
111
 
112
static void
113
union_defs (struct df *df, struct ref *use, struct web_entry *def_entry,
114
            struct web_entry *use_entry)
115
{
116
  rtx insn = DF_REF_INSN (use);
117
  struct df_link *link = DF_REF_CHAIN (use);
118
  struct df_link *use_link = DF_INSN_USES (df, insn);
119
  struct df_link *def_link = DF_INSN_DEFS (df, insn);
120
  rtx set = single_set (insn);
121
 
122
  /* Some instructions may use match_dup for their operands.  In case the
123
     operands are dead, we will assign them different pseudos, creating
124
     invalid instructions, so union all uses of the same operand for each
125
     insn.  */
126
 
127
  while (use_link)
128
    {
129
      if (use != use_link->ref
130
          && DF_REF_REAL_REG (use) == DF_REF_REAL_REG (use_link->ref))
131
        unionfind_union (use_entry + DF_REF_ID (use),
132
                         use_entry + DF_REF_ID (use_link->ref));
133
      use_link = use_link->next;
134
    }
135
 
136
  /* Recognize trivial noop moves and attempt to keep them as noop.
137
     While most of noop moves should be removed, we still keep some
138
     of them at libcall boundaries and such.  */
139
 
140
  if (set
141
      && SET_SRC (set) == DF_REF_REG (use)
142
      && SET_SRC (set) == SET_DEST (set))
143
    {
144
      while (def_link)
145
        {
146
          if (DF_REF_REAL_REG (use) == DF_REF_REAL_REG (def_link->ref))
147
            unionfind_union (use_entry + DF_REF_ID (use),
148
                             def_entry + DF_REF_ID (def_link->ref));
149
          def_link = def_link->next;
150
        }
151
    }
152
  while (link)
153
    {
154
      unionfind_union (use_entry + DF_REF_ID (use),
155
                       def_entry + DF_REF_ID (link->ref));
156
      link = link->next;
157
    }
158
 
159
  /* A READ_WRITE use requires the corresponding def to be in the same
160
     register.  Find it and union.  */
161
  if (use->flags & DF_REF_READ_WRITE)
162
    {
163
      struct df_link *link = DF_INSN_DEFS (df, DF_REF_INSN (use));
164
 
165
      while (link)
166
        {
167
          if (DF_REF_REAL_REG (link->ref) == DF_REF_REAL_REG (use))
168
            unionfind_union (use_entry + DF_REF_ID (use),
169
                             def_entry + DF_REF_ID (link->ref));
170
          link = link->next;
171
        }
172
    }
173
}
174
 
175
/* Find the corresponding register for the given entry.  */
176
 
177
static rtx
178
entry_register (struct web_entry *entry, struct ref *ref, char *used)
179
{
180
  struct web_entry *root;
181
  rtx reg, newreg;
182
 
183
  /* Find the corresponding web and see if it has been visited.  */
184
  root = unionfind_root (entry);
185
  if (root->reg)
186
    return root->reg;
187
 
188
  /* We are seeing this web for the first time, do the assignment.  */
189
  reg = DF_REF_REAL_REG (ref);
190
 
191
  /* In case the original register is already assigned, generate new one.  */
192
  if (!used[REGNO (reg)])
193
    newreg = reg, used[REGNO (reg)] = 1;
194
  else if (REG_USERVAR_P (reg) && 0/*&& !flag_messy_debugging*/)
195
    {
196
      newreg = reg;
197
      if (dump_file)
198
        fprintf (dump_file,
199
                 "New web forced to keep reg=%i (user variable)\n",
200
                 REGNO (reg));
201
    }
202
  else
203
    {
204
      newreg = gen_reg_rtx (GET_MODE (reg));
205
      REG_USERVAR_P (newreg) = REG_USERVAR_P (reg);
206
      REG_POINTER (newreg) = REG_POINTER (reg);
207
      REG_ATTRS (newreg) = REG_ATTRS (reg);
208
      if (dump_file)
209
        fprintf (dump_file, "Web oldreg=%i newreg=%i\n", REGNO (reg),
210
                 REGNO (newreg));
211
    }
212
 
213
  root->reg = newreg;
214
  return newreg;
215
}
216
 
217
/* Replace the reference by REG.  */
218
 
219
static void
220
replace_ref (struct ref *ref, rtx reg)
221
{
222
  rtx oldreg = DF_REF_REAL_REG (ref);
223
  rtx *loc = DF_REF_REAL_LOC (ref);
224
 
225
  if (oldreg == reg)
226
    return;
227
  if (dump_file)
228
    fprintf (dump_file, "Updating insn %i (%i->%i)\n",
229
             INSN_UID (DF_REF_INSN (ref)), REGNO (oldreg), REGNO (reg));
230
  *loc = reg;
231
}
232
 
233
/* Main entry point.  */
234
 
235
void
236
web_main (void)
237
{
238
  struct df *df;
239
  struct web_entry *def_entry;
240
  struct web_entry *use_entry;
241
  unsigned int i;
242
  int max = max_reg_num ();
243
  char *used;
244
 
245
  df = df_init ();
246
  df_analyze (df, 0, DF_UD_CHAIN | DF_EQUIV_NOTES);
247
 
248
  def_entry = xcalloc (df->n_defs, sizeof (struct web_entry));
249
  use_entry = xcalloc (df->n_uses, sizeof (struct web_entry));
250
  used = xcalloc (max, sizeof (char));
251
 
252
  if (dump_file)
253
    df_dump (df, DF_UD_CHAIN | DF_DU_CHAIN, dump_file);
254
 
255
  /* Produce the web.  */
256
  for (i = 0; i < df->n_uses; i++)
257
    union_defs (df, df->uses[i], def_entry, use_entry);
258
 
259
  /* Update the instruction stream, allocating new registers for split pseudos
260
     in progress.  */
261
  for (i = 0; i < df->n_uses; i++)
262
    replace_ref (df->uses[i], entry_register (use_entry + i, df->uses[i],
263
                                              used));
264
  for (i = 0; i < df->n_defs; i++)
265
    replace_ref (df->defs[i], entry_register (def_entry + i, df->defs[i],
266
                                              used));
267
 
268
  /* Dataflow information is corrupt here, but it can be easily updated
269
     by creating new entries for new registers and updates or calling
270
     df_insns_modify.  */
271
  free (def_entry);
272
  free (use_entry);
273
  free (used);
274
  df_finish (df);
275
}
276
 
277
static bool
278
gate_handle_web (void)
279
{
280
  return (optimize > 0 && flag_web);
281
}
282
 
283
static void
284
rest_of_handle_web (void)
285
{
286
  web_main ();
287
  delete_trivially_dead_insns (get_insns (), max_reg_num ());
288
  cleanup_cfg (CLEANUP_EXPENSIVE);
289
  reg_scan (get_insns (), max_reg_num ());
290
}
291
 
292
struct tree_opt_pass pass_web =
293
{
294
  "web",                                /* name */
295
  gate_handle_web,                      /* gate */
296
  rest_of_handle_web,                   /* execute */
297
  NULL,                                 /* sub */
298
  NULL,                                 /* next */
299
  0,                                    /* static_pass_number */
300
  TV_WEB,                               /* tv_id */
301
  0,                                    /* properties_required */
302
  0,                                    /* properties_provided */
303
  0,                                    /* properties_destroyed */
304
  0,                                    /* todo_flags_start */
305
  TODO_dump_func,                       /* todo_flags_finish */
306
  'Z'                                   /* letter */
307
};
308
 

powered by: WebSVN 2.1.0

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