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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [tree-outof-ssa.c] - Blame information for rev 280

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 280 jeremybenn
/* Convert a program in SSA form into Normal form.
2
   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
3
   Free Software Foundation, Inc.
4
   Contributed by Andrew Macleod <amacleod@redhat.com>
5
 
6
This file is part of GCC.
7
 
8
GCC is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 3, or (at your option)
11
any later version.
12
 
13
GCC is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
GNU General Public License for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with GCC; see the file COPYING3.  If not see
20
<http://www.gnu.org/licenses/>.  */
21
 
22
#include "config.h"
23
#include "system.h"
24
#include "coretypes.h"
25
#include "tm.h"
26
#include "tree.h"
27
#include "ggc.h"
28
#include "basic-block.h"
29
#include "diagnostic.h"
30
#include "bitmap.h"
31
#include "tree-flow.h"
32
#include "timevar.h"
33
#include "tree-dump.h"
34
#include "tree-pass.h"
35
#include "toplev.h"
36
#include "expr.h"
37
#include "ssaexpand.h"
38
 
39
 
40
DEF_VEC_I(source_location);
41
DEF_VEC_ALLOC_I(source_location,heap);
42
 
43
/* Used to hold all the components required to do SSA PHI elimination.
44
   The node and pred/succ list is a simple linear list of nodes and
45
   edges represented as pairs of nodes.
46
 
47
   The predecessor and successor list:  Nodes are entered in pairs, where
48
   [0] ->PRED, [1]->SUCC.  All the even indexes in the array represent
49
   predecessors, all the odd elements are successors.
50
 
51
   Rationale:
52
   When implemented as bitmaps, very large programs SSA->Normal times were
53
   being dominated by clearing the interference graph.
54
 
55
   Typically this list of edges is extremely small since it only includes
56
   PHI results and uses from a single edge which have not coalesced with
57
   each other.  This means that no virtual PHI nodes are included, and
58
   empirical evidence suggests that the number of edges rarely exceed
59
   3, and in a bootstrap of GCC, the maximum size encountered was 7.
60
   This also limits the number of possible nodes that are involved to
61
   rarely more than 6, and in the bootstrap of gcc, the maximum number
62
   of nodes encountered was 12.  */
63
 
64
typedef struct _elim_graph {
65
  /* Size of the elimination vectors.  */
66
  int size;
67
 
68
  /* List of nodes in the elimination graph.  */
69
  VEC(int,heap) *nodes;
70
 
71
  /*  The predecessor and successor edge list.  */
72
  VEC(int,heap) *edge_list;
73
 
74
  /* Source locus on each edge */
75
  VEC(source_location,heap) *edge_locus;
76
 
77
  /* Visited vector.  */
78
  sbitmap visited;
79
 
80
  /* Stack for visited nodes.  */
81
  VEC(int,heap) *stack;
82
 
83
  /* The variable partition map.  */
84
  var_map map;
85
 
86
  /* Edge being eliminated by this graph.  */
87
  edge e;
88
 
89
  /* List of constant copies to emit.  These are pushed on in pairs.  */
90
  VEC(int,heap) *const_dests;
91
  VEC(tree,heap) *const_copies;
92
 
93
  /* Source locations for any constant copies.  */
94
  VEC(source_location,heap) *copy_locus;
95
} *elim_graph;
96
 
97
 
98
/* For an edge E find out a good source location to associate with
99
   instructions inserted on edge E.  If E has an implicit goto set,
100
   use its location.  Otherwise search instructions in predecessors
101
   of E for a location, and use that one.  That makes sense because
102
   we insert on edges for PHI nodes, and effects of PHIs happen on
103
   the end of the predecessor conceptually.  */
104
 
105
static void
106
set_location_for_edge (edge e)
107
{
108
  if (e->goto_locus)
109
    {
110
      set_curr_insn_source_location (e->goto_locus);
111
      set_curr_insn_block (e->goto_block);
112
    }
113
  else
114
    {
115
      basic_block bb = e->src;
116
      gimple_stmt_iterator gsi;
117
 
118
      do
119
        {
120
          for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
121
            {
122
              gimple stmt = gsi_stmt (gsi);
123
              if (is_gimple_debug (stmt))
124
                continue;
125
              if (gimple_has_location (stmt) || gimple_block (stmt))
126
                {
127
                  set_curr_insn_source_location (gimple_location (stmt));
128
                  set_curr_insn_block (gimple_block (stmt));
129
                  return;
130
                }
131
            }
132
          /* Nothing found in this basic block.  Make a half-assed attempt
133
             to continue with another block.  */
134
          if (single_pred_p (bb))
135
            bb = single_pred (bb);
136
          else
137
            bb = e->src;
138
        }
139
      while (bb != e->src);
140
    }
141
}
142
 
143
/* Emit insns to copy SRC into DEST converting SRC if necessary.  As
144
   SRC/DEST might be BLKmode memory locations SIZEEXP is a tree from
145
   which we deduce the size to copy in that case.  */
146
 
147
static inline rtx
148
emit_partition_copy (rtx dest, rtx src, int unsignedsrcp, tree sizeexp)
149
{
150
  rtx seq;
151
 
152
  start_sequence ();
153
 
154
  if (GET_MODE (src) != VOIDmode && GET_MODE (src) != GET_MODE (dest))
155
    src = convert_to_mode (GET_MODE (dest), src, unsignedsrcp);
156
  if (GET_MODE (src) == BLKmode)
157
    {
158
      gcc_assert (GET_MODE (dest) == BLKmode);
159
      emit_block_move (dest, src, expr_size (sizeexp), BLOCK_OP_NORMAL);
160
    }
161
  else
162
    emit_move_insn (dest, src);
163
 
164
  seq = get_insns ();
165
  end_sequence ();
166
 
167
  return seq;
168
}
169
 
170
/* Insert a copy instruction from partition SRC to DEST onto edge E.  */
171
 
172
static void
173
insert_partition_copy_on_edge (edge e, int dest, int src, source_location locus)
174
{
175
  tree var;
176
  rtx seq;
177
  if (dump_file && (dump_flags & TDF_DETAILS))
178
    {
179
      fprintf (dump_file,
180
               "Inserting a partition copy on edge BB%d->BB%d :"
181
               "PART.%d = PART.%d",
182
               e->src->index,
183
               e->dest->index, dest, src);
184
      fprintf (dump_file, "\n");
185
    }
186
 
187
  gcc_assert (SA.partition_to_pseudo[dest]);
188
  gcc_assert (SA.partition_to_pseudo[src]);
189
 
190
  set_location_for_edge (e);
191
  /* If a locus is provided, override the default.  */
192
  if (locus)
193
    set_curr_insn_source_location (locus);
194
 
195
  var = partition_to_var (SA.map, src);
196
  seq = emit_partition_copy (SA.partition_to_pseudo[dest],
197
                             SA.partition_to_pseudo[src],
198
                             TYPE_UNSIGNED (TREE_TYPE (var)),
199
                             var);
200
 
201
  insert_insn_on_edge (seq, e);
202
}
203
 
204
/* Insert a copy instruction from expression SRC to partition DEST
205
   onto edge E.  */
206
 
207
static void
208
insert_value_copy_on_edge (edge e, int dest, tree src, source_location locus)
209
{
210
  rtx seq, x;
211
  enum machine_mode dest_mode, src_mode;
212
  int unsignedp;
213
  tree var;
214
 
215
  if (dump_file && (dump_flags & TDF_DETAILS))
216
    {
217
      fprintf (dump_file,
218
               "Inserting a value copy on edge BB%d->BB%d : PART.%d = ",
219
               e->src->index,
220
               e->dest->index, dest);
221
      print_generic_expr (dump_file, src, TDF_SLIM);
222
      fprintf (dump_file, "\n");
223
    }
224
 
225
  gcc_assert (SA.partition_to_pseudo[dest]);
226
 
227
  set_location_for_edge (e);
228
  /* If a locus is provided, override the default.  */
229
  if (locus)
230
    set_curr_insn_source_location (locus);
231
 
232
  start_sequence ();
233
 
234
  var = SSA_NAME_VAR (partition_to_var (SA.map, dest));
235
  src_mode = TYPE_MODE (TREE_TYPE (src));
236
  dest_mode = promote_decl_mode (var, &unsignedp);
237
  gcc_assert (src_mode == TYPE_MODE (TREE_TYPE (var)));
238
  gcc_assert (dest_mode == GET_MODE (SA.partition_to_pseudo[dest]));
239
 
240
  if (src_mode != dest_mode)
241
    {
242
      x = expand_expr (src, NULL, src_mode, EXPAND_NORMAL);
243
      x = convert_modes (dest_mode, src_mode, x, unsignedp);
244
    }
245
  else if (src_mode == BLKmode)
246
    {
247
      x = SA.partition_to_pseudo[dest];
248
      store_expr (src, x, 0, false);
249
    }
250
  else
251
    x = expand_expr (src, SA.partition_to_pseudo[dest],
252
                     dest_mode, EXPAND_NORMAL);
253
 
254
  if (x != SA.partition_to_pseudo[dest])
255
    emit_move_insn (SA.partition_to_pseudo[dest], x);
256
  seq = get_insns ();
257
  end_sequence ();
258
 
259
  insert_insn_on_edge (seq, e);
260
}
261
 
262
/* Insert a copy instruction from RTL expression SRC to partition DEST
263
   onto edge E.  */
264
 
265
static void
266
insert_rtx_to_part_on_edge (edge e, int dest, rtx src, int unsignedsrcp,
267
                            source_location locus)
268
{
269
  rtx seq;
270
  if (dump_file && (dump_flags & TDF_DETAILS))
271
    {
272
      fprintf (dump_file,
273
               "Inserting a temp copy on edge BB%d->BB%d : PART.%d = ",
274
               e->src->index,
275
               e->dest->index, dest);
276
      print_simple_rtl (dump_file, src);
277
      fprintf (dump_file, "\n");
278
    }
279
 
280
  gcc_assert (SA.partition_to_pseudo[dest]);
281
 
282
  set_location_for_edge (e);
283
  /* If a locus is provided, override the default.  */
284
  if (locus)
285
    set_curr_insn_source_location (locus);
286
 
287
  /* We give the destination as sizeexp in case src/dest are BLKmode
288
     mems.  Usually we give the source.  As we result from SSA names
289
     the left and right size should be the same (and no WITH_SIZE_EXPR
290
     involved), so it doesn't matter.  */
291
  seq = emit_partition_copy (SA.partition_to_pseudo[dest],
292
                             src, unsignedsrcp,
293
                             partition_to_var (SA.map, dest));
294
 
295
  insert_insn_on_edge (seq, e);
296
}
297
 
298
/* Insert a copy instruction from partition SRC to RTL lvalue DEST
299
   onto edge E.  */
300
 
301
static void
302
insert_part_to_rtx_on_edge (edge e, rtx dest, int src, source_location locus)
303
{
304
  tree var;
305
  rtx seq;
306
  if (dump_file && (dump_flags & TDF_DETAILS))
307
    {
308
      fprintf (dump_file,
309
               "Inserting a temp copy on edge BB%d->BB%d : ",
310
               e->src->index,
311
               e->dest->index);
312
      print_simple_rtl (dump_file, dest);
313
      fprintf (dump_file, "= PART.%d\n", src);
314
    }
315
 
316
  gcc_assert (SA.partition_to_pseudo[src]);
317
 
318
  set_location_for_edge (e);
319
  /* If a locus is provided, override the default.  */
320
  if (locus)
321
    set_curr_insn_source_location (locus);
322
 
323
  var = partition_to_var (SA.map, src);
324
  seq = emit_partition_copy (dest,
325
                             SA.partition_to_pseudo[src],
326
                             TYPE_UNSIGNED (TREE_TYPE (var)),
327
                             var);
328
 
329
  insert_insn_on_edge (seq, e);
330
}
331
 
332
 
333
/* Create an elimination graph with SIZE nodes and associated data
334
   structures.  */
335
 
336
static elim_graph
337
new_elim_graph (int size)
338
{
339
  elim_graph g = (elim_graph) xmalloc (sizeof (struct _elim_graph));
340
 
341
  g->nodes = VEC_alloc (int, heap, 30);
342
  g->const_dests = VEC_alloc (int, heap, 20);
343
  g->const_copies = VEC_alloc (tree, heap, 20);
344
  g->copy_locus = VEC_alloc (source_location, heap, 10);
345
  g->edge_list = VEC_alloc (int, heap, 20);
346
  g->edge_locus = VEC_alloc (source_location, heap, 10);
347
  g->stack = VEC_alloc (int, heap, 30);
348
 
349
  g->visited = sbitmap_alloc (size);
350
 
351
  return g;
352
}
353
 
354
 
355
/* Empty elimination graph G.  */
356
 
357
static inline void
358
clear_elim_graph (elim_graph g)
359
{
360
  VEC_truncate (int, g->nodes, 0);
361
  VEC_truncate (int, g->edge_list, 0);
362
  VEC_truncate (source_location, g->edge_locus, 0);
363
}
364
 
365
 
366
/* Delete elimination graph G.  */
367
 
368
static inline void
369
delete_elim_graph (elim_graph g)
370
{
371
  sbitmap_free (g->visited);
372
  VEC_free (int, heap, g->stack);
373
  VEC_free (int, heap, g->edge_list);
374
  VEC_free (tree, heap, g->const_copies);
375
  VEC_free (int, heap, g->const_dests);
376
  VEC_free (int, heap, g->nodes);
377
  VEC_free (source_location, heap, g->copy_locus);
378
  VEC_free (source_location, heap, g->edge_locus);
379
 
380
  free (g);
381
}
382
 
383
 
384
/* Return the number of nodes in graph G.  */
385
 
386
static inline int
387
elim_graph_size (elim_graph g)
388
{
389
  return VEC_length (int, g->nodes);
390
}
391
 
392
 
393
/* Add NODE to graph G, if it doesn't exist already.  */
394
 
395
static inline void
396
elim_graph_add_node (elim_graph g, int node)
397
{
398
  int x;
399
  int t;
400
 
401
  for (x = 0; VEC_iterate (int, g->nodes, x, t); x++)
402
    if (t == node)
403
      return;
404
  VEC_safe_push (int, heap, g->nodes, node);
405
}
406
 
407
 
408
/* Add the edge PRED->SUCC to graph G.  */
409
 
410
static inline void
411
elim_graph_add_edge (elim_graph g, int pred, int succ, source_location locus)
412
{
413
  VEC_safe_push (int, heap, g->edge_list, pred);
414
  VEC_safe_push (int, heap, g->edge_list, succ);
415
  VEC_safe_push (source_location, heap, g->edge_locus, locus);
416
}
417
 
418
 
419
/* Remove an edge from graph G for which NODE is the predecessor, and
420
   return the successor node.  -1 is returned if there is no such edge.  */
421
 
422
static inline int
423
elim_graph_remove_succ_edge (elim_graph g, int node, source_location *locus)
424
{
425
  int y;
426
  unsigned x;
427
  for (x = 0; x < VEC_length (int, g->edge_list); x += 2)
428
    if (VEC_index (int, g->edge_list, x) == node)
429
      {
430
        VEC_replace (int, g->edge_list, x, -1);
431
        y = VEC_index (int, g->edge_list, x + 1);
432
        VEC_replace (int, g->edge_list, x + 1, -1);
433
        *locus = VEC_index (source_location, g->edge_locus, x / 2);
434
        VEC_replace (source_location, g->edge_locus, x / 2, UNKNOWN_LOCATION);
435
        return y;
436
      }
437
  *locus = UNKNOWN_LOCATION;
438
  return -1;
439
}
440
 
441
 
442
/* Find all the nodes in GRAPH which are successors to NODE in the
443
   edge list.  VAR will hold the partition number found.  CODE is the
444
   code fragment executed for every node found.  */
445
 
446
#define FOR_EACH_ELIM_GRAPH_SUCC(GRAPH, NODE, VAR, LOCUS, CODE)         \
447
do {                                                                    \
448
  unsigned x_;                                                          \
449
  int y_;                                                               \
450
  for (x_ = 0; x_ < VEC_length (int, (GRAPH)->edge_list); x_ += 2)       \
451
    {                                                                   \
452
      y_ = VEC_index (int, (GRAPH)->edge_list, x_);                     \
453
      if (y_ != (NODE))                                                 \
454
        continue;                                                       \
455
      (VAR) = VEC_index (int, (GRAPH)->edge_list, x_ + 1);              \
456
      (LOCUS) = VEC_index (source_location, (GRAPH)->edge_locus, x_ / 2); \
457
      CODE;                                                             \
458
    }                                                                   \
459
} while (0)
460
 
461
 
462
/* Find all the nodes which are predecessors of NODE in the edge list for
463
   GRAPH.  VAR will hold the partition number found.  CODE is the
464
   code fragment executed for every node found.  */
465
 
466
#define FOR_EACH_ELIM_GRAPH_PRED(GRAPH, NODE, VAR, LOCUS, CODE)         \
467
do {                                                                    \
468
  unsigned x_;                                                          \
469
  int y_;                                                               \
470
  for (x_ = 0; x_ < VEC_length (int, (GRAPH)->edge_list); x_ += 2)       \
471
    {                                                                   \
472
      y_ = VEC_index (int, (GRAPH)->edge_list, x_ + 1);                 \
473
      if (y_ != (NODE))                                                 \
474
        continue;                                                       \
475
      (VAR) = VEC_index (int, (GRAPH)->edge_list, x_);                  \
476
      (LOCUS) = VEC_index (source_location, (GRAPH)->edge_locus, x_ / 2); \
477
      CODE;                                                             \
478
    }                                                                   \
479
} while (0)
480
 
481
 
482
/* Add T to elimination graph G.  */
483
 
484
static inline void
485
eliminate_name (elim_graph g, int T)
486
{
487
  elim_graph_add_node (g, T);
488
}
489
 
490
 
491
/* Build elimination graph G for basic block BB on incoming PHI edge
492
   G->e.  */
493
 
494
static void
495
eliminate_build (elim_graph g)
496
{
497
  tree Ti;
498
  int p0, pi;
499
  gimple_stmt_iterator gsi;
500
 
501
  clear_elim_graph (g);
502
 
503
  for (gsi = gsi_start_phis (g->e->dest); !gsi_end_p (gsi); gsi_next (&gsi))
504
    {
505
      gimple phi = gsi_stmt (gsi);
506
      source_location locus;
507
 
508
      p0 = var_to_partition (g->map, gimple_phi_result (phi));
509
      /* Ignore results which are not in partitions.  */
510
      if (p0 == NO_PARTITION)
511
        continue;
512
 
513
      Ti = PHI_ARG_DEF (phi, g->e->dest_idx);
514
      locus = gimple_phi_arg_location_from_edge (phi, g->e);
515
 
516
      /* If this argument is a constant, or a SSA_NAME which is being
517
         left in SSA form, just queue a copy to be emitted on this
518
         edge.  */
519
      if (!phi_ssa_name_p (Ti)
520
          || (TREE_CODE (Ti) == SSA_NAME
521
              && var_to_partition (g->map, Ti) == NO_PARTITION))
522
        {
523
          /* Save constant copies until all other copies have been emitted
524
             on this edge.  */
525
          VEC_safe_push (int, heap, g->const_dests, p0);
526
          VEC_safe_push (tree, heap, g->const_copies, Ti);
527
          VEC_safe_push (source_location, heap, g->copy_locus, locus);
528
        }
529
      else
530
        {
531
          pi = var_to_partition (g->map, Ti);
532
          if (p0 != pi)
533
            {
534
              eliminate_name (g, p0);
535
              eliminate_name (g, pi);
536
              elim_graph_add_edge (g, p0, pi, locus);
537
            }
538
        }
539
    }
540
}
541
 
542
 
543
/* Push successors of T onto the elimination stack for G.  */
544
 
545
static void
546
elim_forward (elim_graph g, int T)
547
{
548
  int S;
549
  source_location locus;
550
 
551
  SET_BIT (g->visited, T);
552
  FOR_EACH_ELIM_GRAPH_SUCC (g, T, S, locus,
553
    {
554
      if (!TEST_BIT (g->visited, S))
555
        elim_forward (g, S);
556
    });
557
  VEC_safe_push (int, heap, g->stack, T);
558
}
559
 
560
 
561
/* Return 1 if there unvisited predecessors of T in graph G.  */
562
 
563
static int
564
elim_unvisited_predecessor (elim_graph g, int T)
565
{
566
  int P;
567
  source_location locus;
568
 
569
  FOR_EACH_ELIM_GRAPH_PRED (g, T, P, locus,
570
    {
571
      if (!TEST_BIT (g->visited, P))
572
        return 1;
573
    });
574
  return 0;
575
}
576
 
577
/* Process predecessors first, and insert a copy.  */
578
 
579
static void
580
elim_backward (elim_graph g, int T)
581
{
582
  int P;
583
  source_location locus;
584
 
585
  SET_BIT (g->visited, T);
586
  FOR_EACH_ELIM_GRAPH_PRED (g, T, P, locus,
587
    {
588
      if (!TEST_BIT (g->visited, P))
589
        {
590
          elim_backward (g, P);
591
          insert_partition_copy_on_edge (g->e, P, T, locus);
592
        }
593
    });
594
}
595
 
596
/* Allocate a new pseudo register usable for storing values sitting
597
   in NAME (a decl or SSA name), i.e. with matching mode and attributes.  */
598
 
599
static rtx
600
get_temp_reg (tree name)
601
{
602
  tree var = TREE_CODE (name) == SSA_NAME ? SSA_NAME_VAR (name) : name;
603
  tree type = TREE_TYPE (var);
604
  int unsignedp;
605
  enum machine_mode reg_mode = promote_decl_mode (var, &unsignedp);
606
  rtx x = gen_reg_rtx (reg_mode);
607
  if (POINTER_TYPE_P (type))
608
    mark_reg_pointer (x, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (var))));
609
  return x;
610
}
611
 
612
/* Insert required copies for T in graph G.  Check for a strongly connected
613
   region, and create a temporary to break the cycle if one is found.  */
614
 
615
static void
616
elim_create (elim_graph g, int T)
617
{
618
  int P, S;
619
  source_location locus;
620
 
621
  if (elim_unvisited_predecessor (g, T))
622
    {
623
      tree var = partition_to_var (g->map, T);
624
      rtx U = get_temp_reg (var);
625
      int unsignedsrcp = TYPE_UNSIGNED (TREE_TYPE (var));
626
 
627
      insert_part_to_rtx_on_edge (g->e, U, T, UNKNOWN_LOCATION);
628
      FOR_EACH_ELIM_GRAPH_PRED (g, T, P, locus,
629
        {
630
          if (!TEST_BIT (g->visited, P))
631
            {
632
              elim_backward (g, P);
633
              insert_rtx_to_part_on_edge (g->e, P, U, unsignedsrcp, locus);
634
            }
635
        });
636
    }
637
  else
638
    {
639
      S = elim_graph_remove_succ_edge (g, T, &locus);
640
      if (S != -1)
641
        {
642
          SET_BIT (g->visited, T);
643
          insert_partition_copy_on_edge (g->e, T, S, locus);
644
        }
645
    }
646
}
647
 
648
 
649
/* Eliminate all the phi nodes on edge E in graph G.  */
650
 
651
static void
652
eliminate_phi (edge e, elim_graph g)
653
{
654
  int x;
655
 
656
  gcc_assert (VEC_length (tree, g->const_copies) == 0);
657
  gcc_assert (VEC_length (source_location, g->copy_locus) == 0);
658
 
659
  /* Abnormal edges already have everything coalesced.  */
660
  if (e->flags & EDGE_ABNORMAL)
661
    return;
662
 
663
  g->e = e;
664
 
665
  eliminate_build (g);
666
 
667
  if (elim_graph_size (g) != 0)
668
    {
669
      int part;
670
 
671
      sbitmap_zero (g->visited);
672
      VEC_truncate (int, g->stack, 0);
673
 
674
      for (x = 0; VEC_iterate (int, g->nodes, x, part); x++)
675
        {
676
          if (!TEST_BIT (g->visited, part))
677
            elim_forward (g, part);
678
        }
679
 
680
      sbitmap_zero (g->visited);
681
      while (VEC_length (int, g->stack) > 0)
682
        {
683
          x = VEC_pop (int, g->stack);
684
          if (!TEST_BIT (g->visited, x))
685
            elim_create (g, x);
686
        }
687
    }
688
 
689
  /* If there are any pending constant copies, issue them now.  */
690
  while (VEC_length (tree, g->const_copies) > 0)
691
    {
692
      int dest;
693
      tree src;
694
      source_location locus;
695
 
696
      src = VEC_pop (tree, g->const_copies);
697
      dest = VEC_pop (int, g->const_dests);
698
      locus = VEC_pop (source_location, g->copy_locus);
699
      insert_value_copy_on_edge (e, dest, src, locus);
700
    }
701
}
702
 
703
 
704
/* Remove each argument from PHI.  If an arg was the last use of an SSA_NAME,
705
   check to see if this allows another PHI node to be removed.  */
706
 
707
static void
708
remove_gimple_phi_args (gimple phi)
709
{
710
  use_operand_p arg_p;
711
  ssa_op_iter iter;
712
 
713
  if (dump_file && (dump_flags & TDF_DETAILS))
714
    {
715
      fprintf (dump_file, "Removing Dead PHI definition: ");
716
      print_gimple_stmt (dump_file, phi, 0, TDF_SLIM);
717
    }
718
 
719
  FOR_EACH_PHI_ARG (arg_p, phi, iter, SSA_OP_USE)
720
    {
721
      tree arg = USE_FROM_PTR (arg_p);
722
      if (TREE_CODE (arg) == SSA_NAME)
723
        {
724
          /* Remove the reference to the existing argument.  */
725
          SET_USE (arg_p, NULL_TREE);
726
          if (has_zero_uses (arg))
727
            {
728
              gimple stmt;
729
              gimple_stmt_iterator gsi;
730
 
731
              stmt = SSA_NAME_DEF_STMT (arg);
732
 
733
              /* Also remove the def if it is a PHI node.  */
734
              if (gimple_code (stmt) == GIMPLE_PHI)
735
                {
736
                  remove_gimple_phi_args (stmt);
737
                  gsi = gsi_for_stmt (stmt);
738
                  remove_phi_node (&gsi, true);
739
                }
740
 
741
            }
742
        }
743
    }
744
}
745
 
746
/* Remove any PHI node which is a virtual PHI, or a PHI with no uses.  */
747
 
748
static void
749
eliminate_useless_phis (void)
750
{
751
  basic_block bb;
752
  gimple_stmt_iterator gsi;
753
  tree result;
754
 
755
  FOR_EACH_BB (bb)
756
    {
757
      for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); )
758
        {
759
          gimple phi = gsi_stmt (gsi);
760
          result = gimple_phi_result (phi);
761
          if (!is_gimple_reg (SSA_NAME_VAR (result)))
762
            {
763
#ifdef ENABLE_CHECKING
764
              size_t i;
765
              /* There should be no arguments which are not virtual, or the
766
                 results will be incorrect.  */
767
              for (i = 0; i < gimple_phi_num_args (phi); i++)
768
                {
769
                  tree arg = PHI_ARG_DEF (phi, i);
770
                  if (TREE_CODE (arg) == SSA_NAME
771
                      && is_gimple_reg (SSA_NAME_VAR (arg)))
772
                    {
773
                      fprintf (stderr, "Argument of PHI is not virtual (");
774
                      print_generic_expr (stderr, arg, TDF_SLIM);
775
                      fprintf (stderr, "), but the result is :");
776
                      print_gimple_stmt (stderr, phi, 0, TDF_SLIM);
777
                      internal_error ("SSA corruption");
778
                    }
779
                }
780
#endif
781
              remove_phi_node (&gsi, true);
782
            }
783
          else
784
            {
785
              /* Also remove real PHIs with no uses.  */
786
              if (has_zero_uses (result))
787
                {
788
                  remove_gimple_phi_args (phi);
789
                  remove_phi_node (&gsi, true);
790
                }
791
              else
792
                gsi_next (&gsi);
793
            }
794
        }
795
    }
796
}
797
 
798
 
799
/* This function will rewrite the current program using the variable mapping
800
   found in MAP.  If the replacement vector VALUES is provided, any
801
   occurrences of partitions with non-null entries in the vector will be
802
   replaced with the expression in the vector instead of its mapped
803
   variable.  */
804
 
805
static void
806
rewrite_trees (var_map map ATTRIBUTE_UNUSED)
807
{
808
#ifdef ENABLE_CHECKING
809
  basic_block bb;
810
  /* Search for PHIs where the destination has no partition, but one
811
     or more arguments has a partition.  This should not happen and can
812
     create incorrect code.  */
813
  FOR_EACH_BB (bb)
814
    {
815
      gimple_stmt_iterator gsi;
816
      for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
817
        {
818
          gimple phi = gsi_stmt (gsi);
819
          tree T0 = var_to_partition_to_var (map, gimple_phi_result (phi));
820
          if (T0 == NULL_TREE)
821
            {
822
              size_t i;
823
              for (i = 0; i < gimple_phi_num_args (phi); i++)
824
                {
825
                  tree arg = PHI_ARG_DEF (phi, i);
826
 
827
                  if (TREE_CODE (arg) == SSA_NAME
828
                      && var_to_partition (map, arg) != NO_PARTITION)
829
                    {
830
                      fprintf (stderr, "Argument of PHI is in a partition :(");
831
                      print_generic_expr (stderr, arg, TDF_SLIM);
832
                      fprintf (stderr, "), but the result is not :");
833
                      print_gimple_stmt (stderr, phi, 0, TDF_SLIM);
834
                      internal_error ("SSA corruption");
835
                    }
836
                }
837
            }
838
        }
839
    }
840
#endif
841
}
842
 
843
/* Given the out-of-ssa info object SA (with prepared partitions)
844
   eliminate all phi nodes in all basic blocks.  Afterwards no
845
   basic block will have phi nodes anymore and there are possibly
846
   some RTL instructions inserted on edges.  */
847
 
848
void
849
expand_phi_nodes (struct ssaexpand *sa)
850
{
851
  basic_block bb;
852
  elim_graph g = new_elim_graph (sa->map->num_partitions);
853
  g->map = sa->map;
854
 
855
  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb, EXIT_BLOCK_PTR, next_bb)
856
    if (!gimple_seq_empty_p (phi_nodes (bb)))
857
      {
858
        edge e;
859
        edge_iterator ei;
860
        FOR_EACH_EDGE (e, ei, bb->preds)
861
          eliminate_phi (e, g);
862
        set_phi_nodes (bb, NULL);
863
        /* We can't redirect EH edges in RTL land, so we need to do this
864
           here.  Redirection happens only when splitting is necessary,
865
           which it is only for critical edges, normally.  For EH edges
866
           it might also be necessary when the successor has more than
867
           one predecessor.  In that case the edge is either required to
868
           be fallthru (which EH edges aren't), or the predecessor needs
869
           to end with a jump (which again, isn't the case with EH edges).
870
           Hence, split all EH edges on which we inserted instructions
871
           and whose successor has multiple predecessors.  */
872
        for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
873
          {
874
            if (e->insns.r && (e->flags & EDGE_EH)
875
                && !single_pred_p (e->dest))
876
              {
877
                rtx insns = e->insns.r;
878
                basic_block bb;
879
                e->insns.r = NULL_RTX;
880
                bb = split_edge (e);
881
                single_pred_edge (bb)->insns.r = insns;
882
              }
883
            else
884
              ei_next (&ei);
885
          }
886
      }
887
 
888
  delete_elim_graph (g);
889
}
890
 
891
 
892
/* Remove the ssa-names in the current function and translate them into normal
893
   compiler variables.  PERFORM_TER is true if Temporary Expression Replacement
894
   should also be used.  */
895
 
896
static void
897
remove_ssa_form (bool perform_ter, struct ssaexpand *sa)
898
{
899
  bitmap values = NULL;
900
  var_map map;
901
  unsigned i;
902
 
903
  map = coalesce_ssa_name ();
904
 
905
  /* Return to viewing the variable list as just all reference variables after
906
     coalescing has been performed.  */
907
  partition_view_normal (map, false);
908
 
909
  if (dump_file && (dump_flags & TDF_DETAILS))
910
    {
911
      fprintf (dump_file, "After Coalescing:\n");
912
      dump_var_map (dump_file, map);
913
    }
914
 
915
  if (perform_ter)
916
    {
917
      values = find_replaceable_exprs (map);
918
      if (values && dump_file && (dump_flags & TDF_DETAILS))
919
        dump_replaceable_exprs (dump_file, values);
920
    }
921
 
922
  rewrite_trees (map);
923
 
924
  sa->map = map;
925
  sa->values = values;
926
  sa->partition_has_default_def = BITMAP_ALLOC (NULL);
927
  for (i = 1; i < num_ssa_names; i++)
928
    {
929
      tree t = ssa_name (i);
930
      if (t && SSA_NAME_IS_DEFAULT_DEF (t))
931
        {
932
          int p = var_to_partition (map, t);
933
          if (p != NO_PARTITION)
934
            bitmap_set_bit (sa->partition_has_default_def, p);
935
        }
936
    }
937
}
938
 
939
 
940
/* If not already done so for basic block BB, assign increasing uids
941
   to each of its instructions.  */
942
 
943
static void
944
maybe_renumber_stmts_bb (basic_block bb)
945
{
946
  unsigned i = 0;
947
  gimple_stmt_iterator gsi;
948
 
949
  if (!bb->aux)
950
    return;
951
  bb->aux = NULL;
952
  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
953
    {
954
      gimple stmt = gsi_stmt (gsi);
955
      gimple_set_uid (stmt, i);
956
      i++;
957
    }
958
}
959
 
960
 
961
/* Return true if we can determine that the SSA_NAMEs RESULT (a result
962
   of a PHI node) and ARG (one of its arguments) conflict.  Return false
963
   otherwise, also when we simply aren't sure.  */
964
 
965
static bool
966
trivially_conflicts_p (basic_block bb, tree result, tree arg)
967
{
968
  use_operand_p use;
969
  imm_use_iterator imm_iter;
970
  gimple defa = SSA_NAME_DEF_STMT (arg);
971
 
972
  /* If ARG isn't defined in the same block it's too complicated for
973
     our little mind.  */
974
  if (gimple_bb (defa) != bb)
975
    return false;
976
 
977
  FOR_EACH_IMM_USE_FAST (use, imm_iter, result)
978
    {
979
      gimple use_stmt = USE_STMT (use);
980
      if (is_gimple_debug (use_stmt))
981
        continue;
982
      /* Now, if there's a use of RESULT that lies outside this basic block,
983
         then there surely is a conflict with ARG.  */
984
      if (gimple_bb (use_stmt) != bb)
985
        return true;
986
      if (gimple_code (use_stmt) == GIMPLE_PHI)
987
        continue;
988
      /* The use now is in a real stmt of BB, so if ARG was defined
989
         in a PHI node (like RESULT) both conflict.  */
990
      if (gimple_code (defa) == GIMPLE_PHI)
991
        return true;
992
      maybe_renumber_stmts_bb (bb);
993
      /* If the use of RESULT occurs after the definition of ARG,
994
         the two conflict too.  */
995
      if (gimple_uid (defa) < gimple_uid (use_stmt))
996
        return true;
997
    }
998
 
999
  return false;
1000
}
1001
 
1002
 
1003
/* Search every PHI node for arguments associated with backedges which
1004
   we can trivially determine will need a copy (the argument is either
1005
   not an SSA_NAME or the argument has a different underlying variable
1006
   than the PHI result).
1007
 
1008
   Insert a copy from the PHI argument to a new destination at the
1009
   end of the block with the backedge to the top of the loop.  Update
1010
   the PHI argument to reference this new destination.  */
1011
 
1012
static void
1013
insert_backedge_copies (void)
1014
{
1015
  basic_block bb;
1016
  gimple_stmt_iterator gsi;
1017
 
1018
  FOR_EACH_BB (bb)
1019
    {
1020
      /* Mark block as possibly needing calculation of UIDs.  */
1021
      bb->aux = &bb->aux;
1022
 
1023
      for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1024
        {
1025
          gimple phi = gsi_stmt (gsi);
1026
          tree result = gimple_phi_result (phi);
1027
          tree result_var;
1028
          size_t i;
1029
 
1030
          if (!is_gimple_reg (result))
1031
            continue;
1032
 
1033
          result_var = SSA_NAME_VAR (result);
1034
          for (i = 0; i < gimple_phi_num_args (phi); i++)
1035
            {
1036
              tree arg = gimple_phi_arg_def (phi, i);
1037
              edge e = gimple_phi_arg_edge (phi, i);
1038
 
1039
              /* If the argument is not an SSA_NAME, then we will need a
1040
                 constant initialization.  If the argument is an SSA_NAME with
1041
                 a different underlying variable then a copy statement will be
1042
                 needed.  */
1043
              if ((e->flags & EDGE_DFS_BACK)
1044
                  && (TREE_CODE (arg) != SSA_NAME
1045
                      || SSA_NAME_VAR (arg) != result_var
1046
                      || trivially_conflicts_p (bb, result, arg)))
1047
                {
1048
                  tree name;
1049
                  gimple stmt, last = NULL;
1050
                  gimple_stmt_iterator gsi2;
1051
 
1052
                  gsi2 = gsi_last_bb (gimple_phi_arg_edge (phi, i)->src);
1053
                  if (!gsi_end_p (gsi2))
1054
                    last = gsi_stmt (gsi2);
1055
 
1056
                  /* In theory the only way we ought to get back to the
1057
                     start of a loop should be with a COND_EXPR or GOTO_EXPR.
1058
                     However, better safe than sorry.
1059
                     If the block ends with a control statement or
1060
                     something that might throw, then we have to
1061
                     insert this assignment before the last
1062
                     statement.  Else insert it after the last statement.  */
1063
                  if (last && stmt_ends_bb_p (last))
1064
                    {
1065
                      /* If the last statement in the block is the definition
1066
                         site of the PHI argument, then we can't insert
1067
                         anything after it.  */
1068
                      if (TREE_CODE (arg) == SSA_NAME
1069
                          && SSA_NAME_DEF_STMT (arg) == last)
1070
                        continue;
1071
                    }
1072
 
1073
                  /* Create a new instance of the underlying variable of the
1074
                     PHI result.  */
1075
                  stmt = gimple_build_assign (result_var,
1076
                                              gimple_phi_arg_def (phi, i));
1077
                  name = make_ssa_name (result_var, stmt);
1078
                  gimple_assign_set_lhs (stmt, name);
1079
 
1080
                  /* copy location if present.  */
1081
                  if (gimple_phi_arg_has_location (phi, i))
1082
                    gimple_set_location (stmt,
1083
                                         gimple_phi_arg_location (phi, i));
1084
 
1085
                  /* Insert the new statement into the block and update
1086
                     the PHI node.  */
1087
                  if (last && stmt_ends_bb_p (last))
1088
                    gsi_insert_before (&gsi2, stmt, GSI_NEW_STMT);
1089
                  else
1090
                    gsi_insert_after (&gsi2, stmt, GSI_NEW_STMT);
1091
                  SET_PHI_ARG_DEF (phi, i, name);
1092
                }
1093
            }
1094
        }
1095
 
1096
      /* Unmark this block again.  */
1097
      bb->aux = NULL;
1098
    }
1099
}
1100
 
1101
/* Free all memory associated with going out of SSA form.  SA is
1102
   the outof-SSA info object.  */
1103
 
1104
void
1105
finish_out_of_ssa (struct ssaexpand *sa)
1106
{
1107
  free (sa->partition_to_pseudo);
1108
  if (sa->values)
1109
    BITMAP_FREE (sa->values);
1110
  delete_var_map (sa->map);
1111
  BITMAP_FREE (sa->partition_has_default_def);
1112
  memset (sa, 0, sizeof *sa);
1113
}
1114
 
1115
/* Take the current function out of SSA form, translating PHIs as described in
1116
   R. Morgan, ``Building an Optimizing Compiler'',
1117
   Butterworth-Heinemann, Boston, MA, 1998. pp 176-186.  */
1118
 
1119
unsigned int
1120
rewrite_out_of_ssa (struct ssaexpand *sa)
1121
{
1122
  /* If elimination of a PHI requires inserting a copy on a backedge,
1123
     then we will have to split the backedge which has numerous
1124
     undesirable performance effects.
1125
 
1126
     A significant number of such cases can be handled here by inserting
1127
     copies into the loop itself.  */
1128
  insert_backedge_copies ();
1129
 
1130
 
1131
  /* Eliminate PHIs which are of no use, such as virtual or dead phis.  */
1132
  eliminate_useless_phis ();
1133
 
1134
  if (dump_file && (dump_flags & TDF_DETAILS))
1135
    gimple_dump_cfg (dump_file, dump_flags & ~TDF_DETAILS);
1136
 
1137
  remove_ssa_form (flag_tree_ter, sa);
1138
 
1139
  if (dump_file && (dump_flags & TDF_DETAILS))
1140
    gimple_dump_cfg (dump_file, dump_flags & ~TDF_DETAILS);
1141
 
1142
  return 0;
1143
}

powered by: WebSVN 2.1.0

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