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 #include "config.h"
00039 #include "system.h"
00040 #include "coretypes.h"
00041 #include "tm.h"
00042 #include "rtl.h"
00043 #include "tm_p.h"
00044 #include "hard-reg-set.h"
00045 #include "obstack.h"
00046 #include "basic-block.h"
00047 #include "cfgloop.h"
00048 #include "expr.h"
00049 #include "recog.h"
00050 #include "output.h"
00051 #include "function.h"
00052 #include "flags.h"
00053 #include "df.h"
00054 #include "hashtab.h"
00055 #include "except.h"
00056
00057
00058
00059 struct loop_data
00060 {
00061 struct loop *outermost_exit;
00062 bool has_call;
00063 };
00064
00065 #define LOOP_DATA(LOOP) ((struct loop_data *) (LOOP)->aux)
00066
00067
00068
00069 struct use
00070 {
00071 rtx *pos;
00072 rtx insn;
00073
00074 struct use *next;
00075 };
00076
00077
00078
00079 struct def
00080 {
00081 struct use *uses;
00082
00083 unsigned n_uses;
00084 unsigned invno;
00085 };
00086
00087
00088
00089 struct invariant
00090 {
00091
00092 unsigned invno;
00093
00094
00095 unsigned eqto;
00096
00097
00098
00099 rtx reg;
00100
00101
00102 struct def *def;
00103
00104
00105 rtx insn;
00106
00107
00108 bool always_executed;
00109
00110
00111 bool move;
00112
00113
00114 unsigned cost;
00115
00116
00117 bitmap depends_on;
00118
00119
00120
00121 unsigned stamp;
00122 };
00123
00124
00125
00126 struct invariant_expr_entry
00127 {
00128
00129 struct invariant *inv;
00130
00131
00132 rtx expr;
00133
00134
00135 enum machine_mode mode;
00136
00137
00138 hashval_t hash;
00139 };
00140
00141
00142
00143
00144 static unsigned actual_stamp;
00145
00146 typedef struct invariant *invariant_p;
00147
00148 DEF_VEC_P(invariant_p);
00149 DEF_VEC_ALLOC_P(invariant_p, heap);
00150
00151
00152
00153 static VEC(invariant_p,heap) *invariants;
00154
00155
00156
00157 static struct df *df = NULL;
00158
00159
00160
00161 static bool
00162 check_maybe_invariant (rtx x)
00163 {
00164 enum rtx_code code = GET_CODE (x);
00165 int i, j;
00166 const char *fmt;
00167
00168 switch (code)
00169 {
00170 case CONST_INT:
00171 case CONST_DOUBLE:
00172 case SYMBOL_REF:
00173 case CONST:
00174 case LABEL_REF:
00175 return true;
00176
00177 case PC:
00178 case CC0:
00179 case UNSPEC_VOLATILE:
00180 case CALL:
00181 return false;
00182
00183 case REG:
00184 return true;
00185
00186 case MEM:
00187
00188
00189
00190
00191
00192 if (MEM_READONLY_P (x))
00193 break;
00194
00195 return false;
00196
00197 case ASM_OPERANDS:
00198
00199 if (MEM_VOLATILE_P (x))
00200 return false;
00201 break;
00202
00203 default:
00204 break;
00205 }
00206
00207 fmt = GET_RTX_FORMAT (code);
00208 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00209 {
00210 if (fmt[i] == 'e')
00211 {
00212 if (!check_maybe_invariant (XEXP (x, i)))
00213 return false;
00214 }
00215 else if (fmt[i] == 'E')
00216 {
00217 for (j = 0; j < XVECLEN (x, i); j++)
00218 if (!check_maybe_invariant (XVECEXP (x, i, j)))
00219 return false;
00220 }
00221 }
00222
00223 return true;
00224 }
00225
00226
00227
00228
00229 static struct invariant *
00230 invariant_for_use (struct df_ref *use)
00231 {
00232 struct df_link *defs;
00233 struct df_ref *def;
00234 basic_block bb = BLOCK_FOR_INSN (use->insn), def_bb;
00235
00236 if (use->flags & DF_REF_READ_WRITE)
00237 return NULL;
00238
00239 defs = DF_REF_CHAIN (use);
00240 if (!defs || defs->next)
00241 return NULL;
00242 def = defs->ref;
00243 if (!DF_REF_DATA (def))
00244 return NULL;
00245
00246 def_bb = DF_REF_BB (def);
00247 if (!dominated_by_p (CDI_DOMINATORS, bb, def_bb))
00248 return NULL;
00249 return DF_REF_DATA (def);
00250 }
00251
00252
00253
00254 static hashval_t
00255 hash_invariant_expr_1 (rtx insn, rtx x)
00256 {
00257 enum rtx_code code = GET_CODE (x);
00258 int i, j;
00259 const char *fmt;
00260 hashval_t val = code;
00261 int do_not_record_p;
00262 struct df_ref *use;
00263 struct invariant *inv;
00264
00265 switch (code)
00266 {
00267 case CONST_INT:
00268 case CONST_DOUBLE:
00269 case SYMBOL_REF:
00270 case CONST:
00271 case LABEL_REF:
00272 return hash_rtx (x, GET_MODE (x), &do_not_record_p, NULL, false);
00273
00274 case REG:
00275 use = df_find_use (df, insn, x);
00276 if (!use)
00277 return hash_rtx (x, GET_MODE (x), &do_not_record_p, NULL, false);
00278 inv = invariant_for_use (use);
00279 if (!inv)
00280 return hash_rtx (x, GET_MODE (x), &do_not_record_p, NULL, false);
00281
00282 gcc_assert (inv->eqto != ~0u);
00283 return inv->eqto;
00284
00285 default:
00286 break;
00287 }
00288
00289 fmt = GET_RTX_FORMAT (code);
00290 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00291 {
00292 if (fmt[i] == 'e')
00293 val ^= hash_invariant_expr_1 (insn, XEXP (x, i));
00294 else if (fmt[i] == 'E')
00295 {
00296 for (j = 0; j < XVECLEN (x, i); j++)
00297 val ^= hash_invariant_expr_1 (insn, XVECEXP (x, i, j));
00298 }
00299 else if (fmt[i] == 'i' || fmt[i] == 'n')
00300 val ^= XINT (x, i);
00301 }
00302
00303 return val;
00304 }
00305
00306
00307
00308
00309 static bool
00310 invariant_expr_equal_p (rtx insn1, rtx e1, rtx insn2, rtx e2)
00311 {
00312 enum rtx_code code = GET_CODE (e1);
00313 int i, j;
00314 const char *fmt;
00315 struct df_ref *use1, *use2;
00316 struct invariant *inv1 = NULL, *inv2 = NULL;
00317 rtx sub1, sub2;
00318
00319
00320
00321
00322 if (code != GET_CODE (e2) || GET_MODE (e1) != GET_MODE (e2))
00323 return false;
00324
00325 switch (code)
00326 {
00327 case CONST_INT:
00328 case CONST_DOUBLE:
00329 case SYMBOL_REF:
00330 case CONST:
00331 case LABEL_REF:
00332 return rtx_equal_p (e1, e2);
00333
00334 case REG:
00335 use1 = df_find_use (df, insn1, e1);
00336 use2 = df_find_use (df, insn2, e2);
00337 if (use1)
00338 inv1 = invariant_for_use (use1);
00339 if (use2)
00340 inv2 = invariant_for_use (use2);
00341
00342 if (!inv1 && !inv2)
00343 return rtx_equal_p (e1, e2);
00344
00345 if (!inv1 || !inv2)
00346 return false;
00347
00348 gcc_assert (inv1->eqto != ~0u);
00349 gcc_assert (inv2->eqto != ~0u);
00350 return inv1->eqto == inv2->eqto;
00351
00352 default:
00353 break;
00354 }
00355
00356 fmt = GET_RTX_FORMAT (code);
00357 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00358 {
00359 if (fmt[i] == 'e')
00360 {
00361 sub1 = XEXP (e1, i);
00362 sub2 = XEXP (e2, i);
00363
00364 if (!invariant_expr_equal_p (insn1, sub1, insn2, sub2))
00365 return false;
00366 }
00367
00368 else if (fmt[i] == 'E')
00369 {
00370 if (XVECLEN (e1, i) != XVECLEN (e2, i))
00371 return false;
00372
00373 for (j = 0; j < XVECLEN (e1, i); j++)
00374 {
00375 sub1 = XVECEXP (e1, i, j);
00376 sub2 = XVECEXP (e2, i, j);
00377
00378 if (!invariant_expr_equal_p (insn1, sub1, insn2, sub2))
00379 return false;
00380 }
00381 }
00382 else if (fmt[i] == 'i' || fmt[i] == 'n')
00383 {
00384 if (XINT (e1, i) != XINT (e2, i))
00385 return false;
00386 }
00387
00388 else
00389 return false;
00390 }
00391
00392 return true;
00393 }
00394
00395
00396
00397 static hashval_t
00398 hash_invariant_expr (const void *e)
00399 {
00400 const struct invariant_expr_entry *entry = e;
00401
00402 return entry->hash;
00403 }
00404
00405
00406
00407 static int
00408 eq_invariant_expr (const void *e1, const void *e2)
00409 {
00410 const struct invariant_expr_entry *entry1 = e1;
00411 const struct invariant_expr_entry *entry2 = e2;
00412
00413 if (entry1->mode != entry2->mode)
00414 return 0;
00415
00416 return invariant_expr_equal_p (entry1->inv->insn, entry1->expr,
00417 entry2->inv->insn, entry2->expr);
00418 }
00419
00420
00421
00422
00423
00424 static struct invariant *
00425 find_or_insert_inv (htab_t eq, rtx expr, enum machine_mode mode,
00426 struct invariant *inv)
00427 {
00428 hashval_t hash = hash_invariant_expr_1 (inv->insn, expr);
00429 struct invariant_expr_entry *entry;
00430 struct invariant_expr_entry pentry;
00431 PTR *slot;
00432
00433 pentry.expr = expr;
00434 pentry.inv = inv;
00435 pentry.mode = mode;
00436 slot = htab_find_slot_with_hash (eq, &pentry, hash, INSERT);
00437 entry = *slot;
00438
00439 if (entry)
00440 return entry->inv;
00441
00442 entry = XNEW (struct invariant_expr_entry);
00443 entry->inv = inv;
00444 entry->expr = expr;
00445 entry->mode = mode;
00446 entry->hash = hash;
00447 *slot = entry;
00448
00449 return inv;
00450 }
00451
00452
00453
00454
00455 static void
00456 find_identical_invariants (htab_t eq, struct invariant *inv)
00457 {
00458 unsigned depno;
00459 bitmap_iterator bi;
00460 struct invariant *dep;
00461 rtx expr, set;
00462 enum machine_mode mode;
00463
00464 if (inv->eqto != ~0u)
00465 return;
00466
00467 EXECUTE_IF_SET_IN_BITMAP (inv->depends_on, 0, depno, bi)
00468 {
00469 dep = VEC_index (invariant_p, invariants, depno);
00470 find_identical_invariants (eq, dep);
00471 }
00472
00473 set = single_set (inv->insn);
00474 expr = SET_SRC (set);
00475 mode = GET_MODE (expr);
00476 if (mode == VOIDmode)
00477 mode = GET_MODE (SET_DEST (set));
00478 inv->eqto = find_or_insert_inv (eq, expr, mode, inv)->invno;
00479
00480 if (dump_file && inv->eqto != inv->invno)
00481 fprintf (dump_file,
00482 "Invariant %d is equivalent to invariant %d.\n",
00483 inv->invno, inv->eqto);
00484 }
00485
00486
00487
00488 static void
00489 merge_identical_invariants (void)
00490 {
00491 unsigned i;
00492 struct invariant *inv;
00493 htab_t eq = htab_create (VEC_length (invariant_p, invariants),
00494 hash_invariant_expr, eq_invariant_expr, free);
00495
00496 for (i = 0; VEC_iterate (invariant_p, invariants, i, inv); i++)
00497 find_identical_invariants (eq, inv);
00498
00499 htab_delete (eq);
00500 }
00501
00502
00503
00504
00505
00506
00507
00508 static void
00509 compute_always_reached (struct loop *loop, basic_block *body,
00510 bitmap may_exit, bitmap always_reached)
00511 {
00512 unsigned i;
00513
00514 for (i = 0; i < loop->num_nodes; i++)
00515 {
00516 if (dominated_by_p (CDI_DOMINATORS, loop->latch, body[i]))
00517 bitmap_set_bit (always_reached, i);
00518
00519 if (bitmap_bit_p (may_exit, i))
00520 return;
00521 }
00522 }
00523
00524
00525
00526
00527
00528 static void
00529 find_exits (struct loop *loop, basic_block *body,
00530 bitmap may_exit, bitmap has_exit)
00531 {
00532 unsigned i;
00533 edge_iterator ei;
00534 edge e;
00535 struct loop *outermost_exit = loop, *aexit;
00536 bool has_call = false;
00537 rtx insn;
00538
00539 for (i = 0; i < loop->num_nodes; i++)
00540 {
00541 if (body[i]->loop_father == loop)
00542 {
00543 FOR_BB_INSNS (body[i], insn)
00544 {
00545 if (CALL_P (insn)
00546 && !CONST_OR_PURE_CALL_P (insn))
00547 {
00548 has_call = true;
00549 bitmap_set_bit (may_exit, i);
00550 break;
00551 }
00552 }
00553
00554 FOR_EACH_EDGE (e, ei, body[i]->succs)
00555 {
00556 if (flow_bb_inside_loop_p (loop, e->dest))
00557 continue;
00558
00559 bitmap_set_bit (may_exit, i);
00560 bitmap_set_bit (has_exit, i);
00561 outermost_exit = find_common_loop (outermost_exit,
00562 e->dest->loop_father);
00563 }
00564 continue;
00565 }
00566
00567
00568
00569
00570 if (body[i]->loop_father->header != body[i])
00571 continue;
00572
00573 if (LOOP_DATA (body[i]->loop_father)->has_call)
00574 {
00575 has_call = true;
00576 bitmap_set_bit (may_exit, i);
00577 }
00578 aexit = LOOP_DATA (body[i]->loop_father)->outermost_exit;
00579 if (aexit != loop)
00580 {
00581 bitmap_set_bit (may_exit, i);
00582 bitmap_set_bit (has_exit, i);
00583
00584 if (flow_loop_nested_p (aexit, outermost_exit))
00585 outermost_exit = aexit;
00586 }
00587 }
00588
00589 loop->aux = xcalloc (1, sizeof (struct loop_data));
00590 LOOP_DATA (loop)->outermost_exit = outermost_exit;
00591 LOOP_DATA (loop)->has_call = has_call;
00592 }
00593
00594
00595
00596 static bool
00597 may_assign_reg_p (rtx x)
00598 {
00599 return (GET_MODE (x) != VOIDmode
00600 && GET_MODE (x) != BLKmode
00601 && can_copy_p (GET_MODE (x))
00602 && (!REG_P (x)
00603 || !HARD_REGISTER_P (x)
00604 || REGNO_REG_CLASS (REGNO (x)) != NO_REGS));
00605 }
00606
00607
00608
00609
00610 static void
00611 find_defs (struct loop *loop, basic_block *body)
00612 {
00613 unsigned i;
00614 bitmap blocks = BITMAP_ALLOC (NULL);
00615
00616 for (i = 0; i < loop->num_nodes; i++)
00617 bitmap_set_bit (blocks, body[i]->index);
00618
00619 df_set_blocks (df, blocks);
00620 df_analyze (df);
00621 BITMAP_FREE (blocks);
00622 }
00623
00624
00625
00626
00627
00628
00629 static struct invariant *
00630 create_new_invariant (struct def *def, rtx insn, bitmap depends_on,
00631 bool always_executed)
00632 {
00633 struct invariant *inv = XNEW (struct invariant);
00634 rtx set = single_set (insn);
00635
00636 inv->def = def;
00637 inv->always_executed = always_executed;
00638 inv->depends_on = depends_on;
00639
00640
00641
00642 if (def)
00643 inv->cost = rtx_cost (set, SET);
00644 else
00645 inv->cost = rtx_cost (SET_SRC (set), SET);
00646
00647 inv->move = false;
00648 inv->reg = NULL_RTX;
00649 inv->stamp = 0;
00650 inv->insn = insn;
00651
00652 inv->invno = VEC_length (invariant_p, invariants);
00653 inv->eqto = ~0u;
00654 if (def)
00655 def->invno = inv->invno;
00656 VEC_safe_push (invariant_p, heap, invariants, inv);
00657
00658 if (dump_file)
00659 {
00660 fprintf (dump_file,
00661 "Set in insn %d is invariant (%d), cost %d, depends on ",
00662 INSN_UID (insn), inv->invno, inv->cost);
00663 dump_bitmap (dump_file, inv->depends_on);
00664 }
00665
00666 return inv;
00667 }
00668
00669
00670
00671 static void
00672 record_use (struct def *def, rtx *use, rtx insn)
00673 {
00674 struct use *u = XNEW (struct use);
00675
00676 if (GET_CODE (*use) == SUBREG)
00677 use = &SUBREG_REG (*use);
00678 gcc_assert (REG_P (*use));
00679
00680 u->pos = use;
00681 u->insn = insn;
00682 u->next = def->uses;
00683 def->uses = u;
00684 def->n_uses++;
00685 }
00686
00687
00688
00689
00690
00691 static bool
00692 check_dependencies (rtx insn, bitmap depends_on)
00693 {
00694 struct df_link *defs;
00695 struct df_ref *use, *def;
00696 basic_block bb = BLOCK_FOR_INSN (insn), def_bb;
00697 struct def *def_data;
00698 struct invariant *inv;
00699
00700 for (use = DF_INSN_GET (df, insn)->uses; use; use = use->next_ref)
00701 {
00702 if (use->flags & DF_REF_READ_WRITE)
00703 return false;
00704
00705 defs = DF_REF_CHAIN (use);
00706 if (!defs)
00707 continue;
00708
00709 if (defs->next)
00710 return false;
00711
00712 def = defs->ref;
00713 inv = DF_REF_DATA (def);
00714 if (!inv)
00715 return false;
00716
00717 def_data = inv->def;
00718 gcc_assert (def_data != NULL);
00719
00720 def_bb = DF_REF_BB (def);
00721
00722
00723
00724 if (!dominated_by_p (CDI_DOMINATORS, bb, def_bb))
00725 return false;
00726
00727 bitmap_set_bit (depends_on, def_data->invno);
00728 }
00729
00730 return true;
00731 }
00732
00733
00734
00735
00736
00737 static void
00738 find_invariant_insn (rtx insn, bool always_reached, bool always_executed)
00739 {
00740 struct df_ref *ref;
00741 struct def *def;
00742 bitmap depends_on;
00743 rtx set, dest;
00744 bool simple = true;
00745 struct invariant *inv;
00746
00747
00748 if (find_reg_note (insn, REG_RETVAL, NULL_RTX)
00749 || find_reg_note (insn, REG_LIBCALL, NULL_RTX)
00750 || find_reg_note (insn, REG_NO_CONFLICT, NULL_RTX))
00751 return;
00752
00753 #ifdef HAVE_cc0
00754
00755 if (sets_cc0_p (insn))
00756 return;
00757 #endif
00758
00759 set = single_set (insn);
00760 if (!set)
00761 return;
00762 dest = SET_DEST (set);
00763
00764 if (!REG_P (dest)
00765 || HARD_REGISTER_P (dest))
00766 simple = false;
00767
00768 if (!may_assign_reg_p (SET_DEST (set))
00769 || !check_maybe_invariant (SET_SRC (set)))
00770 return;
00771
00772
00773
00774 if (can_throw_internal (insn))
00775 return;
00776
00777
00778 if (may_trap_after_code_motion_p (PATTERN (insn)) && !always_reached)
00779 return;
00780
00781 depends_on = BITMAP_ALLOC (NULL);
00782 if (!check_dependencies (insn, depends_on))
00783 {
00784 BITMAP_FREE (depends_on);
00785 return;
00786 }
00787
00788 if (simple)
00789 def = XCNEW (struct def);
00790 else
00791 def = NULL;
00792
00793 inv = create_new_invariant (def, insn, depends_on, always_executed);
00794
00795 if (simple)
00796 {
00797 ref = df_find_def (df, insn, dest);
00798 DF_REF_DATA (ref) = inv;
00799 }
00800 }
00801
00802
00803
00804 static void
00805 record_uses (rtx insn)
00806 {
00807 struct df_ref *use;
00808 struct invariant *inv;
00809
00810 for (use = DF_INSN_GET (df, insn)->uses; use; use = use->next_ref)
00811 {
00812 inv = invariant_for_use (use);
00813 if (inv)
00814 record_use (inv->def, DF_REF_LOC (use), DF_REF_INSN (use));
00815 }
00816 }
00817
00818
00819
00820
00821
00822 static void
00823 find_invariants_insn (rtx insn, bool always_reached, bool always_executed)
00824 {
00825 find_invariant_insn (insn, always_reached, always_executed);
00826 record_uses (insn);
00827 }
00828
00829
00830
00831
00832
00833
00834 static void
00835 find_invariants_bb (basic_block bb, bool always_reached, bool always_executed)
00836 {
00837 rtx insn;
00838
00839 FOR_BB_INSNS (bb, insn)
00840 {
00841 if (!INSN_P (insn))
00842 continue;
00843
00844 find_invariants_insn (insn, always_reached, always_executed);
00845
00846 if (always_reached
00847 && CALL_P (insn)
00848 && !CONST_OR_PURE_CALL_P (insn))
00849 always_reached = false;
00850 }
00851 }
00852
00853
00854
00855
00856
00857
00858 static void
00859 find_invariants_body (struct loop *loop, basic_block *body,
00860 bitmap always_reached, bitmap always_executed)
00861 {
00862 unsigned i;
00863
00864 for (i = 0; i < loop->num_nodes; i++)
00865 find_invariants_bb (body[i],
00866 bitmap_bit_p (always_reached, i),
00867 bitmap_bit_p (always_executed, i));
00868 }
00869
00870
00871
00872 static void
00873 find_invariants (struct loop *loop)
00874 {
00875 bitmap may_exit = BITMAP_ALLOC (NULL);
00876 bitmap always_reached = BITMAP_ALLOC (NULL);
00877 bitmap has_exit = BITMAP_ALLOC (NULL);
00878 bitmap always_executed = BITMAP_ALLOC (NULL);
00879 basic_block *body = get_loop_body_in_dom_order (loop);
00880
00881 find_exits (loop, body, may_exit, has_exit);
00882 compute_always_reached (loop, body, may_exit, always_reached);
00883 compute_always_reached (loop, body, has_exit, always_executed);
00884
00885 find_defs (loop, body);
00886 find_invariants_body (loop, body, always_reached, always_executed);
00887 merge_identical_invariants ();
00888
00889 BITMAP_FREE (always_reached);
00890 BITMAP_FREE (always_executed);
00891 BITMAP_FREE (may_exit);
00892 BITMAP_FREE (has_exit);
00893 free (body);
00894 }
00895
00896
00897
00898 static void
00899 free_use_list (struct use *use)
00900 {
00901 struct use *next;
00902
00903 for (; use; use = next)
00904 {
00905 next = use->next;
00906 free (use);
00907 }
00908 }
00909
00910
00911
00912
00913 static void
00914 get_inv_cost (struct invariant *inv, int *comp_cost, unsigned *regs_needed)
00915 {
00916 int acomp_cost;
00917 unsigned aregs_needed;
00918 unsigned depno;
00919 struct invariant *dep;
00920 bitmap_iterator bi;
00921
00922
00923 inv = VEC_index (invariant_p, invariants, inv->eqto);
00924
00925 *comp_cost = 0;
00926 *regs_needed = 0;
00927 if (inv->move
00928 || inv->stamp == actual_stamp)
00929 return;
00930 inv->stamp = actual_stamp;
00931
00932 (*regs_needed)++;
00933 (*comp_cost) += inv->cost;
00934
00935 #ifdef STACK_REGS
00936 {
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953 rtx set = single_set (inv->insn);
00954 if (set
00955 && IS_STACK_MODE (GET_MODE (SET_SRC (set)))
00956 && constant_pool_constant_p (SET_SRC (set)))
00957 (*regs_needed) += 2;
00958 }
00959 #endif
00960
00961 EXECUTE_IF_SET_IN_BITMAP (inv->depends_on, 0, depno, bi)
00962 {
00963 dep = VEC_index (invariant_p, invariants, depno);
00964
00965 get_inv_cost (dep, &acomp_cost, &aregs_needed);
00966
00967 if (aregs_needed
00968
00969
00970
00971
00972 && dep->always_executed
00973 && !dep->def->uses->next)
00974 {
00975
00976
00977 aregs_needed--;
00978 }
00979
00980 (*regs_needed) += aregs_needed;
00981 (*comp_cost) += acomp_cost;
00982 }
00983 }
00984
00985
00986
00987
00988
00989
00990
00991 static int
00992 gain_for_invariant (struct invariant *inv, unsigned *regs_needed,
00993 unsigned new_regs, unsigned regs_used, unsigned n_inv_uses)
00994 {
00995 int comp_cost, size_cost;
00996
00997 get_inv_cost (inv, &comp_cost, regs_needed);
00998 actual_stamp++;
00999
01000 size_cost = (global_cost_for_size (new_regs + *regs_needed,
01001 regs_used, n_inv_uses)
01002 - global_cost_for_size (new_regs, regs_used, n_inv_uses));
01003
01004 return comp_cost - size_cost;
01005 }
01006
01007
01008
01009
01010
01011
01012
01013 static int
01014 best_gain_for_invariant (struct invariant **best, unsigned *regs_needed,
01015 unsigned new_regs, unsigned regs_used,
01016 unsigned n_inv_uses)
01017 {
01018 struct invariant *inv;
01019 int gain = 0, again;
01020 unsigned aregs_needed, invno;
01021
01022 for (invno = 0; VEC_iterate (invariant_p, invariants, invno, inv); invno++)
01023 {
01024 if (inv->move)
01025 continue;
01026
01027
01028 if (inv->eqto != inv->invno)
01029 continue;
01030
01031 again = gain_for_invariant (inv, &aregs_needed,
01032 new_regs, regs_used, n_inv_uses);
01033 if (again > gain)
01034 {
01035 gain = again;
01036 *best = inv;
01037 *regs_needed = aregs_needed;
01038 }
01039 }
01040
01041 return gain;
01042 }
01043
01044
01045
01046 static void
01047 set_move_mark (unsigned invno)
01048 {
01049 struct invariant *inv = VEC_index (invariant_p, invariants, invno);
01050 bitmap_iterator bi;
01051
01052
01053 inv = VEC_index (invariant_p, invariants, inv->eqto);
01054
01055 if (inv->move)
01056 return;
01057 inv->move = true;
01058
01059 if (dump_file)
01060 fprintf (dump_file, "Decided to move invariant %d\n", invno);
01061
01062 EXECUTE_IF_SET_IN_BITMAP (inv->depends_on, 0, invno, bi)
01063 {
01064 set_move_mark (invno);
01065 }
01066 }
01067
01068
01069
01070 static void
01071 find_invariants_to_move (void)
01072 {
01073 unsigned i, regs_used, n_inv_uses, regs_needed = 0, new_regs;
01074 struct invariant *inv = NULL;
01075 unsigned int n_regs = DF_REG_SIZE (df);
01076
01077 if (!VEC_length (invariant_p, invariants))
01078 return;
01079
01080
01081
01082 n_inv_uses = 0;
01083
01084
01085
01086 regs_used = 2;
01087
01088 for (i = 0; i < n_regs; i++)
01089 {
01090 if (!DF_REGNO_FIRST_DEF (df, i) && DF_REGNO_LAST_USE (df, i))
01091 {
01092
01093 regs_used++;
01094 }
01095 }
01096
01097 for (i = 0; VEC_iterate (invariant_p, invariants, i, inv); i++)
01098 {
01099 if (inv->def)
01100 n_inv_uses += inv->def->n_uses;
01101 }
01102
01103 new_regs = 0;
01104 while (best_gain_for_invariant (&inv, ®s_needed,
01105 new_regs, regs_used, n_inv_uses) > 0)
01106 {
01107 set_move_mark (inv->invno);
01108 new_regs += regs_needed;
01109 }
01110 }
01111
01112
01113
01114 static bool
01115 seq_insns_valid_p (rtx seq)
01116 {
01117 rtx x;
01118
01119 for (x = seq; x; x = NEXT_INSN (x))
01120 if (insn_invalid_p (x))
01121 return false;
01122
01123 return true;
01124 }
01125
01126
01127
01128
01129 static bool
01130 move_invariant_reg (struct loop *loop, unsigned invno)
01131 {
01132 struct invariant *inv = VEC_index (invariant_p, invariants, invno);
01133 struct invariant *repr = VEC_index (invariant_p, invariants, inv->eqto);
01134 unsigned i;
01135 basic_block preheader = loop_preheader_edge (loop)->src;
01136 rtx reg, set, dest, seq, op;
01137 struct use *use;
01138 bitmap_iterator bi;
01139
01140 if (inv->reg)
01141 return true;
01142 if (!repr->move)
01143 return false;
01144
01145
01146
01147
01148 if (inv == repr)
01149 {
01150 if (inv->depends_on)
01151 {
01152 EXECUTE_IF_SET_IN_BITMAP (inv->depends_on, 0, i, bi)
01153 {
01154 if (!move_invariant_reg (loop, i))
01155 goto fail;
01156 }
01157 }
01158
01159
01160
01161
01162
01163
01164 set = single_set (inv->insn);
01165 dest = SET_DEST (set);
01166 reg = gen_reg_rtx (GET_MODE (dest));
01167
01168
01169
01170
01171 if (REG_P (dest) && !HARD_REGISTER_P (dest))
01172 {
01173 emit_insn_after (gen_move_insn (dest, reg), inv->insn);
01174 SET_DEST (set) = reg;
01175 reorder_insns (inv->insn, inv->insn, BB_END (preheader));
01176 }
01177 else
01178 {
01179 start_sequence ();
01180 op = force_operand (SET_SRC (set), reg);
01181 if (!op)
01182 {
01183 end_sequence ();
01184 goto fail;
01185 }
01186 if (op != reg)
01187 emit_move_insn (reg, op);
01188 seq = get_insns ();
01189 end_sequence ();
01190
01191 if (!seq_insns_valid_p (seq))
01192 goto fail;
01193 emit_insn_after (seq, BB_END (preheader));
01194
01195 emit_insn_after (gen_move_insn (dest, reg), inv->insn);
01196 delete_insn (inv->insn);
01197 }
01198 }
01199 else
01200 {
01201 if (!move_invariant_reg (loop, repr->invno))
01202 goto fail;
01203 reg = repr->reg;
01204 set = single_set (inv->insn);
01205 emit_insn_after (gen_move_insn (SET_DEST (set), reg), inv->insn);
01206 delete_insn (inv->insn);
01207 }
01208
01209 inv->reg = reg;
01210
01211
01212
01213
01214 if (inv->def)
01215 {
01216 for (use = inv->def->uses; use; use = use->next)
01217 *use->pos = reg;
01218 }
01219
01220 return true;
01221
01222 fail:
01223
01224
01225 if (dump_file)
01226 fprintf (dump_file, "Failed to move invariant %d\n", invno);
01227 inv->move = false;
01228 inv->reg = NULL_RTX;
01229 return false;
01230 }
01231
01232
01233
01234
01235 static void
01236 move_invariants (struct loop *loop)
01237 {
01238 struct invariant *inv;
01239 unsigned i;
01240
01241 for (i = 0; VEC_iterate (invariant_p, invariants, i, inv); i++)
01242 move_invariant_reg (loop, i);
01243 }
01244
01245
01246
01247 static void
01248 init_inv_motion_data (void)
01249 {
01250 actual_stamp = 1;
01251
01252 invariants = VEC_alloc (invariant_p, heap, 100);
01253 }
01254
01255
01256
01257 static void
01258 free_inv_motion_data (void)
01259 {
01260 unsigned i;
01261 struct def *def;
01262 struct invariant *inv;
01263
01264 for (i = 0; i < DF_DEFS_SIZE (df); i++)
01265 {
01266 struct df_ref * ref = DF_DEFS_GET (df, i);
01267 if (!ref)
01268 continue;
01269
01270 inv = DF_REF_DATA (ref);
01271 if (!inv)
01272 continue;
01273
01274 def = inv->def;
01275 gcc_assert (def != NULL);
01276
01277 free_use_list (def->uses);
01278 free (def);
01279 DF_REF_DATA (ref) = NULL;
01280 }
01281
01282 for (i = 0; VEC_iterate (invariant_p, invariants, i, inv); i++)
01283 {
01284 BITMAP_FREE (inv->depends_on);
01285 free (inv);
01286 }
01287 VEC_free (invariant_p, heap, invariants);
01288 }
01289
01290
01291
01292 static void
01293 move_single_loop_invariants (struct loop *loop)
01294 {
01295 init_inv_motion_data ();
01296
01297 find_invariants (loop);
01298 find_invariants_to_move ();
01299 move_invariants (loop);
01300
01301 free_inv_motion_data ();
01302 }
01303
01304
01305
01306 static void
01307 free_loop_data (struct loop *loop)
01308 {
01309 struct loop_data *data = LOOP_DATA (loop);
01310
01311 free (data);
01312 loop->aux = NULL;
01313 }
01314
01315
01316
01317 void
01318 move_loop_invariants (struct loops *loops)
01319 {
01320 struct loop *loop;
01321 unsigned i;
01322
01323 df = df_init (DF_HARD_REGS | DF_EQUIV_NOTES);
01324 df_chain_add_problem (df, DF_UD_CHAIN);
01325
01326
01327 loop = loops->tree_root;
01328 while (loop->inner)
01329 loop = loop->inner;
01330
01331 while (loop != loops->tree_root)
01332 {
01333 move_single_loop_invariants (loop);
01334
01335 if (loop->next)
01336 {
01337 loop = loop->next;
01338 while (loop->inner)
01339 loop = loop->inner;
01340 }
01341 else
01342 loop = loop->outer;
01343 }
01344
01345 for (i = 1; i < loops->num; i++)
01346 if (loops->parray[i])
01347 free_loop_data (loops->parray[i]);
01348
01349 df_finish (df);
01350 df = NULL;
01351
01352 #ifdef ENABLE_CHECKING
01353 verify_flow_info ();
01354 #endif
01355 }