Mercurial > hg > CbC > CbC_gcc
comparison gcc/loop-unroll.c @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
comparison
equal
deleted
inserted
replaced
56:3c8a44c06a95 | 63:b7f97abdc517 |
---|---|
1 /* Loop unrolling and peeling. | 1 /* Loop unrolling and peeling. |
2 Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008 | 2 Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2010 |
3 Free Software Foundation, Inc. | 3 Free Software Foundation, Inc. |
4 | 4 |
5 This file is part of GCC. | 5 This file is part of GCC. |
6 | 6 |
7 GCC is free software; you can redistribute it and/or modify it under | 7 GCC is free software; you can redistribute it and/or modify it under |
31 #include "params.h" | 31 #include "params.h" |
32 #include "output.h" | 32 #include "output.h" |
33 #include "expr.h" | 33 #include "expr.h" |
34 #include "hashtab.h" | 34 #include "hashtab.h" |
35 #include "recog.h" | 35 #include "recog.h" |
36 #include "target.h" | |
36 | 37 |
37 /* This pass performs loop unrolling and peeling. We only perform these | 38 /* This pass performs loop unrolling and peeling. We only perform these |
38 optimizations on innermost loops (with single exception) because | 39 optimizations on innermost loops (with single exception) because |
39 the impact on performance is greatest here, and we want to avoid | 40 the impact on performance is greatest here, and we want to avoid |
40 unnecessary code size growth. The gain is caused by greater sequentiality | 41 unnecessary code size growth. The gain is caused by greater sequentiality |
140 static struct opt_info *analyze_insns_in_loop (struct loop *); | 141 static struct opt_info *analyze_insns_in_loop (struct loop *); |
141 static void opt_info_start_duplication (struct opt_info *); | 142 static void opt_info_start_duplication (struct opt_info *); |
142 static void apply_opt_in_copies (struct opt_info *, unsigned, bool, bool); | 143 static void apply_opt_in_copies (struct opt_info *, unsigned, bool, bool); |
143 static void free_opt_info (struct opt_info *); | 144 static void free_opt_info (struct opt_info *); |
144 static struct var_to_expand *analyze_insn_to_expand_var (struct loop*, rtx); | 145 static struct var_to_expand *analyze_insn_to_expand_var (struct loop*, rtx); |
145 static bool referenced_in_one_insn_in_loop_p (struct loop *, rtx); | 146 static bool referenced_in_one_insn_in_loop_p (struct loop *, rtx, int *); |
146 static struct iv_to_split *analyze_iv_to_split_insn (rtx); | 147 static struct iv_to_split *analyze_iv_to_split_insn (rtx); |
147 static void expand_var_during_unrolling (struct var_to_expand *, rtx); | 148 static void expand_var_during_unrolling (struct var_to_expand *, rtx); |
148 static void insert_var_expansion_initialization (struct var_to_expand *, | 149 static void insert_var_expansion_initialization (struct var_to_expand *, |
149 basic_block); | 150 basic_block); |
150 static void combine_var_copies_in_loop_exit (struct var_to_expand *, | 151 static void combine_var_copies_in_loop_exit (struct var_to_expand *, |
824 if (nunroll > nunroll_by_av) | 825 if (nunroll > nunroll_by_av) |
825 nunroll = nunroll_by_av; | 826 nunroll = nunroll_by_av; |
826 if (nunroll > (unsigned) PARAM_VALUE (PARAM_MAX_UNROLL_TIMES)) | 827 if (nunroll > (unsigned) PARAM_VALUE (PARAM_MAX_UNROLL_TIMES)) |
827 nunroll = PARAM_VALUE (PARAM_MAX_UNROLL_TIMES); | 828 nunroll = PARAM_VALUE (PARAM_MAX_UNROLL_TIMES); |
828 | 829 |
830 if (targetm.loop_unroll_adjust) | |
831 nunroll = targetm.loop_unroll_adjust (nunroll, loop); | |
832 | |
829 /* Skip big loops. */ | 833 /* Skip big loops. */ |
830 if (nunroll <= 1) | 834 if (nunroll <= 1) |
831 { | 835 { |
832 if (dump_file) | 836 if (dump_file) |
833 fprintf (dump_file, ";; Not considering loop, is too big\n"); | 837 fprintf (dump_file, ";; Not considering loop, is too big\n"); |
1364 if (nunroll > nunroll_by_av) | 1368 if (nunroll > nunroll_by_av) |
1365 nunroll = nunroll_by_av; | 1369 nunroll = nunroll_by_av; |
1366 if (nunroll > (unsigned) PARAM_VALUE (PARAM_MAX_UNROLL_TIMES)) | 1370 if (nunroll > (unsigned) PARAM_VALUE (PARAM_MAX_UNROLL_TIMES)) |
1367 nunroll = PARAM_VALUE (PARAM_MAX_UNROLL_TIMES); | 1371 nunroll = PARAM_VALUE (PARAM_MAX_UNROLL_TIMES); |
1368 | 1372 |
1373 if (targetm.loop_unroll_adjust) | |
1374 nunroll = targetm.loop_unroll_adjust (nunroll, loop); | |
1375 | |
1369 /* Skip big loops. */ | 1376 /* Skip big loops. */ |
1370 if (nunroll <= 1) | 1377 if (nunroll <= 1) |
1371 { | 1378 { |
1372 if (dump_file) | 1379 if (dump_file) |
1373 fprintf (dump_file, ";; Not considering loop, is too big\n"); | 1380 fprintf (dump_file, ";; Not considering loop, is too big\n"); |
1523 const struct var_to_expand *const i2 = (const struct var_to_expand *) ivts2; | 1530 const struct var_to_expand *const i2 = (const struct var_to_expand *) ivts2; |
1524 | 1531 |
1525 return i1->insn == i2->insn; | 1532 return i1->insn == i2->insn; |
1526 } | 1533 } |
1527 | 1534 |
1528 /* Returns true if REG is referenced in one insn in LOOP. */ | 1535 /* Returns true if REG is referenced in one nondebug insn in LOOP. |
1536 Set *DEBUG_USES to the number of debug insns that reference the | |
1537 variable. */ | |
1529 | 1538 |
1530 bool | 1539 bool |
1531 referenced_in_one_insn_in_loop_p (struct loop *loop, rtx reg) | 1540 referenced_in_one_insn_in_loop_p (struct loop *loop, rtx reg, |
1541 int *debug_uses) | |
1532 { | 1542 { |
1533 basic_block *body, bb; | 1543 basic_block *body, bb; |
1534 unsigned i; | 1544 unsigned i; |
1535 int count_ref = 0; | 1545 int count_ref = 0; |
1536 rtx insn; | 1546 rtx insn; |
1539 for (i = 0; i < loop->num_nodes; i++) | 1549 for (i = 0; i < loop->num_nodes; i++) |
1540 { | 1550 { |
1541 bb = body[i]; | 1551 bb = body[i]; |
1542 | 1552 |
1543 FOR_BB_INSNS (bb, insn) | 1553 FOR_BB_INSNS (bb, insn) |
1544 { | 1554 if (!rtx_referenced_p (reg, insn)) |
1545 if (rtx_referenced_p (reg, insn)) | 1555 continue; |
1546 count_ref++; | 1556 else if (DEBUG_INSN_P (insn)) |
1547 } | 1557 ++*debug_uses; |
1548 } | 1558 else if (++count_ref > 1) |
1559 break; | |
1560 } | |
1561 free (body); | |
1549 return (count_ref == 1); | 1562 return (count_ref == 1); |
1563 } | |
1564 | |
1565 /* Reset the DEBUG_USES debug insns in LOOP that reference REG. */ | |
1566 | |
1567 static void | |
1568 reset_debug_uses_in_loop (struct loop *loop, rtx reg, int debug_uses) | |
1569 { | |
1570 basic_block *body, bb; | |
1571 unsigned i; | |
1572 rtx insn; | |
1573 | |
1574 body = get_loop_body (loop); | |
1575 for (i = 0; debug_uses && i < loop->num_nodes; i++) | |
1576 { | |
1577 bb = body[i]; | |
1578 | |
1579 FOR_BB_INSNS (bb, insn) | |
1580 if (!DEBUG_INSN_P (insn) || !rtx_referenced_p (reg, insn)) | |
1581 continue; | |
1582 else | |
1583 { | |
1584 validate_change (insn, &INSN_VAR_LOCATION_LOC (insn), | |
1585 gen_rtx_UNKNOWN_VAR_LOC (), 0); | |
1586 if (!--debug_uses) | |
1587 break; | |
1588 } | |
1589 } | |
1590 free (body); | |
1550 } | 1591 } |
1551 | 1592 |
1552 /* Determine whether INSN contains an accumulator | 1593 /* Determine whether INSN contains an accumulator |
1553 which can be expanded into separate copies, | 1594 which can be expanded into separate copies, |
1554 one for each copy of the LOOP body. | 1595 one for each copy of the LOOP body. |
1577 { | 1618 { |
1578 rtx set, dest, src, op1, op2, something; | 1619 rtx set, dest, src, op1, op2, something; |
1579 struct var_to_expand *ves; | 1620 struct var_to_expand *ves; |
1580 enum machine_mode mode1, mode2; | 1621 enum machine_mode mode1, mode2; |
1581 unsigned accum_pos; | 1622 unsigned accum_pos; |
1623 int debug_uses = 0; | |
1582 | 1624 |
1583 set = single_set (insn); | 1625 set = single_set (insn); |
1584 if (!set) | 1626 if (!set) |
1585 return NULL; | 1627 return NULL; |
1586 | 1628 |
1622 /* The method of expansion that we are using; which includes | 1664 /* The method of expansion that we are using; which includes |
1623 the initialization of the expansions with zero and the summation of | 1665 the initialization of the expansions with zero and the summation of |
1624 the expansions at the end of the computation will yield wrong results | 1666 the expansions at the end of the computation will yield wrong results |
1625 for (x = something - x) thus avoid using it in that case. */ | 1667 for (x = something - x) thus avoid using it in that case. */ |
1626 if (accum_pos == 1 | 1668 if (accum_pos == 1 |
1627 && GET_CODE (src) == MINUS) | 1669 && GET_CODE (src) == MINUS) |
1628 return NULL; | 1670 return NULL; |
1629 | 1671 |
1630 something = (accum_pos == 0)? op2 : op1; | 1672 something = (accum_pos == 0) ? op2 : op1; |
1631 | 1673 |
1632 if (!referenced_in_one_insn_in_loop_p (loop, dest)) | 1674 if (rtx_referenced_p (dest, something)) |
1633 return NULL; | 1675 return NULL; |
1634 | 1676 |
1635 if (rtx_referenced_p (dest, something)) | 1677 if (!referenced_in_one_insn_in_loop_p (loop, dest, &debug_uses)) |
1636 return NULL; | 1678 return NULL; |
1637 | 1679 |
1638 mode1 = GET_MODE (dest); | 1680 mode1 = GET_MODE (dest); |
1639 mode2 = GET_MODE (something); | 1681 mode2 = GET_MODE (something); |
1640 if ((FLOAT_MODE_P (mode1) | 1682 if ((FLOAT_MODE_P (mode1) |
1647 fprintf (dump_file, | 1689 fprintf (dump_file, |
1648 "\n;; Expanding Accumulator "); | 1690 "\n;; Expanding Accumulator "); |
1649 print_rtl (dump_file, dest); | 1691 print_rtl (dump_file, dest); |
1650 fprintf (dump_file, "\n"); | 1692 fprintf (dump_file, "\n"); |
1651 } | 1693 } |
1694 | |
1695 if (debug_uses) | |
1696 /* Instead of resetting the debug insns, we could replace each | |
1697 debug use in the loop with the sum or product of all expanded | |
1698 accummulators. Since we'll only know of all expansions at the | |
1699 end, we'd have to keep track of which vars_to_expand a debug | |
1700 insn in the loop references, take note of each copy of the | |
1701 debug insn during unrolling, and when it's all done, compute | |
1702 the sum or product of each variable and adjust the original | |
1703 debug insn and each copy thereof. What a pain! */ | |
1704 reset_debug_uses_in_loop (loop, dest, debug_uses); | |
1652 | 1705 |
1653 /* Record the accumulator to expand. */ | 1706 /* Record the accumulator to expand. */ |
1654 ves = XNEW (struct var_to_expand); | 1707 ves = XNEW (struct var_to_expand); |
1655 ves->insn = insn; | 1708 ves->insn = insn; |
1656 ves->reg = copy_rtx (dest); | 1709 ves->reg = copy_rtx (dest); |