1 | /* Code to analyze doloop loops in order for targets to perform late |
2 | optimizations converting doloops to other forms of hardware loops. |
3 | Copyright (C) 2011-2023 Free Software Foundation, Inc. |
4 | |
5 | This file is part of GCC. |
6 | |
7 | GCC is free software; you can redistribute it and/or modify it under |
8 | the terms of the GNU General Public License as published by the Free |
9 | Software Foundation; either version 3, or (at your option) any later |
10 | version. |
11 | |
12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
15 | for more details. |
16 | |
17 | You should have received a copy of the GNU General Public License |
18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. */ |
20 | |
21 | #ifndef GCC_HW_DOLOOP_H |
22 | #define GCC_HW_DOLOOP_H |
23 | |
24 | /* We need to keep a vector of loops */ |
25 | typedef struct hwloop_info_d *hwloop_info; |
26 | |
27 | /* Information about a loop we have found (or are in the process of |
28 | finding). */ |
29 | struct GTY (()) hwloop_info_d |
30 | { |
31 | /* loop number, for dumps */ |
32 | int loop_no; |
33 | |
34 | /* Next loop in the graph. */ |
35 | hwloop_info next; |
36 | |
37 | /* Vector of blocks only within the loop, including those within |
38 | inner loops. */ |
39 | vec<basic_block> blocks; |
40 | |
41 | /* Same information in a bitmap. */ |
42 | bitmap block_bitmap; |
43 | |
44 | /* Vector of inner loops within this loop. Includes loops of every |
45 | nesting level. */ |
46 | vec<hwloop_info> loops; |
47 | |
48 | /* All edges that jump into the loop. */ |
49 | vec<edge, va_gc> *incoming; |
50 | |
51 | /* The ports currently using this infrastructure can typically |
52 | handle two cases: all incoming edges have the same destination |
53 | block, or all incoming edges have the same source block. These |
54 | two members are set to the common source or destination we found, |
55 | or NULL if different blocks were found. If both are NULL the |
56 | loop can't be optimized. */ |
57 | basic_block incoming_src; |
58 | basic_block incoming_dest; |
59 | |
60 | /* First block in the loop. This is the one branched to by the loop_end |
61 | insn. */ |
62 | basic_block head; |
63 | |
64 | /* Last block in the loop (the one with the loop_end insn). */ |
65 | basic_block tail; |
66 | |
67 | /* The successor block of the loop. This is the one the loop_end insn |
68 | falls into. */ |
69 | basic_block successor; |
70 | |
71 | /* The last instruction in the tail. */ |
72 | rtx_insn *last_insn; |
73 | |
74 | /* The loop_end insn. */ |
75 | rtx_insn *loop_end; |
76 | |
77 | /* The iteration register. */ |
78 | rtx iter_reg; |
79 | |
80 | /* The new label placed at the beginning of the loop. */ |
81 | rtx_insn *start_label; |
82 | |
83 | /* The new label placed at the end of the loop. */ |
84 | rtx end_label; |
85 | |
86 | /* The length of the loop. */ |
87 | int length; |
88 | |
89 | /* The nesting depth of the loop. Innermost loops are given a depth |
90 | of 1. Only successfully optimized doloops are counted; if an inner |
91 | loop was marked as bad, it does not increase the depth of its parent |
92 | loop. |
93 | This value is valid when the target's optimize function is called. */ |
94 | int depth; |
95 | |
96 | /* True if we can't optimize this loop. */ |
97 | bool bad; |
98 | |
99 | /* True if we have visited this loop during the optimization phase. */ |
100 | bool visited; |
101 | |
102 | /* The following values are collected before calling the target's optimize |
103 | function and are not valid earlier. */ |
104 | |
105 | /* Record information about control flow: whether the loop has calls |
106 | or asm statements, whether it has edges that jump out of the loop, |
107 | or edges that jump within the loop. */ |
108 | bool has_call; |
109 | bool has_asm; |
110 | bool jumps_within; |
111 | bool jumps_outof; |
112 | |
113 | /* True if there is an instruction other than the doloop_end which uses the |
114 | iteration register. */ |
115 | bool iter_reg_used; |
116 | /* True if the iteration register lives past the doloop instruction. */ |
117 | bool iter_reg_used_outside; |
118 | |
119 | /* Hard registers set at any point in the loop, except for the loop counter |
120 | register's set in the doloop_end instruction. */ |
121 | HARD_REG_SET regs_set_in_loop; |
122 | }; |
123 | |
124 | /* A set of hooks to be defined by a target that wants to use the reorg_loops |
125 | functionality. |
126 | |
127 | reorg_loops is intended to handle cases where special hardware loop |
128 | setup instructions are required before the loop, for example to set |
129 | up loop counter registers that are not exposed to the register |
130 | allocator, or to inform the hardware about loop bounds. |
131 | |
132 | reorg_loops performs analysis to discover loop_end patterns created |
133 | by the earlier loop-doloop pass, and sets up a hwloop_info |
134 | structure for each such insn it finds. It then tries to discover |
135 | the basic blocks containing the loop by tracking the lifetime of |
136 | the iteration register. |
137 | |
138 | If a valid loop can't be found, the FAIL function is called; |
139 | otherwise the OPT function is called for each loop, visiting |
140 | innermost loops first and ascending. */ |
141 | struct hw_doloop_hooks |
142 | { |
143 | /* Examine INSN. If it is a suitable doloop_end pattern, return the |
144 | iteration register, which should be a single hard register. |
145 | Otherwise, return NULL_RTX. */ |
146 | rtx (*end_pattern_reg) (rtx_insn *insn); |
147 | /* Optimize LOOP. The target should perform any additional analysis |
148 | (e.g. checking that the loop isn't too long), and then perform |
149 | its transformations. Return true if successful, false if the |
150 | loop should be marked bad. If it returns false, the FAIL |
151 | function is called. */ |
152 | bool (*opt) (hwloop_info loop); |
153 | /* Handle a loop that was marked bad for any reason. This could be |
154 | used to split the doloop_end pattern. */ |
155 | void (*fail) (hwloop_info loop); |
156 | }; |
157 | |
158 | extern void reorg_loops (bool, struct hw_doloop_hooks *); |
159 | |
160 | #endif /* GCC_HW_DOLOOP_H */ |
161 | |