00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "config.h"
00033 #include "system.h"
00034
00035 #include "rtl.h"
00036 #include "expr.h"
00037 #include "varray.h"
00038 #include "partition.h"
00039 #include "sbitmap.h"
00040 #include "hashtab.h"
00041 #include "regs.h"
00042 #include "hard-reg-set.h"
00043 #include "flags.h"
00044 #include "function.h"
00045 #include "real.h"
00046 #include "insn-config.h"
00047 #include "recog.h"
00048 #include "basic-block.h"
00049 #include "output.h"
00050 #include "ssa.h"
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 static int conservative_reg_partition;
00088
00089
00090 int in_ssa_form = 0;
00091
00092
00093 varray_type ssa_definition;
00094
00095
00096
00097 varray_type ssa_rename_from;
00098
00099
00100
00101
00102
00103
00104 htab_t ssa_rename_from_ht;
00105
00106
00107
00108 static rtx *ssa_rename_to_pseudo;
00109
00110
00111
00112 static rtx ssa_rename_to_hard[FIRST_PSEUDO_REGISTER][NUM_MACHINE_MODES];
00113
00114
00115
00116
00117 typedef struct {
00118 unsigned int reg;
00119 rtx original;
00120 } ssa_rename_from_pair;
00121
00122 struct ssa_rename_from_hash_table_data {
00123 sbitmap canonical_elements;
00124 partition reg_partition;
00125 };
00126
00127 static rtx gen_sequence
00128 PARAMS ((void));
00129 static void ssa_rename_from_initialize
00130 PARAMS ((void));
00131 static rtx ssa_rename_from_lookup
00132 PARAMS ((int reg));
00133 static unsigned int original_register
00134 PARAMS ((unsigned int regno));
00135 static void ssa_rename_from_insert
00136 PARAMS ((unsigned int reg, rtx r));
00137 static void ssa_rename_from_free
00138 PARAMS ((void));
00139 typedef int (*srf_trav) PARAMS ((int regno, rtx r, sbitmap canonical_elements, partition reg_partition));
00140 static void ssa_rename_from_traverse
00141 PARAMS ((htab_trav callback_function, sbitmap canonical_elements, partition reg_partition));
00142 void ssa_rename_from_print
00143 PARAMS ((void));
00144 static int ssa_rename_from_print_1
00145 PARAMS ((void **slot, void *data));
00146 static hashval_t ssa_rename_from_hash_function
00147 PARAMS ((const void * srfp));
00148 static int ssa_rename_from_equal
00149 PARAMS ((const void *srfp1, const void *srfp2));
00150 static void ssa_rename_from_delete
00151 PARAMS ((void *srfp));
00152
00153 static rtx ssa_rename_to_lookup
00154 PARAMS ((rtx reg));
00155 static void ssa_rename_to_insert
00156 PARAMS ((rtx reg, rtx r));
00157
00158
00159 static unsigned int ssa_max_reg_num;
00160
00161
00162
00163 struct rename_context;
00164
00165 static inline rtx * phi_alternative
00166 PARAMS ((rtx, int));
00167 static void compute_dominance_frontiers_1
00168 PARAMS ((sbitmap *frontiers, dominance_info idom, int bb, sbitmap done));
00169 static void find_evaluations_1
00170 PARAMS ((rtx dest, rtx set, void *data));
00171 static void find_evaluations
00172 PARAMS ((sbitmap *evals, int nregs));
00173 static void compute_iterated_dominance_frontiers
00174 PARAMS ((sbitmap *idfs, sbitmap *frontiers, sbitmap *evals, int nregs));
00175 static void insert_phi_node
00176 PARAMS ((int regno, int b));
00177 static void insert_phi_nodes
00178 PARAMS ((sbitmap *idfs, sbitmap *evals, int nregs));
00179 static void create_delayed_rename
00180 PARAMS ((struct rename_context *, rtx *));
00181 static void apply_delayed_renames
00182 PARAMS ((struct rename_context *));
00183 static int rename_insn_1
00184 PARAMS ((rtx *ptr, void *data));
00185 static void rename_block
00186 PARAMS ((int b, dominance_info dom));
00187 static void rename_registers
00188 PARAMS ((int nregs, dominance_info idom));
00189
00190 static inline int ephi_add_node
00191 PARAMS ((rtx reg, rtx *nodes, int *n_nodes));
00192 static int * ephi_forward
00193 PARAMS ((int t, sbitmap visited, sbitmap *succ, int *tstack));
00194 static void ephi_backward
00195 PARAMS ((int t, sbitmap visited, sbitmap *pred, rtx *nodes));
00196 static void ephi_create
00197 PARAMS ((int t, sbitmap visited, sbitmap *pred, sbitmap *succ, rtx *nodes));
00198 static void eliminate_phi
00199 PARAMS ((edge e, partition reg_partition));
00200 static int make_regs_equivalent_over_bad_edges
00201 PARAMS ((int bb, partition reg_partition));
00202
00203
00204
00205 static int make_equivalent_phi_alternatives_equivalent
00206 PARAMS ((int bb, partition reg_partition));
00207 static partition compute_conservative_reg_partition
00208 PARAMS ((void));
00209 static int record_canonical_element_1
00210 PARAMS ((void **srfp, void *data));
00211 static int check_hard_regs_in_partition
00212 PARAMS ((partition reg_partition));
00213 static int rename_equivalent_regs_in_insn
00214 PARAMS ((rtx *ptr, void *data));
00215
00216
00217 static int coalesce_if_unconflicting
00218 PARAMS ((partition p, conflict_graph conflicts, int reg1, int reg2));
00219 static int coalesce_regs_in_copies
00220 PARAMS ((basic_block bb, partition p, conflict_graph conflicts));
00221 static int coalesce_reg_in_phi
00222 PARAMS ((rtx, int dest_regno, int src_regno, void *data));
00223 static int coalesce_regs_in_successor_phi_nodes
00224 PARAMS ((basic_block bb, partition p, conflict_graph conflicts));
00225 static partition compute_coalesced_reg_partition
00226 PARAMS ((void));
00227 static int mark_reg_in_phi
00228 PARAMS ((rtx *ptr, void *data));
00229 static void mark_phi_and_copy_regs
00230 PARAMS ((regset phi_set));
00231
00232 static int rename_equivalent_regs_in_insn
00233 PARAMS ((rtx *ptr, void *data));
00234 static void rename_equivalent_regs
00235 PARAMS ((partition reg_partition));
00236
00237
00238 static int conflicting_hard_regs_p
00239 PARAMS ((int reg1, int reg2));
00240
00241
00242
00243
00244
00245 static rtx
00246 ssa_rename_to_lookup (reg)
00247 rtx reg;
00248 {
00249 if (!HARD_REGISTER_P (reg))
00250 return ssa_rename_to_pseudo[REGNO (reg) - FIRST_PSEUDO_REGISTER];
00251 else
00252 return ssa_rename_to_hard[REGNO (reg)][GET_MODE (reg)];
00253 }
00254
00255
00256
00257 static void
00258 ssa_rename_to_insert(reg, r)
00259 rtx reg;
00260 rtx r;
00261 {
00262 if (!HARD_REGISTER_P (reg))
00263 ssa_rename_to_pseudo[REGNO (reg) - FIRST_PSEUDO_REGISTER] = r;
00264 else
00265 ssa_rename_to_hard[REGNO (reg)][GET_MODE (reg)] = r;
00266 }
00267
00268
00269
00270 static void
00271 ssa_rename_from_initialize ()
00272 {
00273
00274 ssa_rename_from_ht = htab_create (64,
00275 &ssa_rename_from_hash_function,
00276 &ssa_rename_from_equal,
00277 &ssa_rename_from_delete);
00278 }
00279
00280
00281
00282
00283 static rtx
00284 ssa_rename_from_lookup (reg)
00285 int reg;
00286 {
00287 ssa_rename_from_pair srfp;
00288 ssa_rename_from_pair *answer;
00289 srfp.reg = reg;
00290 srfp.original = NULL_RTX;
00291 answer = (ssa_rename_from_pair *)
00292 htab_find_with_hash (ssa_rename_from_ht, (void *) &srfp, reg);
00293 return (answer == 0 ? NULL_RTX : answer->original);
00294 }
00295
00296
00297
00298
00299
00300 static unsigned int
00301 original_register (regno)
00302 unsigned int regno;
00303 {
00304 rtx original_rtx = ssa_rename_from_lookup (regno);
00305 return original_rtx != NULL_RTX ? REGNO (original_rtx) : regno;
00306 }
00307
00308
00309
00310 static void
00311 ssa_rename_from_insert (reg, r)
00312 unsigned int reg;
00313 rtx r;
00314 {
00315 void **slot;
00316 ssa_rename_from_pair *srfp = xmalloc (sizeof (ssa_rename_from_pair));
00317 srfp->reg = reg;
00318 srfp->original = r;
00319 slot = htab_find_slot_with_hash (ssa_rename_from_ht, (const void *) srfp,
00320 reg, INSERT);
00321 if (*slot != 0)
00322 free ((void *) *slot);
00323 *slot = srfp;
00324 }
00325
00326
00327
00328
00329
00330 static void
00331 ssa_rename_from_traverse (callback_function,
00332 canonical_elements, reg_partition)
00333 htab_trav callback_function;
00334 sbitmap canonical_elements;
00335 partition reg_partition;
00336 {
00337 struct ssa_rename_from_hash_table_data srfhd;
00338 srfhd.canonical_elements = canonical_elements;
00339 srfhd.reg_partition = reg_partition;
00340 htab_traverse (ssa_rename_from_ht, callback_function, (void *) &srfhd);
00341 }
00342
00343
00344
00345 static void
00346 ssa_rename_from_free ()
00347 {
00348 htab_delete (ssa_rename_from_ht);
00349 }
00350
00351
00352
00353
00354 void
00355 ssa_rename_from_print ()
00356 {
00357 printf ("ssa_rename_from's hash table contents:\n");
00358 htab_traverse (ssa_rename_from_ht, &ssa_rename_from_print_1, NULL);
00359 }
00360
00361
00362
00363
00364 static int
00365 ssa_rename_from_print_1 (slot, data)
00366 void **slot;
00367 void *data ATTRIBUTE_UNUSED;
00368 {
00369 ssa_rename_from_pair * p = *slot;
00370 printf ("ssa_rename_from maps pseudo %i to original %i.\n",
00371 p->reg, REGNO (p->original));
00372 return 1;
00373 }
00374
00375
00376
00377 static hashval_t
00378 ssa_rename_from_hash_function (srfp)
00379 const void *srfp;
00380 {
00381 return ((const ssa_rename_from_pair *) srfp)->reg;
00382 }
00383
00384
00385
00386 static int
00387 ssa_rename_from_equal (srfp1, srfp2)
00388 const void *srfp1;
00389 const void *srfp2;
00390 {
00391 return ssa_rename_from_hash_function (srfp1) ==
00392 ssa_rename_from_hash_function (srfp2);
00393 }
00394
00395
00396
00397 static void
00398 ssa_rename_from_delete (srfp)
00399 void *srfp;
00400 {
00401 free (srfp);
00402 }
00403
00404
00405
00406
00407 static inline rtx *
00408 phi_alternative (set, c)
00409 rtx set;
00410 int c;
00411 {
00412 rtvec phi_vec = XVEC (SET_SRC (set), 0);
00413 int v;
00414
00415 for (v = GET_NUM_ELEM (phi_vec) - 2; v >= 0; v -= 2)
00416 if (INTVAL (RTVEC_ELT (phi_vec, v + 1)) == c)
00417 return &RTVEC_ELT (phi_vec, v);
00418
00419 return NULL;
00420 }
00421
00422
00423
00424
00425
00426 int
00427 remove_phi_alternative (set, block)
00428 rtx set;
00429 basic_block block;
00430 {
00431 rtvec phi_vec = XVEC (SET_SRC (set), 0);
00432 int num_elem = GET_NUM_ELEM (phi_vec);
00433 int v, c;
00434
00435 c = block->index;
00436 for (v = num_elem - 2; v >= 0; v -= 2)
00437 if (INTVAL (RTVEC_ELT (phi_vec, v + 1)) == c)
00438 {
00439 if (v < num_elem - 2)
00440 {
00441 RTVEC_ELT (phi_vec, v) = RTVEC_ELT (phi_vec, num_elem - 2);
00442 RTVEC_ELT (phi_vec, v + 1) = RTVEC_ELT (phi_vec, num_elem - 1);
00443 }
00444 PUT_NUM_ELEM (phi_vec, num_elem - 2);
00445 return 1;
00446 }
00447
00448 return 0;
00449 }
00450
00451
00452
00453
00454
00455
00456 static sbitmap *fe_evals;
00457 static int fe_current_bb;
00458
00459 static void
00460 find_evaluations_1 (dest, set, data)
00461 rtx dest;
00462 rtx set ATTRIBUTE_UNUSED;
00463 void *data ATTRIBUTE_UNUSED;
00464 {
00465 if (GET_CODE (dest) == REG
00466 && CONVERT_REGISTER_TO_SSA_P (REGNO (dest)))
00467 SET_BIT (fe_evals[REGNO (dest)], fe_current_bb);
00468 }
00469
00470 static void
00471 find_evaluations (evals, nregs)
00472 sbitmap *evals;
00473 int nregs;
00474 {
00475 basic_block bb;
00476
00477 sbitmap_vector_zero (evals, nregs);
00478 fe_evals = evals;
00479
00480 FOR_EACH_BB_REVERSE (bb)
00481 {
00482 rtx p, last;
00483
00484 fe_current_bb = bb->index;
00485 p = bb->head;
00486 last = bb->end;
00487 while (1)
00488 {
00489 if (INSN_P (p))
00490 note_stores (PATTERN (p), find_evaluations_1, NULL);
00491
00492 if (p == last)
00493 break;
00494 p = NEXT_INSN (p);
00495 }
00496 }
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 static void
00517 compute_dominance_frontiers_1 (frontiers, idom, bb, done)
00518 sbitmap *frontiers;
00519 dominance_info idom;
00520 int bb;
00521 sbitmap done;
00522 {
00523 basic_block b = BASIC_BLOCK (bb);
00524 edge e;
00525 basic_block c;
00526
00527 SET_BIT (done, bb);
00528 sbitmap_zero (frontiers[bb]);
00529
00530
00531
00532
00533 FOR_EACH_BB (c)
00534 if (get_immediate_dominator (idom, c)->index == bb
00535 && ! TEST_BIT (done, c->index))
00536 compute_dominance_frontiers_1 (frontiers, idom, c->index, done);
00537
00538
00539 for (e = b->succ; e; e = e->succ_next)
00540 {
00541 if (e->dest == EXIT_BLOCK_PTR)
00542 continue;
00543 if (get_immediate_dominator (idom, e->dest)->index != bb)
00544 SET_BIT (frontiers[bb], e->dest->index);
00545 }
00546
00547
00548 FOR_EACH_BB (c)
00549 if (get_immediate_dominator (idom, c)->index == bb)
00550 {
00551 int x;
00552 EXECUTE_IF_SET_IN_SBITMAP (frontiers[c->index], 0, x,
00553 {
00554 if (get_immediate_dominator (idom, BASIC_BLOCK (x))->index != bb)
00555 SET_BIT (frontiers[bb], x);
00556 });
00557 }
00558 }
00559
00560 void
00561 compute_dominance_frontiers (frontiers, idom)
00562 sbitmap *frontiers;
00563 dominance_info idom;
00564 {
00565 sbitmap done = sbitmap_alloc (last_basic_block);
00566 sbitmap_zero (done);
00567
00568 compute_dominance_frontiers_1 (frontiers, idom, 0, done);
00569
00570 sbitmap_free (done);
00571 }
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581 static void
00582 compute_iterated_dominance_frontiers (idfs, frontiers, evals, nregs)
00583 sbitmap *idfs;
00584 sbitmap *frontiers;
00585 sbitmap *evals;
00586 int nregs;
00587 {
00588 sbitmap worklist;
00589 int reg, passes = 0;
00590
00591 worklist = sbitmap_alloc (last_basic_block);
00592
00593 for (reg = 0; reg < nregs; ++reg)
00594 {
00595 sbitmap idf = idfs[reg];
00596 int b, changed;
00597
00598
00599
00600
00601 sbitmap_copy (worklist, evals[reg]);
00602
00603
00604
00605 sbitmap_zero (idf);
00606
00607
00608 do
00609 {
00610 changed = 0;
00611 passes++;
00612 EXECUTE_IF_SET_IN_SBITMAP (worklist, 0, b,
00613 {
00614 RESET_BIT (worklist, b);
00615
00616
00617
00618
00619 sbitmap_union_of_diff (worklist, worklist, frontiers[b], idf);
00620 sbitmap_a_or_b (idf, idf, frontiers[b]);
00621 changed = 1;
00622 });
00623 }
00624 while (changed);
00625 }
00626
00627 sbitmap_free (worklist);
00628
00629 if (rtl_dump_file)
00630 {
00631 fprintf (rtl_dump_file,
00632 "Iterated dominance frontier: %d passes on %d regs.\n",
00633 passes, nregs);
00634 }
00635 }
00636
00637
00638
00639 static void
00640 insert_phi_node (regno, bb)
00641 int regno, bb;
00642 {
00643 basic_block b = BASIC_BLOCK (bb);
00644 edge e;
00645 int npred, i;
00646 rtvec vec;
00647 rtx phi, reg;
00648 rtx insn;
00649 int end_p;
00650
00651
00652 for (e = b->pred, npred = 0; e; e = e->pred_next)
00653 if (e->src != ENTRY_BLOCK_PTR)
00654 npred++;
00655
00656
00657
00658 if (npred == 0)
00659 return;
00660
00661
00662 reg = regno_reg_rtx[regno];
00663
00664
00665
00666 vec = rtvec_alloc (npred * 2);
00667 for (e = b->pred, i = 0; e ; e = e->pred_next, i += 2)
00668 if (e->src != ENTRY_BLOCK_PTR)
00669 {
00670 RTVEC_ELT (vec, i + 0) = pc_rtx;
00671 RTVEC_ELT (vec, i + 1) = GEN_INT (e->src->index);
00672 }
00673
00674 phi = gen_rtx_PHI (VOIDmode, vec);
00675 phi = gen_rtx_SET (VOIDmode, reg, phi);
00676
00677 insn = first_insn_after_basic_block_note (b);
00678 end_p = PREV_INSN (insn) == b->end;
00679 emit_insn_before (phi, insn);
00680 if (end_p)
00681 b->end = PREV_INSN (insn);
00682 }
00683
00684 static void
00685 insert_phi_nodes (idfs, evals, nregs)
00686 sbitmap *idfs;
00687 sbitmap *evals ATTRIBUTE_UNUSED;
00688 int nregs;
00689 {
00690 int reg;
00691
00692 for (reg = 0; reg < nregs; ++reg)
00693 if (CONVERT_REGISTER_TO_SSA_P (reg))
00694 {
00695 int b;
00696 EXECUTE_IF_SET_IN_SBITMAP (idfs[reg], 0, b,
00697 {
00698 if (REGNO_REG_SET_P (BASIC_BLOCK (b)->global_live_at_start, reg))
00699 insert_phi_node (reg, b);
00700 });
00701 }
00702 }
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712 struct rename_set_data
00713 {
00714 struct rename_set_data *next;
00715
00716 rtx *reg_loc;
00717
00718 rtx old_reg;
00719
00720
00721 rtx new_reg;
00722
00723
00724 rtx prev_reg;
00725
00726 rtx set_insn;
00727 };
00728
00729
00730
00731 struct rename_context
00732 {
00733 struct rename_set_data *new_renames;
00734 struct rename_set_data *done_renames;
00735 rtx current_insn;
00736 };
00737
00738
00739 static void
00740 create_delayed_rename (c, reg_loc)
00741 struct rename_context *c;
00742 rtx *reg_loc;
00743 {
00744 struct rename_set_data *r;
00745 r = (struct rename_set_data *) xmalloc (sizeof(*r));
00746
00747 if (GET_CODE (*reg_loc) != REG
00748 || !CONVERT_REGISTER_TO_SSA_P (REGNO (*reg_loc)))
00749 abort ();
00750
00751 r->reg_loc = reg_loc;
00752 r->old_reg = *reg_loc;
00753 r->prev_reg = ssa_rename_to_lookup(r->old_reg);
00754 r->set_insn = c->current_insn;
00755 r->next = c->new_renames;
00756 c->new_renames = r;
00757 }
00758
00759
00760
00761
00762
00763
00764
00765
00766 #define RENAME_NO_RTX pc_rtx
00767
00768
00769
00770
00771 static void
00772 apply_delayed_renames (c)
00773 struct rename_context *c;
00774 {
00775 struct rename_set_data *r;
00776 struct rename_set_data *last_r = NULL;
00777
00778 for (r = c->new_renames; r != NULL; r = r->next)
00779 {
00780 int new_regno;
00781
00782
00783
00784 if (ssa_rename_to_lookup (r->old_reg) != r->prev_reg)
00785 abort ();
00786
00787
00788
00789 if (r->prev_reg == NULL_RTX && !HARD_REGISTER_P (r->old_reg))
00790 {
00791 r->new_reg = r->old_reg;
00792
00793 r->prev_reg = RENAME_NO_RTX;
00794 }
00795 else
00796 r->new_reg = gen_reg_rtx (GET_MODE (r->old_reg));
00797 new_regno = REGNO (r->new_reg);
00798 ssa_rename_to_insert (r->old_reg, r->new_reg);
00799
00800 if (new_regno >= (int) ssa_definition->num_elements)
00801 {
00802 int new_limit = new_regno * 5 / 4;
00803 VARRAY_GROW (ssa_definition, new_limit);
00804 }
00805
00806 VARRAY_RTX (ssa_definition, new_regno) = r->set_insn;
00807 ssa_rename_from_insert (new_regno, r->old_reg);
00808 last_r = r;
00809 }
00810 if (last_r != NULL)
00811 {
00812 last_r->next = c->done_renames;
00813 c->done_renames = c->new_renames;
00814 c->new_renames = NULL;
00815 }
00816 }
00817
00818
00819
00820
00821 static int
00822 rename_insn_1 (ptr, data)
00823 rtx *ptr;
00824 void *data;
00825 {
00826 rtx x = *ptr;
00827 struct rename_context *context = data;
00828
00829 if (x == NULL_RTX)
00830 return 0;
00831
00832 switch (GET_CODE (x))
00833 {
00834 case SET:
00835 {
00836 rtx *destp = &SET_DEST (x);
00837 rtx dest = SET_DEST (x);
00838
00839
00840
00841
00842
00843
00844 if (GET_CODE (dest) == SUBREG
00845 && (GET_MODE_SIZE (GET_MODE (dest))
00846 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))))
00847 && GET_CODE (SUBREG_REG (dest)) == REG
00848 && CONVERT_REGISTER_TO_SSA_P (REGNO (SUBREG_REG (dest))))
00849 {
00850 destp = &XEXP (dest, 0);
00851 dest = XEXP (dest, 0);
00852 }
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869 if (GET_CODE (dest) == STRICT_LOW_PART
00870 || GET_CODE (dest) == SUBREG
00871 || GET_CODE (dest) == SIGN_EXTRACT
00872 || GET_CODE (dest) == ZERO_EXTRACT)
00873 {
00874 rtx i, reg;
00875 reg = dest;
00876
00877 while (GET_CODE (reg) == STRICT_LOW_PART
00878 || GET_CODE (reg) == SUBREG
00879 || GET_CODE (reg) == SIGN_EXTRACT
00880 || GET_CODE (reg) == ZERO_EXTRACT)
00881 reg = XEXP (reg, 0);
00882
00883 if (GET_CODE (reg) == REG
00884 && CONVERT_REGISTER_TO_SSA_P (REGNO (reg)))
00885 {
00886
00887
00888
00889
00890 struct rename_set_data *saved_new_renames;
00891 saved_new_renames = context->new_renames;
00892 context->new_renames = NULL;
00893 i = emit_insn (gen_rtx_SET (VOIDmode, reg, reg));
00894 for_each_rtx (&i, rename_insn_1, data);
00895 apply_delayed_renames (context);
00896 context->new_renames = saved_new_renames;
00897 }
00898 }
00899 else if (GET_CODE (dest) == REG
00900 && CONVERT_REGISTER_TO_SSA_P (REGNO (dest)))
00901 {
00902
00903
00904
00905
00906 create_delayed_rename (context, destp);
00907
00908
00909
00910
00911 if (GET_CODE (x) == SET)
00912 for_each_rtx (&SET_SRC (x), rename_insn_1, data);
00913 return -1;
00914 }
00915
00916
00917
00918 return 0;
00919 }
00920
00921 case REG:
00922 if (CONVERT_REGISTER_TO_SSA_P (REGNO (x))
00923 && REGNO (x) < ssa_max_reg_num)
00924 {
00925 rtx new_reg = ssa_rename_to_lookup (x);
00926
00927 if (new_reg != RENAME_NO_RTX && new_reg != NULL_RTX)
00928 {
00929 if (GET_MODE (x) != GET_MODE (new_reg))
00930 abort ();
00931 *ptr = new_reg;
00932 }
00933 else
00934 {
00935
00936
00937 *ptr = gen_reg_rtx (GET_MODE (x));
00938 }
00939 }
00940 return -1;
00941
00942 case CLOBBER:
00943
00944
00945
00946
00947
00948 {
00949 rtx dest = XCEXP (x, 0, CLOBBER);
00950 if (REG_P (dest))
00951 {
00952 if (CONVERT_REGISTER_TO_SSA_P (REGNO (dest))
00953 && REGNO (dest) < ssa_max_reg_num)
00954 {
00955 rtx new_reg = ssa_rename_to_lookup (dest);
00956 if (new_reg != NULL_RTX && new_reg != RENAME_NO_RTX)
00957 XCEXP (x, 0, CLOBBER) = new_reg;
00958 }
00959
00960 return -1;
00961 }
00962 else
00963
00964 return 0;
00965 }
00966
00967 case PHI:
00968
00969 return -1;
00970
00971 default:
00972
00973 return 0;
00974 }
00975 }
00976
00977 static rtx
00978 gen_sequence ()
00979 {
00980 rtx first_insn = get_insns ();
00981 rtx result;
00982 rtx tem;
00983 int i;
00984 int len;
00985
00986
00987 len = 0;
00988 for (tem = first_insn; tem; tem = NEXT_INSN (tem))
00989 len++;
00990
00991 result = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (len));
00992
00993 for (i = 0, tem = first_insn; tem; tem = NEXT_INSN (tem), i++)
00994 XVECEXP (result, 0, i) = tem;
00995
00996 return result;
00997 }
00998
00999 static void
01000 rename_block (bb, idom)
01001 int bb;
01002 dominance_info idom;
01003 {
01004 basic_block b = BASIC_BLOCK (bb);
01005 edge e;
01006 rtx insn, next, last;
01007 struct rename_set_data *set_data = NULL;
01008 basic_block c;
01009
01010
01011
01012
01013 next = b->head;
01014 last = b->end;
01015 do
01016 {
01017 insn = next;
01018 if (INSN_P (insn))
01019 {
01020 struct rename_context context;
01021 context.done_renames = set_data;
01022 context.new_renames = NULL;
01023 context.current_insn = insn;
01024
01025 start_sequence ();
01026 for_each_rtx (&PATTERN (insn), rename_insn_1, &context);
01027 for_each_rtx (®_NOTES (insn), rename_insn_1, &context);
01028
01029
01030
01031
01032
01033 if (get_insns () != NULL_RTX)
01034 {
01035 rtx seq;
01036 int i;
01037
01038 emit (PATTERN (insn));
01039 seq = gen_sequence ();
01040
01041
01042 for (i = 0; i < XVECLEN (seq, 0); i++)
01043 XVECEXP (seq, 0, i) = PATTERN (XVECEXP (seq, 0, i));
01044 PATTERN (insn) = seq;
01045 }
01046 end_sequence ();
01047
01048 apply_delayed_renames (&context);
01049 set_data = context.done_renames;
01050 }
01051
01052 next = NEXT_INSN (insn);
01053 }
01054 while (insn != last);
01055
01056
01057
01058 for (e = b->succ; e; e = e->succ_next)
01059 {
01060 if (e->dest == EXIT_BLOCK_PTR)
01061 continue;
01062
01063 insn = first_insn_after_basic_block_note (e->dest);
01064
01065 while (PHI_NODE_P (insn))
01066 {
01067 rtx phi = PATTERN (insn);
01068 rtx reg;
01069
01070
01071
01072
01073
01074
01075
01076 reg = SET_DEST (phi);
01077 if (REGNO (reg) >= ssa_max_reg_num)
01078 reg = ssa_rename_from_lookup (REGNO (reg));
01079 if (reg == NULL_RTX)
01080 abort ();
01081 reg = ssa_rename_to_lookup (reg);
01082
01083
01084
01085
01086 if (reg == NULL || reg == RENAME_NO_RTX)
01087 {
01088 if (! remove_phi_alternative (phi, b))
01089 abort ();
01090 }
01091 else
01092 {
01093
01094
01095
01096 if (GET_MODE (SET_DEST (phi)) == VOIDmode)
01097 PUT_MODE (SET_DEST (phi), GET_MODE (reg));
01098 else if (GET_MODE (SET_DEST (phi)) != GET_MODE (reg))
01099 abort ();
01100
01101 *phi_alternative (phi, bb) = reg;
01102 }
01103
01104 insn = NEXT_INSN (insn);
01105 }
01106 }
01107
01108
01109
01110
01111 FOR_EACH_BB (c)
01112 if (get_immediate_dominator (idom, c)->index == bb)
01113 rename_block (c->index, idom);
01114
01115
01116
01117
01118 while (set_data)
01119 {
01120 struct rename_set_data *next;
01121 rtx old_reg = *set_data->reg_loc;
01122
01123 if (*set_data->reg_loc != set_data->old_reg)
01124 abort ();
01125 *set_data->reg_loc = set_data->new_reg;
01126
01127 ssa_rename_to_insert (old_reg, set_data->prev_reg);
01128
01129 next = set_data->next;
01130 free (set_data);
01131 set_data = next;
01132 }
01133 }
01134
01135 static void
01136 rename_registers (nregs, idom)
01137 int nregs;
01138 dominance_info idom;
01139 {
01140 VARRAY_RTX_INIT (ssa_definition, nregs * 3, "ssa_definition");
01141 ssa_rename_from_initialize ();
01142
01143 ssa_rename_to_pseudo = (rtx *) alloca (nregs * sizeof(rtx));
01144 memset ((char *) ssa_rename_to_pseudo, 0, nregs * sizeof(rtx));
01145 memset ((char *) ssa_rename_to_hard, 0,
01146 FIRST_PSEUDO_REGISTER * NUM_MACHINE_MODES * sizeof (rtx));
01147
01148 rename_block (0, idom);
01149
01150
01151
01152
01153 ssa_rename_to_pseudo = NULL;
01154 }
01155
01156
01157
01158 void
01159 convert_to_ssa ()
01160 {
01161
01162 sbitmap *evals;
01163
01164
01165 sbitmap *dfs;
01166 sbitmap *idfs;
01167
01168
01169 dominance_info idom;
01170
01171 int nregs;
01172
01173 basic_block bb;
01174
01175
01176 if (in_ssa_form)
01177 abort ();
01178
01179
01180
01181 life_analysis (get_insns (), NULL, 0);
01182
01183 idom = calculate_dominance_info (CDI_DOMINATORS);
01184
01185 if (rtl_dump_file)
01186 {
01187 fputs (";; Immediate Dominators:\n", rtl_dump_file);
01188 FOR_EACH_BB (bb)
01189 fprintf (rtl_dump_file, ";\t%3d = %3d\n", bb->index,
01190 get_immediate_dominator (idom, bb)->index);
01191 fflush (rtl_dump_file);
01192 }
01193
01194
01195
01196 dfs = sbitmap_vector_alloc (last_basic_block, last_basic_block);
01197 compute_dominance_frontiers (dfs, idom);
01198
01199 if (rtl_dump_file)
01200 {
01201 dump_sbitmap_vector (rtl_dump_file, ";; Dominance Frontiers:",
01202 "; Basic Block", dfs, last_basic_block);
01203 fflush (rtl_dump_file);
01204 }
01205
01206
01207
01208 ssa_max_reg_num = max_reg_num ();
01209 nregs = ssa_max_reg_num;
01210 evals = sbitmap_vector_alloc (nregs, last_basic_block);
01211 find_evaluations (evals, nregs);
01212
01213
01214
01215 idfs = sbitmap_vector_alloc (nregs, last_basic_block);
01216 compute_iterated_dominance_frontiers (idfs, dfs, evals, nregs);
01217
01218 if (rtl_dump_file)
01219 {
01220 dump_sbitmap_vector (rtl_dump_file, ";; Iterated Dominance Frontiers:",
01221 "; Register", idfs, nregs);
01222 fflush (rtl_dump_file);
01223 }
01224
01225
01226
01227 insert_phi_nodes (idfs, evals, nregs);
01228
01229
01230
01231 rename_registers (nregs, idom);
01232
01233
01234
01235 sbitmap_vector_free (dfs);
01236 sbitmap_vector_free (evals);
01237 sbitmap_vector_free (idfs);
01238 in_ssa_form = 1;
01239
01240 reg_scan (get_insns (), max_reg_num (), 1);
01241 free_dominance_info (idom);
01242 }
01243
01244
01245
01246
01247
01248 static inline int
01249 ephi_add_node (reg, nodes, n_nodes)
01250 rtx reg, *nodes;
01251 int *n_nodes;
01252 {
01253 int i;
01254 for (i = *n_nodes - 1; i >= 0; --i)
01255 if (REGNO (reg) == REGNO (nodes[i]))
01256 return i;
01257
01258 nodes[i = (*n_nodes)++] = reg;
01259 return i;
01260 }
01261
01262
01263
01264
01265
01266
01267 static int *
01268 ephi_forward (t, visited, succ, tstack)
01269 int t;
01270 sbitmap visited;
01271 sbitmap *succ;
01272 int *tstack;
01273 {
01274 int s;
01275
01276 SET_BIT (visited, t);
01277
01278 EXECUTE_IF_SET_IN_SBITMAP (succ[t], 0, s,
01279 {
01280 if (! TEST_BIT (visited, s))
01281 tstack = ephi_forward (s, visited, succ, tstack);
01282 });
01283
01284 *tstack++ = t;
01285 return tstack;
01286 }
01287
01288
01289
01290
01291 static void
01292 ephi_backward (t, visited, pred, nodes)
01293 int t;
01294 sbitmap visited, *pred;
01295 rtx *nodes;
01296 {
01297 int p;
01298
01299 SET_BIT (visited, t);
01300
01301 EXECUTE_IF_SET_IN_SBITMAP (pred[t], 0, p,
01302 {
01303 if (! TEST_BIT (visited, p))
01304 {
01305 ephi_backward (p, visited, pred, nodes);
01306 emit_move_insn (nodes[p], nodes[t]);
01307 }
01308 });
01309 }
01310
01311
01312
01313
01314 static void
01315 ephi_create (t, visited, pred, succ, nodes)
01316 int t;
01317 sbitmap visited, *pred, *succ;
01318 rtx *nodes;
01319 {
01320 rtx reg_u = NULL_RTX;
01321 int unvisited_predecessors = 0;
01322 int p;
01323
01324
01325
01326
01327
01328
01329 EXECUTE_IF_SET_IN_SBITMAP (pred[t], 0, p,
01330 {
01331 if (! TEST_BIT (visited, p))
01332 unvisited_predecessors = 1;
01333 else if (!reg_u)
01334 reg_u = nodes[p];
01335 });
01336
01337 if (unvisited_predecessors)
01338 {
01339
01340
01341
01342 if (!reg_u)
01343 {
01344 reg_u = gen_reg_rtx (GET_MODE (nodes[t]));
01345 emit_move_insn (reg_u, nodes[t]);
01346 }
01347
01348 EXECUTE_IF_SET_IN_SBITMAP (pred[t], 0, p,
01349 {
01350 if (! TEST_BIT (visited, p))
01351 {
01352 ephi_backward (p, visited, pred, nodes);
01353 emit_move_insn (nodes[p], reg_u);
01354 }
01355 });
01356 }
01357 else
01358 {
01359
01360
01361 int s;
01362 EXECUTE_IF_SET_IN_SBITMAP (succ[t], 0, s,
01363 {
01364 SET_BIT (visited, t);
01365 emit_move_insn (nodes[t], nodes[s]);
01366 return;
01367 });
01368 }
01369 }
01370
01371
01372
01373 static void
01374 eliminate_phi (e, reg_partition)
01375 edge e;
01376 partition reg_partition;
01377 {
01378 int n_nodes;
01379 sbitmap *pred, *succ;
01380 sbitmap visited;
01381 rtx *nodes;
01382 int *stack, *tstack;
01383 rtx insn;
01384 int i;
01385
01386
01387
01388 insn = first_insn_after_basic_block_note (e->dest);
01389
01390 n_nodes = 0;
01391 while (PHI_NODE_P (insn))
01392 {
01393 insn = next_nonnote_insn (insn);
01394 n_nodes += 2;
01395 }
01396
01397 if (n_nodes == 0)
01398 return;
01399
01400
01401
01402
01403
01404
01405
01406 nodes = (rtx *) alloca (n_nodes * sizeof(rtx));
01407 pred = sbitmap_vector_alloc (n_nodes, n_nodes);
01408 succ = sbitmap_vector_alloc (n_nodes, n_nodes);
01409 sbitmap_vector_zero (pred, n_nodes);
01410 sbitmap_vector_zero (succ, n_nodes);
01411
01412 insn = first_insn_after_basic_block_note (e->dest);
01413
01414 n_nodes = 0;
01415 for (; PHI_NODE_P (insn); insn = next_nonnote_insn (insn))
01416 {
01417 rtx* preg = phi_alternative (PATTERN (insn), e->src->index);
01418 rtx tgt = SET_DEST (PATTERN (insn));
01419 rtx reg;
01420
01421
01422
01423
01424 if (preg == NULL)
01425 continue;
01426 reg = *preg;
01427
01428 if (GET_CODE (reg) != REG || GET_CODE (tgt) != REG)
01429 abort ();
01430
01431 reg = regno_reg_rtx[partition_find (reg_partition, REGNO (reg))];
01432 tgt = regno_reg_rtx[partition_find (reg_partition, REGNO (tgt))];
01433
01434
01435 if (reg != tgt)
01436 {
01437 int ireg, itgt;
01438
01439 ireg = ephi_add_node (reg, nodes, &n_nodes);
01440 itgt = ephi_add_node (tgt, nodes, &n_nodes);
01441
01442 SET_BIT (pred[ireg], itgt);
01443 SET_BIT (succ[itgt], ireg);
01444 }
01445 }
01446
01447 if (n_nodes == 0)
01448 goto out;
01449
01450
01451
01452 visited = sbitmap_alloc (n_nodes);
01453 sbitmap_zero (visited);
01454
01455 tstack = stack = (int *) alloca (n_nodes * sizeof (int));
01456
01457 for (i = 0; i < n_nodes; ++i)
01458 if (! TEST_BIT (visited, i))
01459 tstack = ephi_forward (i, visited, succ, tstack);
01460
01461 sbitmap_zero (visited);
01462
01463
01464
01465 start_sequence ();
01466
01467 while (tstack != stack)
01468 {
01469 i = *--tstack;
01470 if (! TEST_BIT (visited, i))
01471 ephi_create (i, visited, pred, succ, nodes);
01472 }
01473
01474 insn = get_insns ();
01475 end_sequence ();
01476 insert_insn_on_edge (insn, e);
01477 if (rtl_dump_file)
01478 fprintf (rtl_dump_file, "Emitting copy on edge (%d,%d)\n",
01479 e->src->index, e->dest->index);
01480
01481 sbitmap_free (visited);
01482 out:
01483 sbitmap_vector_free (pred);
01484 sbitmap_vector_free (succ);
01485 }
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502 static int
01503 make_regs_equivalent_over_bad_edges (bb, reg_partition)
01504 int bb;
01505 partition reg_partition;
01506 {
01507 int changed = 0;
01508 basic_block b = BASIC_BLOCK (bb);
01509 rtx phi;
01510
01511
01512 phi = first_insn_after_basic_block_note (b);
01513
01514
01515 for (;
01516 PHI_NODE_P (phi);
01517 phi = next_nonnote_insn (phi))
01518 {
01519 edge e;
01520 int tgt_regno;
01521 rtx set = PATTERN (phi);
01522 rtx tgt = SET_DEST (set);
01523
01524
01525 if (GET_CODE (tgt) != REG
01526 || !CONVERT_REGISTER_TO_SSA_P (REGNO (tgt)))
01527 abort ();
01528 tgt_regno = REGNO (tgt);
01529
01530
01531 for (e = b->pred; e; e = e->pred_next)
01532 if ((e->flags & EDGE_ABNORMAL) && EDGE_CRITICAL_P (e))
01533 {
01534 rtx *alt = phi_alternative (set, e->src->index);
01535 int alt_regno;
01536
01537
01538
01539 if (alt == 0)
01540 continue;
01541
01542
01543 if (GET_CODE (*alt) != REG
01544 || !CONVERT_REGISTER_TO_SSA_P (REGNO (*alt)))
01545 abort ();
01546 alt_regno = REGNO (*alt);
01547
01548
01549
01550 if (partition_find (reg_partition, tgt_regno)
01551 != partition_find (reg_partition, alt_regno))
01552 {
01553
01554 if (conflicting_hard_regs_p (tgt_regno, alt_regno))
01555
01556
01557 abort ();
01558
01559 partition_union (reg_partition,
01560 tgt_regno, alt_regno);
01561 ++changed;
01562 }
01563 }
01564 }
01565
01566 return changed;
01567 }
01568
01569
01570
01571
01572
01573
01574
01575 static int
01576 make_equivalent_phi_alternatives_equivalent (bb, reg_partition)
01577 int bb;
01578 partition reg_partition;
01579 {
01580 int changed = 0;
01581 basic_block b = BASIC_BLOCK (bb);
01582 rtx phi;
01583
01584
01585 phi = first_insn_after_basic_block_note (b);
01586
01587
01588 for (;
01589 PHI_NODE_P (phi);
01590 phi = next_nonnote_insn (phi))
01591 {
01592 rtx set = PATTERN (phi);
01593
01594 int tgt_regno = REGNO (SET_DEST (PATTERN (phi)));
01595
01596 rtx phi2 = next_nonnote_insn (phi);
01597
01598
01599 for (;
01600 PHI_NODE_P (phi2);
01601 phi2 = next_nonnote_insn (phi2))
01602 {
01603 rtx set2 = PATTERN (phi2);
01604
01605 int tgt2_regno = REGNO (SET_DEST (set2));
01606
01607
01608 if (partition_find (reg_partition, tgt_regno) ==
01609 partition_find (reg_partition, tgt2_regno))
01610 {
01611 edge e;
01612
01613 for (e = b->pred; e; e = e->pred_next)
01614 {
01615 int pred_block = e->src->index;
01616
01617
01618 rtx *alt = phi_alternative (set, pred_block);
01619 rtx *alt2 = phi_alternative (set2, pred_block);
01620
01621
01622
01623 if (alt == 0 || alt2 == 0)
01624 continue;
01625
01626
01627 if (GET_CODE (*alt) != REG
01628 || !CONVERT_REGISTER_TO_SSA_P (REGNO (*alt)))
01629 abort ();
01630 if (GET_CODE (*alt2) != REG
01631 || !CONVERT_REGISTER_TO_SSA_P (REGNO (*alt2)))
01632 abort ();
01633
01634
01635
01636 if (partition_find (reg_partition, REGNO (*alt))
01637 != partition_find (reg_partition, REGNO (*alt2)))
01638 {
01639
01640 if (conflicting_hard_regs_p (REGNO (*alt), REGNO (*alt2)))
01641
01642
01643 abort ();
01644
01645 partition_union (reg_partition,
01646 REGNO (*alt), REGNO (*alt2));
01647 ++changed;
01648 }
01649 }
01650 }
01651 }
01652 }
01653
01654 return changed;
01655 }
01656
01657
01658
01659
01660 static partition
01661 compute_conservative_reg_partition ()
01662 {
01663 basic_block bb;
01664 int changed = 0;
01665
01666
01667
01668
01669 partition p =
01670 partition_new (ssa_definition->num_elements);
01671
01672
01673
01674
01675
01676 FOR_EACH_BB_REVERSE (bb)
01677 changed += make_regs_equivalent_over_bad_edges (bb->index, p);
01678
01679
01680
01681
01682 while (changed > 0)
01683 {
01684 changed = 0;
01685 FOR_EACH_BB_REVERSE (bb)
01686 changed += make_equivalent_phi_alternatives_equivalent (bb->index, p);
01687 }
01688
01689 return p;
01690 }
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722 static int
01723 coalesce_if_unconflicting (p, conflicts, reg1, reg2)
01724 partition p;
01725 conflict_graph conflicts;
01726 int reg1;
01727 int reg2;
01728 {
01729 int reg;
01730
01731
01732 if (!CONVERT_REGISTER_TO_SSA_P (reg1) || !CONVERT_REGISTER_TO_SSA_P (reg2))
01733 return 0;
01734
01735
01736
01737 reg1 = partition_find (p, reg1);
01738 reg2 = partition_find (p, reg2);
01739
01740
01741 if (reg1 == reg2)
01742 return 0;
01743
01744
01745 if (conflicting_hard_regs_p (reg1, reg2) ||
01746 conflict_graph_conflict_p (conflicts, reg1, reg2))
01747 return 0;
01748
01749
01750 partition_union (p, reg1, reg2);
01751
01752
01753 reg = partition_find (p, reg1);
01754
01755
01756 conflict_graph_merge_regs (conflicts, reg, reg1);
01757 conflict_graph_merge_regs (conflicts, reg, reg2);
01758
01759 return 1;
01760 }
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770 static int
01771 coalesce_regs_in_copies (bb, p, conflicts)
01772 basic_block bb;
01773 partition p;
01774 conflict_graph conflicts;
01775 {
01776 int changed = 0;
01777 rtx insn;
01778 rtx end = bb->end;
01779
01780
01781 for (insn = bb->head; insn != end; insn = NEXT_INSN (insn))
01782 {
01783 rtx pattern;
01784 rtx src;
01785 rtx dest;
01786
01787
01788 if (GET_CODE (insn) != INSN)
01789 continue;
01790 pattern = PATTERN (insn);
01791 if (GET_CODE (pattern) != SET)
01792 continue;
01793
01794 src = SET_SRC (pattern);
01795 dest = SET_DEST (pattern);
01796
01797
01798 if (GET_CODE (src) != REG || GET_CODE (dest) != REG)
01799 continue;
01800
01801
01802
01803
01804
01805
01806
01807 if (GET_MODE (src) != GET_MODE (dest))
01808 continue;
01809
01810
01811
01812
01813 changed += coalesce_if_unconflicting (p, conflicts,
01814 REGNO (src), REGNO (dest));
01815 }
01816
01817 return changed;
01818 }
01819
01820 struct phi_coalesce_context
01821 {
01822 partition p;
01823 conflict_graph conflicts;
01824 int changed;
01825 };
01826
01827
01828
01829
01830
01831
01832 static int
01833 coalesce_reg_in_phi (insn, dest_regno, src_regno, data)
01834 rtx insn ATTRIBUTE_UNUSED;
01835 int dest_regno;
01836 int src_regno;
01837 void *data;
01838 {
01839 struct phi_coalesce_context *context =
01840 (struct phi_coalesce_context *) data;
01841
01842
01843 context->changed
01844 += coalesce_if_unconflicting (context->p, context->conflicts,
01845 dest_regno, src_regno);
01846 return 0;
01847 }
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858 static int
01859 coalesce_regs_in_successor_phi_nodes (bb, p, conflicts)
01860 basic_block bb;
01861 partition p;
01862 conflict_graph conflicts;
01863 {
01864 struct phi_coalesce_context context;
01865 context.p = p;
01866 context.conflicts = conflicts;
01867 context.changed = 0;
01868
01869 for_each_successor_phi (bb, &coalesce_reg_in_phi, &context);
01870
01871 return context.changed;
01872 }
01873
01874
01875
01876
01877
01878
01879 static partition
01880 compute_coalesced_reg_partition ()
01881 {
01882 basic_block bb;
01883 int changed = 0;
01884 regset_head phi_set_head;
01885 regset phi_set = &phi_set_head;
01886
01887 partition p =
01888 partition_new (ssa_definition->num_elements);
01889
01890
01891
01892
01893
01894 FOR_EACH_BB_REVERSE (bb)
01895 make_regs_equivalent_over_bad_edges (bb->index, p);
01896
01897 INIT_REG_SET (phi_set);
01898
01899 do
01900 {
01901 conflict_graph conflicts;
01902
01903 changed = 0;
01904
01905
01906
01907 CLEAR_REG_SET (phi_set);
01908 mark_phi_and_copy_regs (phi_set);
01909
01910
01911 conflicts = conflict_graph_compute (phi_set, p);
01912
01913
01914
01915
01916
01917 FOR_EACH_BB_REVERSE (bb)
01918 {
01919 changed += coalesce_regs_in_copies (bb, p, conflicts);
01920 changed +=
01921 coalesce_regs_in_successor_phi_nodes (bb, p, conflicts);
01922 }
01923
01924 conflict_graph_delete (conflicts);
01925 }
01926 while (changed > 0);
01927
01928 FREE_REG_SET (phi_set);
01929
01930 return p;
01931 }
01932
01933
01934
01935
01936
01937 static int
01938 mark_reg_in_phi (ptr, data)
01939 rtx *ptr;
01940 void *data;
01941 {
01942 rtx expr = *ptr;
01943 regset set = (regset) data;
01944
01945 switch (GET_CODE (expr))
01946 {
01947 case REG:
01948 SET_REGNO_REG_SET (set, REGNO (expr));
01949
01950 case CONST_INT:
01951 case PHI:
01952 return 0;
01953 default:
01954 abort ();
01955 }
01956 }
01957
01958
01959
01960
01961
01962
01963 static void
01964 mark_phi_and_copy_regs (phi_set)
01965 regset phi_set;
01966 {
01967 unsigned int reg;
01968
01969
01970 for (reg = 0; reg < VARRAY_SIZE (ssa_definition); ++reg)
01971 if (CONVERT_REGISTER_TO_SSA_P (reg))
01972 {
01973 rtx insn = VARRAY_RTX (ssa_definition, reg);
01974 rtx pattern;
01975 rtx src;
01976
01977 if (insn == NULL
01978 || (GET_CODE (insn) == NOTE
01979 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED))
01980 continue;
01981 pattern = PATTERN (insn);
01982
01983
01984 if (GET_CODE (pattern) != SET)
01985 continue;
01986 src = SET_SRC (pattern);
01987
01988 if (GET_CODE (src) == REG)
01989 {
01990
01991 SET_REGNO_REG_SET (phi_set, reg);
01992 SET_REGNO_REG_SET (phi_set, REGNO (src));
01993 }
01994 else if (GET_CODE (src) == PHI)
01995 {
01996
01997 SET_REGNO_REG_SET (phi_set, reg);
01998
01999 for_each_rtx (&src, mark_reg_in_phi, phi_set);
02000 }
02001
02002 }
02003 }
02004
02005
02006
02007
02008 static int
02009 rename_equivalent_regs_in_insn (ptr, data)
02010 rtx *ptr;
02011 void* data;
02012 {
02013 rtx x = *ptr;
02014 partition reg_partition = (partition) data;
02015
02016 if (x == NULL_RTX)
02017 return 0;
02018
02019 switch (GET_CODE (x))
02020 {
02021 case REG:
02022 if (CONVERT_REGISTER_TO_SSA_P (REGNO (x)))
02023 {
02024 unsigned int regno = REGNO (x);
02025 unsigned int new_regno = partition_find (reg_partition, regno);
02026 rtx canonical_element_rtx = ssa_rename_from_lookup (new_regno);
02027
02028 if (canonical_element_rtx != NULL_RTX &&
02029 HARD_REGISTER_P (canonical_element_rtx))
02030 {
02031 if (REGNO (canonical_element_rtx) != regno)
02032 *ptr = canonical_element_rtx;
02033 }
02034 else if (regno != new_regno)
02035 {
02036 rtx new_reg = regno_reg_rtx[new_regno];
02037 if (GET_MODE (x) != GET_MODE (new_reg))
02038 abort ();
02039 *ptr = new_reg;
02040 }
02041 }
02042 return -1;
02043
02044 case PHI:
02045
02046
02047 return -1;
02048
02049 default:
02050
02051 return 0;
02052 }
02053 }
02054
02055
02056
02057
02058
02059 static int
02060 record_canonical_element_1 (srfp, data)
02061 void **srfp;
02062 void *data;
02063 {
02064 unsigned int reg = ((ssa_rename_from_pair *) *srfp)->reg;
02065 sbitmap canonical_elements =
02066 ((struct ssa_rename_from_hash_table_data *) data)->canonical_elements;
02067 partition reg_partition =
02068 ((struct ssa_rename_from_hash_table_data *) data)->reg_partition;
02069
02070 SET_BIT (canonical_elements, partition_find (reg_partition, reg));
02071 return 1;
02072 }
02073
02074
02075
02076
02077
02078
02079 static int
02080 check_hard_regs_in_partition (reg_partition)
02081 partition reg_partition;
02082 {
02083
02084
02085
02086 sbitmap canonical_elements;
02087 int element_index;
02088 int already_seen[FIRST_PSEUDO_REGISTER][NUM_MACHINE_MODES];
02089 int reg;
02090 int mach_mode;
02091
02092
02093 canonical_elements = sbitmap_alloc (max_reg_num ());
02094 sbitmap_zero (canonical_elements);
02095 ssa_rename_from_traverse (&record_canonical_element_1,
02096 canonical_elements, reg_partition);
02097
02098
02099 for (reg = 0; reg < FIRST_PSEUDO_REGISTER; ++reg)
02100 for (mach_mode = 0; mach_mode < NUM_MACHINE_MODES; ++mach_mode)
02101 already_seen[reg][mach_mode] = 0;
02102
02103
02104 EXECUTE_IF_SET_IN_SBITMAP (canonical_elements, 0, element_index,
02105 {
02106 rtx hard_reg_rtx = ssa_rename_from_lookup (element_index);
02107 if (hard_reg_rtx != NULL_RTX &&
02108 HARD_REGISTER_P (hard_reg_rtx) &&
02109 already_seen[REGNO (hard_reg_rtx)][GET_MODE (hard_reg_rtx)] != 0)
02110
02111
02112 return 0;
02113 });
02114
02115 sbitmap_free (canonical_elements);
02116
02117 return 1;
02118 }
02119
02120
02121
02122
02123 static void
02124 rename_equivalent_regs (reg_partition)
02125 partition reg_partition;
02126 {
02127 basic_block b;
02128
02129 FOR_EACH_BB_REVERSE (b)
02130 {
02131 rtx next = b->head;
02132 rtx last = b->end;
02133 rtx insn;
02134
02135 do
02136 {
02137 insn = next;
02138 if (INSN_P (insn))
02139 {
02140 for_each_rtx (&PATTERN (insn),
02141 rename_equivalent_regs_in_insn,
02142 reg_partition);
02143 for_each_rtx (®_NOTES (insn),
02144 rename_equivalent_regs_in_insn,
02145 reg_partition);
02146
02147 if (GET_CODE (PATTERN (insn)) == SEQUENCE)
02148 {
02149 rtx s = PATTERN (insn);
02150 int slen = XVECLEN (s, 0);
02151 int i;
02152
02153 if (slen <= 1)
02154 abort ();
02155
02156 PATTERN (insn) = XVECEXP (s, 0, slen-1);
02157 for (i = 0; i < slen - 1; i++)
02158 emit_insn_before (XVECEXP (s, 0, i), insn);
02159 }
02160 }
02161
02162 next = NEXT_INSN (insn);
02163 }
02164 while (insn != last);
02165 }
02166 }
02167
02168
02169
02170 void
02171 convert_from_ssa ()
02172 {
02173 basic_block b, bb;
02174 partition reg_partition;
02175 rtx insns = get_insns ();
02176
02177
02178
02179
02180
02181
02182 life_analysis (insns, NULL, PROP_DEATH_NOTES);
02183
02184
02185
02186 if (conservative_reg_partition)
02187 reg_partition = compute_conservative_reg_partition ();
02188 else
02189 reg_partition = compute_coalesced_reg_partition ();
02190
02191 if (!check_hard_regs_in_partition (reg_partition))
02192
02193
02194 abort ();
02195
02196 rename_equivalent_regs (reg_partition);
02197
02198
02199 FOR_EACH_BB_REVERSE (b)
02200 {
02201 edge e;
02202
02203 for (e = b->pred; e; e = e->pred_next)
02204 if (e->src != ENTRY_BLOCK_PTR)
02205 eliminate_phi (e, reg_partition);
02206 }
02207
02208 partition_delete (reg_partition);
02209
02210
02211 FOR_EACH_BB_REVERSE (bb)
02212 {
02213 rtx insn = bb->head;
02214
02215 while (1)
02216 {
02217
02218 if (PHI_NODE_P (insn))
02219 {
02220 if (insn == bb->end)
02221 bb->end = PREV_INSN (insn);
02222 insn = delete_insn (insn);
02223 }
02224
02225
02226
02227 else if (INSN_P (insn))
02228 break;
02229
02230 else if (insn == bb->end)
02231 break;
02232 else
02233 insn = NEXT_INSN (insn);
02234 }
02235 }
02236
02237
02238 commit_edge_insertions ();
02239
02240 in_ssa_form = 0;
02241
02242 count_or_remove_death_notes (NULL, 1);
02243
02244
02245 ssa_definition = 0;
02246 ssa_rename_from_free ();
02247 }
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258 int
02259 for_each_successor_phi (bb, fn, data)
02260 basic_block bb;
02261 successor_phi_fn fn;
02262 void *data;
02263 {
02264 edge e;
02265
02266 if (bb == EXIT_BLOCK_PTR)
02267 return 0;
02268
02269
02270 for (e = bb->succ; e != NULL; e = e->succ_next)
02271 {
02272 rtx insn;
02273
02274 basic_block successor = e->dest;
02275 if (successor == ENTRY_BLOCK_PTR
02276 || successor == EXIT_BLOCK_PTR)
02277 continue;
02278
02279
02280 insn = first_insn_after_basic_block_note (successor);
02281
02282 if (insn == NULL)
02283 continue;
02284
02285
02286 for ( ; PHI_NODE_P (insn); insn = NEXT_INSN (insn))
02287 {
02288 int result;
02289 rtx phi_set = PATTERN (insn);
02290 rtx *alternative = phi_alternative (phi_set, bb->index);
02291 rtx phi_src;
02292
02293
02294
02295
02296 if (alternative == NULL)
02297 continue;
02298 phi_src = *alternative;
02299
02300
02301 result = (*fn) (insn, REGNO (SET_DEST (phi_set)),
02302 REGNO (phi_src), data);
02303
02304
02305 if (result != 0)
02306 return result;
02307 }
02308 }
02309
02310 return 0;
02311 }
02312
02313
02314
02315
02316
02317
02318 static int
02319 conflicting_hard_regs_p (reg1, reg2)
02320 int reg1;
02321 int reg2;
02322 {
02323 int orig_reg1 = original_register (reg1);
02324 int orig_reg2 = original_register (reg2);
02325 if (HARD_REGISTER_NUM_P (orig_reg1) && HARD_REGISTER_NUM_P (orig_reg2)
02326 && orig_reg1 != orig_reg2)
02327 return 1;
02328 if (HARD_REGISTER_NUM_P (orig_reg1) && !HARD_REGISTER_NUM_P (orig_reg2))
02329 return 1;
02330 if (!HARD_REGISTER_NUM_P (orig_reg1) && HARD_REGISTER_NUM_P (orig_reg2))
02331 return 1;
02332
02333 return 0;
02334 }