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);