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
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #include "config.h"
00053 #include "system.h"
00054 #include "rtl.h"
00055 #include "regs.h"
00056 #include "hard-reg-set.h"
00057 #include "flags.h"
00058 #include "real.h"
00059 #include "insn-config.h"
00060 #include "recog.h"
00061 #include "basic-block.h"
00062 #include "output.h"
00063 #include "tm_p.h"
00064
00065
00066
00067 #include "insn-attr.h"
00068
00069
00070 static void compute_antinout_edge PARAMS ((sbitmap *, sbitmap *,
00071 sbitmap *, sbitmap *));
00072 static void compute_earliest PARAMS ((struct edge_list *, int,
00073 sbitmap *, sbitmap *,
00074 sbitmap *, sbitmap *,
00075 sbitmap *));
00076 static void compute_laterin PARAMS ((struct edge_list *, sbitmap *,
00077 sbitmap *, sbitmap *,
00078 sbitmap *));
00079 static void compute_insert_delete PARAMS ((struct edge_list *edge_list,
00080 sbitmap *, sbitmap *,
00081 sbitmap *, sbitmap *,
00082 sbitmap *));
00083
00084
00085 static void compute_farthest PARAMS ((struct edge_list *, int,
00086 sbitmap *, sbitmap *,
00087 sbitmap*, sbitmap *,
00088 sbitmap *));
00089 static void compute_nearerout PARAMS ((struct edge_list *, sbitmap *,
00090 sbitmap *, sbitmap *,
00091 sbitmap *));
00092 static void compute_rev_insert_delete PARAMS ((struct edge_list *edge_list,
00093 sbitmap *, sbitmap *,
00094 sbitmap *, sbitmap *,
00095 sbitmap *));
00096
00097
00098
00099
00100
00101
00102
00103 static void
00104 compute_antinout_edge (antloc, transp, antin, antout)
00105 sbitmap *antloc;
00106 sbitmap *transp;
00107 sbitmap *antin;
00108 sbitmap *antout;
00109 {
00110 basic_block bb;
00111 edge e;
00112 basic_block *worklist, *qin, *qout, *qend;
00113 unsigned int qlen;
00114
00115
00116
00117
00118 qin = qout = worklist
00119 = (basic_block *) xmalloc (sizeof (basic_block) * n_basic_blocks);
00120
00121
00122
00123 sbitmap_vector_ones (antin, last_basic_block);
00124
00125
00126
00127 FOR_EACH_BB_REVERSE (bb)
00128 {
00129 *qin++ =bb;
00130 bb->aux = bb;
00131 }
00132
00133 qin = worklist;
00134 qend = &worklist[n_basic_blocks];
00135 qlen = n_basic_blocks;
00136
00137
00138
00139 for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
00140 e->src->aux = EXIT_BLOCK_PTR;
00141
00142
00143 while (qlen)
00144 {
00145
00146 bb = *qout++;
00147 qlen--;
00148
00149 if (qout >= qend)
00150 qout = worklist;
00151
00152 if (bb->aux == EXIT_BLOCK_PTR)
00153
00154
00155
00156 sbitmap_zero (antout[bb->index]);
00157 else
00158 {
00159
00160
00161 bb->aux = NULL;
00162 sbitmap_intersection_of_succs (antout[bb->index], antin, bb->index);
00163 }
00164
00165 if (sbitmap_a_or_b_and_c_cg (antin[bb->index], antloc[bb->index],
00166 transp[bb->index], antout[bb->index]))
00167
00168
00169
00170 for (e = bb->pred; e; e = e->pred_next)
00171 if (!e->src->aux && e->src != ENTRY_BLOCK_PTR)
00172 {
00173 *qin++ = e->src;
00174 e->src->aux = e;
00175 qlen++;
00176 if (qin >= qend)
00177 qin = worklist;
00178 }
00179 }
00180
00181 clear_aux_for_edges ();
00182 clear_aux_for_blocks ();
00183 free (worklist);
00184 }
00185
00186
00187
00188 static void
00189 compute_earliest (edge_list, n_exprs, antin, antout, avout, kill, earliest)
00190 struct edge_list *edge_list;
00191 int n_exprs;
00192 sbitmap *antin, *antout, *avout, *kill, *earliest;
00193 {
00194 sbitmap difference, temp_bitmap;
00195 int x, num_edges;
00196 basic_block pred, succ;
00197
00198 num_edges = NUM_EDGES (edge_list);
00199
00200 difference = sbitmap_alloc (n_exprs);
00201 temp_bitmap = sbitmap_alloc (n_exprs);
00202
00203 for (x = 0; x < num_edges; x++)
00204 {
00205 pred = INDEX_EDGE_PRED_BB (edge_list, x);
00206 succ = INDEX_EDGE_SUCC_BB (edge_list, x);
00207 if (pred == ENTRY_BLOCK_PTR)
00208 sbitmap_copy (earliest[x], antin[succ->index]);
00209 else
00210 {
00211 if (succ == EXIT_BLOCK_PTR)
00212 sbitmap_zero (earliest[x]);
00213 else
00214 {
00215 sbitmap_difference (difference, antin[succ->index],
00216 avout[pred->index]);
00217 sbitmap_not (temp_bitmap, antout[pred->index]);
00218 sbitmap_a_and_b_or_c (earliest[x], difference,
00219 kill[pred->index], temp_bitmap);
00220 }
00221 }
00222 }
00223
00224 sbitmap_free (temp_bitmap);
00225 sbitmap_free (difference);
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257 static void
00258 compute_laterin (edge_list, earliest, antloc, later, laterin)
00259 struct edge_list *edge_list;
00260 sbitmap *earliest, *antloc, *later, *laterin;
00261 {
00262 int num_edges, i;
00263 edge e;
00264 basic_block *worklist, *qin, *qout, *qend, bb;
00265 unsigned int qlen;
00266
00267 num_edges = NUM_EDGES (edge_list);
00268
00269
00270
00271
00272 qin = qout = worklist
00273 = (basic_block *) xmalloc (sizeof (basic_block) * (n_basic_blocks + 1));
00274
00275
00276 for (i = 0; i < num_edges; i++)
00277 INDEX_EDGE (edge_list, i)->aux = (void *) (size_t) i;
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 sbitmap_vector_ones (later, num_edges);
00290
00291
00292
00293
00294
00295 for (e = ENTRY_BLOCK_PTR->succ; e; e = e->succ_next)
00296 sbitmap_copy (later[(size_t) e->aux], earliest[(size_t) e->aux]);
00297
00298
00299
00300 FOR_EACH_BB (bb)
00301 {
00302 *qin++ = bb;
00303 bb->aux = bb;
00304 }
00305 qin = worklist;
00306
00307
00308
00309 qend = &worklist[n_basic_blocks];
00310 qlen = n_basic_blocks;
00311
00312
00313 while (qlen)
00314 {
00315
00316 bb = *qout++;
00317 bb->aux = NULL;
00318 qlen--;
00319 if (qout >= qend)
00320 qout = worklist;
00321
00322
00323 sbitmap_ones (laterin[bb->index]);
00324 for (e = bb->pred; e != NULL; e = e->pred_next)
00325 sbitmap_a_and_b (laterin[bb->index], laterin[bb->index], later[(size_t)e->aux]);
00326
00327
00328 for (e = bb->succ; e != NULL; e = e->succ_next)
00329 if (sbitmap_union_of_diff_cg (later[(size_t) e->aux],
00330 earliest[(size_t) e->aux],
00331 laterin[e->src->index],
00332 antloc[e->src->index])
00333
00334
00335 && e->dest != EXIT_BLOCK_PTR && e->dest->aux == 0)
00336 {
00337 *qin++ = e->dest;
00338 e->dest->aux = e;
00339 qlen++;
00340 if (qin >= qend)
00341 qin = worklist;
00342 }
00343 }
00344
00345
00346
00347
00348 sbitmap_ones (laterin[last_basic_block]);
00349 for (e = EXIT_BLOCK_PTR->pred; e != NULL; e = e->pred_next)
00350 sbitmap_a_and_b (laterin[last_basic_block],
00351 laterin[last_basic_block],
00352 later[(size_t) e->aux]);
00353
00354 clear_aux_for_edges ();
00355 free (worklist);
00356 }
00357
00358
00359
00360 static void
00361 compute_insert_delete (edge_list, antloc, later, laterin,
00362 insert, delete)
00363 struct edge_list *edge_list;
00364 sbitmap *antloc, *later, *laterin, *insert, *delete;
00365 {
00366 int x;
00367 basic_block bb;
00368
00369 FOR_EACH_BB (bb)
00370 sbitmap_difference (delete[bb->index], antloc[bb->index], laterin[bb->index]);
00371
00372 for (x = 0; x < NUM_EDGES (edge_list); x++)
00373 {
00374 basic_block b = INDEX_EDGE_SUCC_BB (edge_list, x);
00375
00376 if (b == EXIT_BLOCK_PTR)
00377 sbitmap_difference (insert[x], later[x], laterin[last_basic_block]);
00378 else
00379 sbitmap_difference (insert[x], later[x], laterin[b->index]);
00380 }
00381 }
00382
00383
00384
00385
00386
00387 struct edge_list *
00388 pre_edge_lcm (file, n_exprs, transp, avloc, antloc, kill, insert, delete)
00389 FILE *file ATTRIBUTE_UNUSED;
00390 int n_exprs;
00391 sbitmap *transp;
00392 sbitmap *avloc;
00393 sbitmap *antloc;
00394 sbitmap *kill;
00395 sbitmap **insert;
00396 sbitmap **delete;
00397 {
00398 sbitmap *antin, *antout, *earliest;
00399 sbitmap *avin, *avout;
00400 sbitmap *later, *laterin;
00401 struct edge_list *edge_list;
00402 int num_edges;
00403
00404 edge_list = create_edge_list ();
00405 num_edges = NUM_EDGES (edge_list);
00406
00407 #ifdef LCM_DEBUG_INFO
00408 if (file)
00409 {
00410 fprintf (file, "Edge List:\n");
00411 verify_edge_list (file, edge_list);
00412 print_edge_list (file, edge_list);
00413 dump_sbitmap_vector (file, "transp", "", transp, last_basic_block);
00414 dump_sbitmap_vector (file, "antloc", "", antloc, last_basic_block);
00415 dump_sbitmap_vector (file, "avloc", "", avloc, last_basic_block);
00416 dump_sbitmap_vector (file, "kill", "", kill, last_basic_block);
00417 }
00418 #endif
00419
00420
00421 avin = sbitmap_vector_alloc (last_basic_block, n_exprs);
00422 avout = sbitmap_vector_alloc (last_basic_block, n_exprs);
00423 compute_available (avloc, kill, avout, avin);
00424 sbitmap_vector_free (avin);
00425
00426
00427 antin = sbitmap_vector_alloc (last_basic_block, n_exprs);
00428 antout = sbitmap_vector_alloc (last_basic_block, n_exprs);
00429 compute_antinout_edge (antloc, transp, antin, antout);
00430
00431 #ifdef LCM_DEBUG_INFO
00432 if (file)
00433 {
00434 dump_sbitmap_vector (file, "antin", "", antin, last_basic_block);
00435 dump_sbitmap_vector (file, "antout", "", antout, last_basic_block);
00436 }
00437 #endif
00438
00439
00440 earliest = sbitmap_vector_alloc (num_edges, n_exprs);
00441 compute_earliest (edge_list, n_exprs, antin, antout, avout, kill, earliest);
00442
00443 #ifdef LCM_DEBUG_INFO
00444 if (file)
00445 dump_sbitmap_vector (file, "earliest", "", earliest, num_edges);
00446 #endif
00447
00448 sbitmap_vector_free (antout);
00449 sbitmap_vector_free (antin);
00450 sbitmap_vector_free (avout);
00451
00452 later = sbitmap_vector_alloc (num_edges, n_exprs);
00453
00454
00455 laterin = sbitmap_vector_alloc (last_basic_block + 1, n_exprs);
00456 compute_laterin (edge_list, earliest, antloc, later, laterin);
00457
00458 #ifdef LCM_DEBUG_INFO
00459 if (file)
00460 {
00461 dump_sbitmap_vector (file, "laterin", "", laterin, last_basic_block + 1);
00462 dump_sbitmap_vector (file, "later", "", later, num_edges);
00463 }
00464 #endif
00465
00466 sbitmap_vector_free (earliest);
00467
00468 *insert = sbitmap_vector_alloc (num_edges, n_exprs);
00469 *delete = sbitmap_vector_alloc (last_basic_block, n_exprs);
00470 compute_insert_delete (edge_list, antloc, later, laterin, *insert, *delete);
00471
00472 sbitmap_vector_free (laterin);
00473 sbitmap_vector_free (later);
00474
00475 #ifdef LCM_DEBUG_INFO
00476 if (file)
00477 {
00478 dump_sbitmap_vector (file, "pre_insert_map", "", *insert, num_edges);
00479 dump_sbitmap_vector (file, "pre_delete_map", "", *delete,
00480 last_basic_block);
00481 }
00482 #endif
00483
00484 return edge_list;
00485 }
00486
00487
00488
00489
00490 void
00491 compute_available (avloc, kill, avout, avin)
00492 sbitmap *avloc, *kill, *avout, *avin;
00493 {
00494 edge e;
00495 basic_block *worklist, *qin, *qout, *qend, bb;
00496 unsigned int qlen;
00497
00498
00499
00500
00501 qin = qout = worklist
00502 = (basic_block *) xmalloc (sizeof (basic_block) * n_basic_blocks);
00503
00504
00505 sbitmap_vector_ones (avout, last_basic_block);
00506
00507
00508
00509 FOR_EACH_BB (bb)
00510 {
00511 *qin++ = bb;
00512 bb->aux = bb;
00513 }
00514
00515 qin = worklist;
00516 qend = &worklist[n_basic_blocks];
00517 qlen = n_basic_blocks;
00518
00519
00520
00521 for (e = ENTRY_BLOCK_PTR->succ; e; e = e->succ_next)
00522 e->dest->aux = ENTRY_BLOCK_PTR;
00523
00524
00525 while (qlen)
00526 {
00527
00528 bb = *qout++;
00529 qlen--;
00530
00531 if (qout >= qend)
00532 qout = worklist;
00533
00534
00535
00536
00537 if (bb->aux == ENTRY_BLOCK_PTR)
00538
00539
00540 sbitmap_zero (avin[bb->index]);
00541 else
00542 {
00543
00544
00545 bb->aux = NULL;
00546 sbitmap_intersection_of_preds (avin[bb->index], avout, bb->index);
00547 }
00548
00549 if (sbitmap_union_of_diff_cg (avout[bb->index], avloc[bb->index], avin[bb->index], kill[bb->index]))
00550
00551
00552
00553 for (e = bb->succ; e; e = e->succ_next)
00554 if (!e->dest->aux && e->dest != EXIT_BLOCK_PTR)
00555 {
00556 *qin++ = e->dest;
00557 e->dest->aux = e;
00558 qlen++;
00559
00560 if (qin >= qend)
00561 qin = worklist;
00562 }
00563 }
00564
00565 clear_aux_for_edges ();
00566 clear_aux_for_blocks ();
00567 free (worklist);
00568 }
00569
00570
00571
00572 static void
00573 compute_farthest (edge_list, n_exprs, st_avout, st_avin, st_antin,
00574 kill, farthest)
00575 struct edge_list *edge_list;
00576 int n_exprs;
00577 sbitmap *st_avout, *st_avin, *st_antin, *kill, *farthest;
00578 {
00579 sbitmap difference, temp_bitmap;
00580 int x, num_edges;
00581 basic_block pred, succ;
00582
00583 num_edges = NUM_EDGES (edge_list);
00584
00585 difference = sbitmap_alloc (n_exprs);
00586 temp_bitmap = sbitmap_alloc (n_exprs);
00587
00588 for (x = 0; x < num_edges; x++)
00589 {
00590 pred = INDEX_EDGE_PRED_BB (edge_list, x);
00591 succ = INDEX_EDGE_SUCC_BB (edge_list, x);
00592 if (succ == EXIT_BLOCK_PTR)
00593 sbitmap_copy (farthest[x], st_avout[pred->index]);
00594 else
00595 {
00596 if (pred == ENTRY_BLOCK_PTR)
00597 sbitmap_zero (farthest[x]);
00598 else
00599 {
00600 sbitmap_difference (difference, st_avout[pred->index],
00601 st_antin[succ->index]);
00602 sbitmap_not (temp_bitmap, st_avin[succ->index]);
00603 sbitmap_a_and_b_or_c (farthest[x], difference,
00604 kill[succ->index], temp_bitmap);
00605 }
00606 }
00607 }
00608
00609 sbitmap_free (temp_bitmap);
00610 sbitmap_free (difference);
00611 }
00612
00613
00614
00615
00616
00617
00618 static void
00619 compute_nearerout (edge_list, farthest, st_avloc, nearer, nearerout)
00620 struct edge_list *edge_list;
00621 sbitmap *farthest, *st_avloc, *nearer, *nearerout;
00622 {
00623 int num_edges, i;
00624 edge e;
00625 basic_block *worklist, *tos, bb;
00626
00627 num_edges = NUM_EDGES (edge_list);
00628
00629
00630
00631
00632 tos = worklist
00633 = (basic_block *) xmalloc (sizeof (basic_block) * (n_basic_blocks + 1));
00634
00635
00636
00637 for (i = 0; i < num_edges; i++)
00638 INDEX_EDGE (edge_list, i)->aux = (void *) (size_t) i;
00639
00640
00641 sbitmap_vector_ones (nearer, num_edges);
00642
00643
00644
00645
00646
00647 for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
00648 sbitmap_copy (nearer[(size_t)e->aux], farthest[(size_t)e->aux]);
00649
00650
00651
00652 FOR_EACH_BB (bb)
00653 {
00654 *tos++ = bb;
00655 bb->aux = bb;
00656 }
00657
00658
00659 while (tos != worklist)
00660 {
00661
00662 bb = *--tos;
00663 bb->aux = NULL;
00664
00665
00666 sbitmap_ones (nearerout[bb->index]);
00667 for (e = bb->succ; e != NULL; e = e->succ_next)
00668 sbitmap_a_and_b (nearerout[bb->index], nearerout[bb->index],
00669 nearer[(size_t) e->aux]);
00670
00671
00672 for (e = bb->pred; e != NULL; e = e->pred_next)
00673 if (sbitmap_union_of_diff_cg (nearer[(size_t) e->aux],
00674 farthest[(size_t) e->aux],
00675 nearerout[e->dest->index],
00676 st_avloc[e->dest->index])
00677
00678
00679 && e->src != ENTRY_BLOCK_PTR && e->src->aux == 0)
00680 {
00681 *tos++ = e->src;
00682 e->src->aux = e;
00683 }
00684 }
00685
00686
00687
00688
00689 sbitmap_ones (nearerout[last_basic_block]);
00690 for (e = ENTRY_BLOCK_PTR->succ; e != NULL; e = e->succ_next)
00691 sbitmap_a_and_b (nearerout[last_basic_block],
00692 nearerout[last_basic_block],
00693 nearer[(size_t) e->aux]);
00694
00695 clear_aux_for_edges ();
00696 free (tos);
00697 }
00698
00699
00700
00701 static void
00702 compute_rev_insert_delete (edge_list, st_avloc, nearer, nearerout,
00703 insert, delete)
00704 struct edge_list *edge_list;
00705 sbitmap *st_avloc, *nearer, *nearerout, *insert, *delete;
00706 {
00707 int x;
00708 basic_block bb;
00709
00710 FOR_EACH_BB (bb)
00711 sbitmap_difference (delete[bb->index], st_avloc[bb->index], nearerout[bb->index]);
00712
00713 for (x = 0; x < NUM_EDGES (edge_list); x++)
00714 {
00715 basic_block b = INDEX_EDGE_PRED_BB (edge_list, x);
00716 if (b == ENTRY_BLOCK_PTR)
00717 sbitmap_difference (insert[x], nearer[x], nearerout[last_basic_block]);
00718 else
00719 sbitmap_difference (insert[x], nearer[x], nearerout[b->index]);
00720 }
00721 }
00722
00723
00724
00725
00726
00727
00728 struct edge_list *
00729 pre_edge_rev_lcm (file, n_exprs, transp, st_avloc, st_antloc, kill,
00730 insert, delete)
00731 FILE *file ATTRIBUTE_UNUSED;
00732 int n_exprs;
00733 sbitmap *transp;
00734 sbitmap *st_avloc;
00735 sbitmap *st_antloc;
00736 sbitmap *kill;
00737 sbitmap **insert;
00738 sbitmap **delete;
00739 {
00740 sbitmap *st_antin, *st_antout;
00741 sbitmap *st_avout, *st_avin, *farthest;
00742 sbitmap *nearer, *nearerout;
00743 struct edge_list *edge_list;
00744 int num_edges;
00745
00746 edge_list = create_edge_list ();
00747 num_edges = NUM_EDGES (edge_list);
00748
00749 st_antin = (sbitmap *) sbitmap_vector_alloc (last_basic_block, n_exprs);
00750 st_antout = (sbitmap *) sbitmap_vector_alloc (last_basic_block, n_exprs);
00751 sbitmap_vector_zero (st_antin, last_basic_block);
00752 sbitmap_vector_zero (st_antout, last_basic_block);
00753 compute_antinout_edge (st_antloc, transp, st_antin, st_antout);
00754
00755
00756 st_avout = sbitmap_vector_alloc (last_basic_block, n_exprs);
00757 st_avin = sbitmap_vector_alloc (last_basic_block, n_exprs);
00758 compute_available (st_avloc, kill, st_avout, st_avin);
00759
00760 #ifdef LCM_DEBUG_INFO
00761 if (file)
00762 {
00763 fprintf (file, "Edge List:\n");
00764 verify_edge_list (file, edge_list);
00765 print_edge_list (file, edge_list);
00766 dump_sbitmap_vector (file, "transp", "", transp, last_basic_block);
00767 dump_sbitmap_vector (file, "st_avloc", "", st_avloc, last_basic_block);
00768 dump_sbitmap_vector (file, "st_antloc", "", st_antloc, last_basic_block);
00769 dump_sbitmap_vector (file, "st_antin", "", st_antin, last_basic_block);
00770 dump_sbitmap_vector (file, "st_antout", "", st_antout, last_basic_block);
00771 dump_sbitmap_vector (file, "st_kill", "", kill, last_basic_block);
00772 }
00773 #endif
00774
00775 #ifdef LCM_DEBUG_INFO
00776 if (file)
00777 {
00778 dump_sbitmap_vector (file, "st_avout", "", st_avout, last_basic_block);
00779 dump_sbitmap_vector (file, "st_avin", "", st_avin, last_basic_block);
00780 }
00781 #endif
00782
00783
00784 farthest = sbitmap_vector_alloc (num_edges, n_exprs);
00785 compute_farthest (edge_list, n_exprs, st_avout, st_avin, st_antin,
00786 kill, farthest);
00787
00788 #ifdef LCM_DEBUG_INFO
00789 if (file)
00790 dump_sbitmap_vector (file, "farthest", "", farthest, num_edges);
00791 #endif
00792
00793 sbitmap_vector_free (st_antin);
00794 sbitmap_vector_free (st_antout);
00795
00796 sbitmap_vector_free (st_avin);
00797 sbitmap_vector_free (st_avout);
00798
00799 nearer = sbitmap_vector_alloc (num_edges, n_exprs);
00800
00801
00802 nearerout = sbitmap_vector_alloc (last_basic_block + 1, n_exprs);
00803 compute_nearerout (edge_list, farthest, st_avloc, nearer, nearerout);
00804
00805 #ifdef LCM_DEBUG_INFO
00806 if (file)
00807 {
00808 dump_sbitmap_vector (file, "nearerout", "", nearerout,
00809 last_basic_block + 1);
00810 dump_sbitmap_vector (file, "nearer", "", nearer, num_edges);
00811 }
00812 #endif
00813
00814 sbitmap_vector_free (farthest);
00815
00816 *insert = sbitmap_vector_alloc (num_edges, n_exprs);
00817 *delete = sbitmap_vector_alloc (last_basic_block, n_exprs);
00818 compute_rev_insert_delete (edge_list, st_avloc, nearer, nearerout,
00819 *insert, *delete);
00820
00821 sbitmap_vector_free (nearerout);
00822 sbitmap_vector_free (nearer);
00823
00824 #ifdef LCM_DEBUG_INFO
00825 if (file)
00826 {
00827 dump_sbitmap_vector (file, "pre_insert_map", "", *insert, num_edges);
00828 dump_sbitmap_vector (file, "pre_delete_map", "", *delete,
00829 last_basic_block);
00830 }
00831 #endif
00832 return edge_list;
00833 }
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863 struct seginfo
00864 {
00865 int mode;
00866 rtx insn_ptr;
00867 int bbnum;
00868 struct seginfo *next;
00869 HARD_REG_SET regs_live;
00870 };
00871
00872 struct bb_info
00873 {
00874 struct seginfo *seginfo;
00875 int computing;
00876 };
00877
00878
00879
00880 #ifdef OPTIMIZE_MODE_SWITCHING
00881 static sbitmap *antic;
00882 static sbitmap *transp;
00883 static sbitmap *comp;
00884 static sbitmap *delete;
00885 static sbitmap *insert;
00886
00887 static struct seginfo * new_seginfo PARAMS ((int, rtx, int, HARD_REG_SET));
00888 static void add_seginfo PARAMS ((struct bb_info *, struct seginfo *));
00889 static void reg_dies PARAMS ((rtx, HARD_REG_SET));
00890 static void reg_becomes_live PARAMS ((rtx, rtx, void *));
00891 static void make_preds_opaque PARAMS ((basic_block, int));
00892 #endif
00893
00894 #ifdef OPTIMIZE_MODE_SWITCHING
00895
00896
00897
00898
00899 static struct seginfo *
00900 new_seginfo (mode, insn, bb, regs_live)
00901 int mode;
00902 rtx insn;
00903 int bb;
00904 HARD_REG_SET regs_live;
00905 {
00906 struct seginfo *ptr;
00907 ptr = xmalloc (sizeof (struct seginfo));
00908 ptr->mode = mode;
00909 ptr->insn_ptr = insn;
00910 ptr->bbnum = bb;
00911 ptr->next = NULL;
00912 COPY_HARD_REG_SET (ptr->regs_live, regs_live);
00913 return ptr;
00914 }
00915
00916
00917
00918
00919
00920 static void
00921 add_seginfo (head, info)
00922 struct bb_info *head;
00923 struct seginfo *info;
00924 {
00925 struct seginfo *ptr;
00926
00927 if (head->seginfo == NULL)
00928 head->seginfo = info;
00929 else
00930 {
00931 ptr = head->seginfo;
00932 while (ptr->next != NULL)
00933 ptr = ptr->next;
00934 ptr->next = info;
00935 }
00936 }
00937
00938
00939
00940
00941
00942
00943
00944 static void
00945 make_preds_opaque (b, j)
00946 basic_block b;
00947 int j;
00948 {
00949 edge e;
00950
00951 for (e = b->pred; e; e = e->pred_next)
00952 {
00953 basic_block pb = e->src;
00954
00955 if (e->aux || ! TEST_BIT (transp[pb->index], j))
00956 continue;
00957
00958 RESET_BIT (transp[pb->index], j);
00959 make_preds_opaque (pb, j);
00960 }
00961 }
00962
00963
00964
00965 static void
00966 reg_dies (reg, live)
00967 rtx reg;
00968 HARD_REG_SET live;
00969 {
00970 int regno, nregs;
00971
00972 if (GET_CODE (reg) != REG)
00973 return;
00974
00975 regno = REGNO (reg);
00976 if (regno < FIRST_PSEUDO_REGISTER)
00977 for (nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg)) - 1; nregs >= 0;
00978 nregs--)
00979 CLEAR_HARD_REG_BIT (live, regno + nregs);
00980 }
00981
00982
00983
00984
00985 static void
00986 reg_becomes_live (reg, setter, live)
00987 rtx reg;
00988 rtx setter ATTRIBUTE_UNUSED;
00989 void *live;
00990 {
00991 int regno, nregs;
00992
00993 if (GET_CODE (reg) == SUBREG)
00994 reg = SUBREG_REG (reg);
00995
00996 if (GET_CODE (reg) != REG)
00997 return;
00998
00999 regno = REGNO (reg);
01000 if (regno < FIRST_PSEUDO_REGISTER)
01001 for (nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg)) - 1; nregs >= 0;
01002 nregs--)
01003 SET_HARD_REG_BIT (* (HARD_REG_SET *) live, regno + nregs);
01004 }
01005
01006
01007
01008
01009 int
01010 optimize_mode_switching (file)
01011 FILE *file;
01012 {
01013 rtx insn;
01014 int e;
01015 basic_block bb;
01016 int need_commit = 0;
01017 sbitmap *kill;
01018 struct edge_list *edge_list;
01019 static const int num_modes[] = NUM_MODES_FOR_MODE_SWITCHING;
01020 #define N_ENTITIES ARRAY_SIZE (num_modes)
01021 int entity_map[N_ENTITIES];
01022 struct bb_info *bb_info[N_ENTITIES];
01023 int i, j;
01024 int n_entities;
01025 int max_num_modes = 0;
01026 bool emited = false;
01027 basic_block post_entry ATTRIBUTE_UNUSED, pre_exit ATTRIBUTE_UNUSED;
01028
01029 clear_bb_flags ();
01030
01031 for (e = N_ENTITIES - 1, n_entities = 0; e >= 0; e--)
01032 if (OPTIMIZE_MODE_SWITCHING (e))
01033 {
01034 int entry_exit_extra = 0;
01035
01036
01037
01038
01039 #ifdef NORMAL_MODE
01040 entry_exit_extra = 2;
01041 #endif
01042 bb_info[n_entities]
01043 = (struct bb_info *) xcalloc (last_basic_block + entry_exit_extra,
01044 sizeof **bb_info);
01045 entity_map[n_entities++] = e;
01046 if (num_modes[e] > max_num_modes)
01047 max_num_modes = num_modes[e];
01048 }
01049
01050 if (! n_entities)
01051 return 0;
01052
01053 #ifdef NORMAL_MODE
01054 {
01055
01056
01057
01058 edge eg;
01059 post_entry = split_edge (ENTRY_BLOCK_PTR->succ);
01060
01061
01062
01063 for (pre_exit = 0, eg = EXIT_BLOCK_PTR->pred; eg; eg = eg->pred_next)
01064 if (eg->flags & EDGE_FALLTHRU)
01065 {
01066 regset live_at_end = eg->src->global_live_at_end;
01067
01068 if (pre_exit)
01069 abort ();
01070 pre_exit = split_edge (eg);
01071 COPY_REG_SET (pre_exit->global_live_at_start, live_at_end);
01072 COPY_REG_SET (pre_exit->global_live_at_end, live_at_end);
01073 }
01074 }
01075 #endif
01076
01077
01078
01079 antic = sbitmap_vector_alloc (last_basic_block, n_entities);
01080 transp = sbitmap_vector_alloc (last_basic_block, n_entities);
01081 comp = sbitmap_vector_alloc (last_basic_block, n_entities);
01082
01083 sbitmap_vector_ones (transp, last_basic_block);
01084
01085 for (j = n_entities - 1; j >= 0; j--)
01086 {
01087 int e = entity_map[j];
01088 int no_mode = num_modes[e];
01089 struct bb_info *info = bb_info[j];
01090
01091
01092
01093
01094 FOR_EACH_BB (bb)
01095 {
01096 struct seginfo *ptr;
01097 int last_mode = no_mode;
01098 HARD_REG_SET live_now;
01099
01100 REG_SET_TO_HARD_REG_SET (live_now,
01101 bb->global_live_at_start);
01102 for (insn = bb->head;
01103 insn != NULL && insn != NEXT_INSN (bb->end);
01104 insn = NEXT_INSN (insn))
01105 {
01106 if (INSN_P (insn))
01107 {
01108 int mode = MODE_NEEDED (e, insn);
01109 rtx link;
01110
01111 if (mode != no_mode && mode != last_mode)
01112 {
01113 last_mode = mode;
01114 ptr = new_seginfo (mode, insn, bb->index, live_now);
01115 add_seginfo (info + bb->index, ptr);
01116 RESET_BIT (transp[bb->index], j);
01117 }
01118
01119
01120 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
01121 if (REG_NOTE_KIND (link) == REG_DEAD)
01122 reg_dies (XEXP (link, 0), live_now);
01123
01124 note_stores (PATTERN (insn), reg_becomes_live, &live_now);
01125 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
01126 if (REG_NOTE_KIND (link) == REG_UNUSED)
01127 reg_dies (XEXP (link, 0), live_now);
01128 }
01129 }
01130
01131 info[bb->index].computing = last_mode;
01132
01133 if (last_mode == no_mode)
01134 {
01135 ptr = new_seginfo (no_mode, bb->end, bb->index, live_now);
01136 add_seginfo (info + bb->index, ptr);
01137 }
01138 }
01139 #ifdef NORMAL_MODE
01140 {
01141 int mode = NORMAL_MODE (e);
01142
01143 if (mode != no_mode)
01144 {
01145 bb = post_entry;
01146
01147
01148
01149
01150
01151 RESET_BIT (transp[bb->index], j);
01152
01153
01154
01155
01156 info[bb->index].computing = mode;
01157
01158 if (pre_exit)
01159 info[pre_exit->index].seginfo->mode = mode;
01160 }
01161 }
01162 #endif
01163 }
01164
01165 kill = sbitmap_vector_alloc (last_basic_block, n_entities);
01166 for (i = 0; i < max_num_modes; i++)
01167 {
01168 int current_mode[N_ENTITIES];
01169
01170
01171 sbitmap_vector_zero (antic, last_basic_block);
01172 sbitmap_vector_zero (comp, last_basic_block);
01173 for (j = n_entities - 1; j >= 0; j--)
01174 {
01175 int m = current_mode[j] = MODE_PRIORITY_TO_MODE (entity_map[j], i);
01176 struct bb_info *info = bb_info[j];
01177
01178 FOR_EACH_BB (bb)
01179 {
01180 if (info[bb->index].seginfo->mode == m)
01181 SET_BIT (antic[bb->index], j);
01182
01183 if (info[bb->index].computing == m)
01184 SET_BIT (comp[bb->index], j);
01185 }
01186 }
01187
01188
01189
01190
01191 FOR_EACH_BB (bb)
01192 sbitmap_not (kill[bb->index], transp[bb->index]);
01193 edge_list = pre_edge_lcm (file, 1, transp, comp, antic,
01194 kill, &insert, &delete);
01195
01196 for (j = n_entities - 1; j >= 0; j--)
01197 {
01198
01199 int no_mode = num_modes[entity_map[j]];
01200
01201
01202
01203
01204
01205
01206
01207
01208 for (e = NUM_EDGES (edge_list) - 1; e >= 0; e--)
01209 {
01210 edge eg = INDEX_EDGE (edge_list, e);
01211 int mode;
01212 basic_block src_bb;
01213 HARD_REG_SET live_at_edge;
01214 rtx mode_set;
01215
01216 eg->aux = 0;
01217
01218 if (! TEST_BIT (insert[e], j))
01219 continue;
01220
01221 eg->aux = (void *)1;
01222
01223 mode = current_mode[j];
01224 src_bb = eg->src;
01225
01226 REG_SET_TO_HARD_REG_SET (live_at_edge,
01227 src_bb->global_live_at_end);
01228
01229 start_sequence ();
01230 EMIT_MODE_SET (entity_map[j], mode, live_at_edge);
01231 mode_set = get_insns ();
01232 end_sequence ();
01233
01234
01235 if (mode_set == NULL_RTX)
01236 continue;
01237
01238
01239
01240 if (eg->flags & EDGE_ABNORMAL)
01241 {
01242 emited = true;
01243 if (GET_CODE (src_bb->end) == JUMP_INSN)
01244 emit_insn_before (mode_set, src_bb->end);
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256 else if (GET_CODE (src_bb->end) == INSN)
01257 emit_insn_after (mode_set, src_bb->end);
01258 else
01259 abort ();
01260 bb_info[j][src_bb->index].computing = mode;
01261 RESET_BIT (transp[src_bb->index], j);
01262 }
01263 else
01264 {
01265 need_commit = 1;
01266 insert_insn_on_edge (mode_set, eg);
01267 }
01268 }
01269
01270 FOR_EACH_BB_REVERSE (bb)
01271 if (TEST_BIT (delete[bb->index], j))
01272 {
01273 make_preds_opaque (bb, j);
01274
01275 bb_info[j][bb->index].seginfo->mode = no_mode;
01276 }
01277 }
01278
01279 clear_aux_for_edges ();
01280 free_edge_list (edge_list);
01281 }
01282
01283
01284 for (j = n_entities - 1; j >= 0; j--)
01285 {
01286 int no_mode = num_modes[entity_map[j]];
01287
01288 FOR_EACH_BB_REVERSE (bb)
01289 {
01290 struct seginfo *ptr, *next;
01291 for (ptr = bb_info[j][bb->index].seginfo; ptr; ptr = next)
01292 {
01293 next = ptr->next;
01294 if (ptr->mode != no_mode)
01295 {
01296 rtx mode_set;
01297
01298 start_sequence ();
01299 EMIT_MODE_SET (entity_map[j], ptr->mode, ptr->regs_live);
01300 mode_set = get_insns ();
01301 end_sequence ();
01302
01303
01304 if (mode_set == NULL_RTX)
01305 continue;
01306
01307 emited = true;
01308 if (GET_CODE (ptr->insn_ptr) == NOTE
01309 && (NOTE_LINE_NUMBER (ptr->insn_ptr)
01310 == NOTE_INSN_BASIC_BLOCK))
01311 emit_insn_after (mode_set, ptr->insn_ptr);
01312 else
01313 emit_insn_before (mode_set, ptr->insn_ptr);
01314 }
01315
01316 free (ptr);
01317 }
01318 }
01319
01320 free (bb_info[j]);
01321 }
01322
01323
01324
01325 sbitmap_vector_free (kill);
01326 sbitmap_vector_free (antic);
01327 sbitmap_vector_free (transp);
01328 sbitmap_vector_free (comp);
01329 sbitmap_vector_free (delete);
01330 sbitmap_vector_free (insert);
01331
01332 if (need_commit)
01333 commit_edge_insertions ();
01334
01335 #ifdef NORMAL_MODE
01336 cleanup_cfg (CLEANUP_NO_INSN_DEL);
01337 #else
01338 if (!need_commit && !emited)
01339 return 0;
01340 #endif
01341
01342 max_regno = max_reg_num ();
01343 allocate_reg_info (max_regno, FALSE, FALSE);
01344 update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
01345 (PROP_DEATH_NOTES | PROP_KILL_DEAD_CODE
01346 | PROP_SCAN_DEAD_CODE));
01347
01348 return 1;
01349 }
01350 #endif