1e4b17023SJohn Marino /* Instruction scheduling pass. This file computes dependencies between
2e4b17023SJohn Marino instructions.
3e4b17023SJohn Marino Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
4e4b17023SJohn Marino 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
5e4b17023SJohn Marino 2011, 2012
6e4b17023SJohn Marino Free Software Foundation, Inc.
7e4b17023SJohn Marino Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
8e4b17023SJohn Marino and currently maintained by, Jim Wilson (wilson@cygnus.com)
9e4b17023SJohn Marino
10e4b17023SJohn Marino This file is part of GCC.
11e4b17023SJohn Marino
12e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
13e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
14e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
15e4b17023SJohn Marino version.
16e4b17023SJohn Marino
17e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
18e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
19e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20e4b17023SJohn Marino for more details.
21e4b17023SJohn Marino
22e4b17023SJohn Marino You should have received a copy of the GNU General Public License
23e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
24e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
25e4b17023SJohn Marino
26e4b17023SJohn Marino #include "config.h"
27e4b17023SJohn Marino #include "system.h"
28e4b17023SJohn Marino #include "coretypes.h"
29e4b17023SJohn Marino #include "tm.h"
30e4b17023SJohn Marino #include "diagnostic-core.h"
31e4b17023SJohn Marino #include "rtl.h"
32e4b17023SJohn Marino #include "tm_p.h"
33e4b17023SJohn Marino #include "hard-reg-set.h"
34e4b17023SJohn Marino #include "regs.h"
35e4b17023SJohn Marino #include "function.h"
36e4b17023SJohn Marino #include "flags.h"
37e4b17023SJohn Marino #include "insn-config.h"
38e4b17023SJohn Marino #include "insn-attr.h"
39e4b17023SJohn Marino #include "except.h"
40e4b17023SJohn Marino #include "recog.h"
41e4b17023SJohn Marino #include "sched-int.h"
42e4b17023SJohn Marino #include "params.h"
43e4b17023SJohn Marino #include "cselib.h"
44e4b17023SJohn Marino #include "ira.h"
45e4b17023SJohn Marino #include "target.h"
46e4b17023SJohn Marino
47e4b17023SJohn Marino #ifdef INSN_SCHEDULING
48e4b17023SJohn Marino
49e4b17023SJohn Marino #ifdef ENABLE_CHECKING
50e4b17023SJohn Marino #define CHECK (true)
51e4b17023SJohn Marino #else
52e4b17023SJohn Marino #define CHECK (false)
53e4b17023SJohn Marino #endif
54e4b17023SJohn Marino
55e4b17023SJohn Marino /* Holds current parameters for the dependency analyzer. */
56e4b17023SJohn Marino struct sched_deps_info_def *sched_deps_info;
57e4b17023SJohn Marino
58e4b17023SJohn Marino /* The data is specific to the Haifa scheduler. */
59e4b17023SJohn Marino VEC(haifa_deps_insn_data_def, heap) *h_d_i_d = NULL;
60e4b17023SJohn Marino
61e4b17023SJohn Marino /* Return the major type present in the DS. */
62e4b17023SJohn Marino enum reg_note
ds_to_dk(ds_t ds)63e4b17023SJohn Marino ds_to_dk (ds_t ds)
64e4b17023SJohn Marino {
65e4b17023SJohn Marino if (ds & DEP_TRUE)
66e4b17023SJohn Marino return REG_DEP_TRUE;
67e4b17023SJohn Marino
68e4b17023SJohn Marino if (ds & DEP_OUTPUT)
69e4b17023SJohn Marino return REG_DEP_OUTPUT;
70e4b17023SJohn Marino
71e4b17023SJohn Marino if (ds & DEP_CONTROL)
72e4b17023SJohn Marino return REG_DEP_CONTROL;
73e4b17023SJohn Marino
74e4b17023SJohn Marino gcc_assert (ds & DEP_ANTI);
75e4b17023SJohn Marino
76e4b17023SJohn Marino return REG_DEP_ANTI;
77e4b17023SJohn Marino }
78e4b17023SJohn Marino
79e4b17023SJohn Marino /* Return equivalent dep_status. */
80e4b17023SJohn Marino ds_t
dk_to_ds(enum reg_note dk)81e4b17023SJohn Marino dk_to_ds (enum reg_note dk)
82e4b17023SJohn Marino {
83e4b17023SJohn Marino switch (dk)
84e4b17023SJohn Marino {
85e4b17023SJohn Marino case REG_DEP_TRUE:
86e4b17023SJohn Marino return DEP_TRUE;
87e4b17023SJohn Marino
88e4b17023SJohn Marino case REG_DEP_OUTPUT:
89e4b17023SJohn Marino return DEP_OUTPUT;
90e4b17023SJohn Marino
91e4b17023SJohn Marino case REG_DEP_CONTROL:
92e4b17023SJohn Marino return DEP_CONTROL;
93e4b17023SJohn Marino
94e4b17023SJohn Marino default:
95e4b17023SJohn Marino gcc_assert (dk == REG_DEP_ANTI);
96e4b17023SJohn Marino return DEP_ANTI;
97e4b17023SJohn Marino }
98e4b17023SJohn Marino }
99e4b17023SJohn Marino
100e4b17023SJohn Marino /* Functions to operate with dependence information container - dep_t. */
101e4b17023SJohn Marino
102e4b17023SJohn Marino /* Init DEP with the arguments. */
103e4b17023SJohn Marino void
init_dep_1(dep_t dep,rtx pro,rtx con,enum reg_note type,ds_t ds)104e4b17023SJohn Marino init_dep_1 (dep_t dep, rtx pro, rtx con, enum reg_note type, ds_t ds)
105e4b17023SJohn Marino {
106e4b17023SJohn Marino DEP_PRO (dep) = pro;
107e4b17023SJohn Marino DEP_CON (dep) = con;
108e4b17023SJohn Marino DEP_TYPE (dep) = type;
109e4b17023SJohn Marino DEP_STATUS (dep) = ds;
110e4b17023SJohn Marino DEP_COST (dep) = UNKNOWN_DEP_COST;
111e4b17023SJohn Marino }
112e4b17023SJohn Marino
113e4b17023SJohn Marino /* Init DEP with the arguments.
114e4b17023SJohn Marino While most of the scheduler (including targets) only need the major type
115e4b17023SJohn Marino of the dependency, it is convenient to hide full dep_status from them. */
116e4b17023SJohn Marino void
init_dep(dep_t dep,rtx pro,rtx con,enum reg_note kind)117e4b17023SJohn Marino init_dep (dep_t dep, rtx pro, rtx con, enum reg_note kind)
118e4b17023SJohn Marino {
119e4b17023SJohn Marino ds_t ds;
120e4b17023SJohn Marino
121e4b17023SJohn Marino if ((current_sched_info->flags & USE_DEPS_LIST))
122e4b17023SJohn Marino ds = dk_to_ds (kind);
123e4b17023SJohn Marino else
124e4b17023SJohn Marino ds = 0;
125e4b17023SJohn Marino
126e4b17023SJohn Marino init_dep_1 (dep, pro, con, kind, ds);
127e4b17023SJohn Marino }
128e4b17023SJohn Marino
129e4b17023SJohn Marino /* Make a copy of FROM in TO. */
130e4b17023SJohn Marino static void
copy_dep(dep_t to,dep_t from)131e4b17023SJohn Marino copy_dep (dep_t to, dep_t from)
132e4b17023SJohn Marino {
133e4b17023SJohn Marino memcpy (to, from, sizeof (*to));
134e4b17023SJohn Marino }
135e4b17023SJohn Marino
136e4b17023SJohn Marino static void dump_ds (FILE *, ds_t);
137e4b17023SJohn Marino
138e4b17023SJohn Marino /* Define flags for dump_dep (). */
139e4b17023SJohn Marino
140e4b17023SJohn Marino /* Dump producer of the dependence. */
141e4b17023SJohn Marino #define DUMP_DEP_PRO (2)
142e4b17023SJohn Marino
143e4b17023SJohn Marino /* Dump consumer of the dependence. */
144e4b17023SJohn Marino #define DUMP_DEP_CON (4)
145e4b17023SJohn Marino
146e4b17023SJohn Marino /* Dump type of the dependence. */
147e4b17023SJohn Marino #define DUMP_DEP_TYPE (8)
148e4b17023SJohn Marino
149e4b17023SJohn Marino /* Dump status of the dependence. */
150e4b17023SJohn Marino #define DUMP_DEP_STATUS (16)
151e4b17023SJohn Marino
152e4b17023SJohn Marino /* Dump all information about the dependence. */
153e4b17023SJohn Marino #define DUMP_DEP_ALL (DUMP_DEP_PRO | DUMP_DEP_CON | DUMP_DEP_TYPE \
154e4b17023SJohn Marino |DUMP_DEP_STATUS)
155e4b17023SJohn Marino
156e4b17023SJohn Marino /* Dump DEP to DUMP.
157e4b17023SJohn Marino FLAGS is a bit mask specifying what information about DEP needs
158e4b17023SJohn Marino to be printed.
159e4b17023SJohn Marino If FLAGS has the very first bit set, then dump all information about DEP
160e4b17023SJohn Marino and propagate this bit into the callee dump functions. */
161e4b17023SJohn Marino static void
dump_dep(FILE * dump,dep_t dep,int flags)162e4b17023SJohn Marino dump_dep (FILE *dump, dep_t dep, int flags)
163e4b17023SJohn Marino {
164e4b17023SJohn Marino if (flags & 1)
165e4b17023SJohn Marino flags |= DUMP_DEP_ALL;
166e4b17023SJohn Marino
167e4b17023SJohn Marino fprintf (dump, "<");
168e4b17023SJohn Marino
169e4b17023SJohn Marino if (flags & DUMP_DEP_PRO)
170e4b17023SJohn Marino fprintf (dump, "%d; ", INSN_UID (DEP_PRO (dep)));
171e4b17023SJohn Marino
172e4b17023SJohn Marino if (flags & DUMP_DEP_CON)
173e4b17023SJohn Marino fprintf (dump, "%d; ", INSN_UID (DEP_CON (dep)));
174e4b17023SJohn Marino
175e4b17023SJohn Marino if (flags & DUMP_DEP_TYPE)
176e4b17023SJohn Marino {
177e4b17023SJohn Marino char t;
178e4b17023SJohn Marino enum reg_note type = DEP_TYPE (dep);
179e4b17023SJohn Marino
180e4b17023SJohn Marino switch (type)
181e4b17023SJohn Marino {
182e4b17023SJohn Marino case REG_DEP_TRUE:
183e4b17023SJohn Marino t = 't';
184e4b17023SJohn Marino break;
185e4b17023SJohn Marino
186e4b17023SJohn Marino case REG_DEP_OUTPUT:
187e4b17023SJohn Marino t = 'o';
188e4b17023SJohn Marino break;
189e4b17023SJohn Marino
190e4b17023SJohn Marino case REG_DEP_CONTROL:
191e4b17023SJohn Marino t = 'c';
192e4b17023SJohn Marino break;
193e4b17023SJohn Marino
194e4b17023SJohn Marino case REG_DEP_ANTI:
195e4b17023SJohn Marino t = 'a';
196e4b17023SJohn Marino break;
197e4b17023SJohn Marino
198e4b17023SJohn Marino default:
199e4b17023SJohn Marino gcc_unreachable ();
200e4b17023SJohn Marino break;
201e4b17023SJohn Marino }
202e4b17023SJohn Marino
203e4b17023SJohn Marino fprintf (dump, "%c; ", t);
204e4b17023SJohn Marino }
205e4b17023SJohn Marino
206e4b17023SJohn Marino if (flags & DUMP_DEP_STATUS)
207e4b17023SJohn Marino {
208e4b17023SJohn Marino if (current_sched_info->flags & USE_DEPS_LIST)
209e4b17023SJohn Marino dump_ds (dump, DEP_STATUS (dep));
210e4b17023SJohn Marino }
211e4b17023SJohn Marino
212e4b17023SJohn Marino fprintf (dump, ">");
213e4b17023SJohn Marino }
214e4b17023SJohn Marino
215e4b17023SJohn Marino /* Default flags for dump_dep (). */
216e4b17023SJohn Marino static int dump_dep_flags = (DUMP_DEP_PRO | DUMP_DEP_CON);
217e4b17023SJohn Marino
218e4b17023SJohn Marino /* Dump all fields of DEP to STDERR. */
219e4b17023SJohn Marino void
sd_debug_dep(dep_t dep)220e4b17023SJohn Marino sd_debug_dep (dep_t dep)
221e4b17023SJohn Marino {
222e4b17023SJohn Marino dump_dep (stderr, dep, 1);
223e4b17023SJohn Marino fprintf (stderr, "\n");
224e4b17023SJohn Marino }
225e4b17023SJohn Marino
226e4b17023SJohn Marino /* Determine whether DEP is a dependency link of a non-debug insn on a
227e4b17023SJohn Marino debug insn. */
228e4b17023SJohn Marino
229e4b17023SJohn Marino static inline bool
depl_on_debug_p(dep_link_t dep)230e4b17023SJohn Marino depl_on_debug_p (dep_link_t dep)
231e4b17023SJohn Marino {
232e4b17023SJohn Marino return (DEBUG_INSN_P (DEP_LINK_PRO (dep))
233e4b17023SJohn Marino && !DEBUG_INSN_P (DEP_LINK_CON (dep)));
234e4b17023SJohn Marino }
235e4b17023SJohn Marino
236e4b17023SJohn Marino /* Functions to operate with a single link from the dependencies lists -
237e4b17023SJohn Marino dep_link_t. */
238e4b17023SJohn Marino
239e4b17023SJohn Marino /* Attach L to appear after link X whose &DEP_LINK_NEXT (X) is given by
240e4b17023SJohn Marino PREV_NEXT_P. */
241e4b17023SJohn Marino static void
attach_dep_link(dep_link_t l,dep_link_t * prev_nextp)242e4b17023SJohn Marino attach_dep_link (dep_link_t l, dep_link_t *prev_nextp)
243e4b17023SJohn Marino {
244e4b17023SJohn Marino dep_link_t next = *prev_nextp;
245e4b17023SJohn Marino
246e4b17023SJohn Marino gcc_assert (DEP_LINK_PREV_NEXTP (l) == NULL
247e4b17023SJohn Marino && DEP_LINK_NEXT (l) == NULL);
248e4b17023SJohn Marino
249e4b17023SJohn Marino /* Init node being inserted. */
250e4b17023SJohn Marino DEP_LINK_PREV_NEXTP (l) = prev_nextp;
251e4b17023SJohn Marino DEP_LINK_NEXT (l) = next;
252e4b17023SJohn Marino
253e4b17023SJohn Marino /* Fix next node. */
254e4b17023SJohn Marino if (next != NULL)
255e4b17023SJohn Marino {
256e4b17023SJohn Marino gcc_assert (DEP_LINK_PREV_NEXTP (next) == prev_nextp);
257e4b17023SJohn Marino
258e4b17023SJohn Marino DEP_LINK_PREV_NEXTP (next) = &DEP_LINK_NEXT (l);
259e4b17023SJohn Marino }
260e4b17023SJohn Marino
261e4b17023SJohn Marino /* Fix prev node. */
262e4b17023SJohn Marino *prev_nextp = l;
263e4b17023SJohn Marino }
264e4b17023SJohn Marino
265e4b17023SJohn Marino /* Add dep_link LINK to deps_list L. */
266e4b17023SJohn Marino static void
add_to_deps_list(dep_link_t link,deps_list_t l)267e4b17023SJohn Marino add_to_deps_list (dep_link_t link, deps_list_t l)
268e4b17023SJohn Marino {
269e4b17023SJohn Marino attach_dep_link (link, &DEPS_LIST_FIRST (l));
270e4b17023SJohn Marino
271e4b17023SJohn Marino /* Don't count debug deps. */
272e4b17023SJohn Marino if (!depl_on_debug_p (link))
273e4b17023SJohn Marino ++DEPS_LIST_N_LINKS (l);
274e4b17023SJohn Marino }
275e4b17023SJohn Marino
276e4b17023SJohn Marino /* Detach dep_link L from the list. */
277e4b17023SJohn Marino static void
detach_dep_link(dep_link_t l)278e4b17023SJohn Marino detach_dep_link (dep_link_t l)
279e4b17023SJohn Marino {
280e4b17023SJohn Marino dep_link_t *prev_nextp = DEP_LINK_PREV_NEXTP (l);
281e4b17023SJohn Marino dep_link_t next = DEP_LINK_NEXT (l);
282e4b17023SJohn Marino
283e4b17023SJohn Marino *prev_nextp = next;
284e4b17023SJohn Marino
285e4b17023SJohn Marino if (next != NULL)
286e4b17023SJohn Marino DEP_LINK_PREV_NEXTP (next) = prev_nextp;
287e4b17023SJohn Marino
288e4b17023SJohn Marino DEP_LINK_PREV_NEXTP (l) = NULL;
289e4b17023SJohn Marino DEP_LINK_NEXT (l) = NULL;
290e4b17023SJohn Marino }
291e4b17023SJohn Marino
292e4b17023SJohn Marino /* Remove link LINK from list LIST. */
293e4b17023SJohn Marino static void
remove_from_deps_list(dep_link_t link,deps_list_t list)294e4b17023SJohn Marino remove_from_deps_list (dep_link_t link, deps_list_t list)
295e4b17023SJohn Marino {
296e4b17023SJohn Marino detach_dep_link (link);
297e4b17023SJohn Marino
298e4b17023SJohn Marino /* Don't count debug deps. */
299e4b17023SJohn Marino if (!depl_on_debug_p (link))
300e4b17023SJohn Marino --DEPS_LIST_N_LINKS (list);
301e4b17023SJohn Marino }
302e4b17023SJohn Marino
303e4b17023SJohn Marino /* Move link LINK from list FROM to list TO. */
304e4b17023SJohn Marino static void
move_dep_link(dep_link_t link,deps_list_t from,deps_list_t to)305e4b17023SJohn Marino move_dep_link (dep_link_t link, deps_list_t from, deps_list_t to)
306e4b17023SJohn Marino {
307e4b17023SJohn Marino remove_from_deps_list (link, from);
308e4b17023SJohn Marino add_to_deps_list (link, to);
309e4b17023SJohn Marino }
310e4b17023SJohn Marino
311e4b17023SJohn Marino /* Return true of LINK is not attached to any list. */
312e4b17023SJohn Marino static bool
dep_link_is_detached_p(dep_link_t link)313e4b17023SJohn Marino dep_link_is_detached_p (dep_link_t link)
314e4b17023SJohn Marino {
315e4b17023SJohn Marino return DEP_LINK_PREV_NEXTP (link) == NULL;
316e4b17023SJohn Marino }
317e4b17023SJohn Marino
318e4b17023SJohn Marino /* Pool to hold all dependency nodes (dep_node_t). */
319e4b17023SJohn Marino static alloc_pool dn_pool;
320e4b17023SJohn Marino
321e4b17023SJohn Marino /* Number of dep_nodes out there. */
322e4b17023SJohn Marino static int dn_pool_diff = 0;
323e4b17023SJohn Marino
324e4b17023SJohn Marino /* Create a dep_node. */
325e4b17023SJohn Marino static dep_node_t
create_dep_node(void)326e4b17023SJohn Marino create_dep_node (void)
327e4b17023SJohn Marino {
328e4b17023SJohn Marino dep_node_t n = (dep_node_t) pool_alloc (dn_pool);
329e4b17023SJohn Marino dep_link_t back = DEP_NODE_BACK (n);
330e4b17023SJohn Marino dep_link_t forw = DEP_NODE_FORW (n);
331e4b17023SJohn Marino
332e4b17023SJohn Marino DEP_LINK_NODE (back) = n;
333e4b17023SJohn Marino DEP_LINK_NEXT (back) = NULL;
334e4b17023SJohn Marino DEP_LINK_PREV_NEXTP (back) = NULL;
335e4b17023SJohn Marino
336e4b17023SJohn Marino DEP_LINK_NODE (forw) = n;
337e4b17023SJohn Marino DEP_LINK_NEXT (forw) = NULL;
338e4b17023SJohn Marino DEP_LINK_PREV_NEXTP (forw) = NULL;
339e4b17023SJohn Marino
340e4b17023SJohn Marino ++dn_pool_diff;
341e4b17023SJohn Marino
342e4b17023SJohn Marino return n;
343e4b17023SJohn Marino }
344e4b17023SJohn Marino
345e4b17023SJohn Marino /* Delete dep_node N. N must not be connected to any deps_list. */
346e4b17023SJohn Marino static void
delete_dep_node(dep_node_t n)347e4b17023SJohn Marino delete_dep_node (dep_node_t n)
348e4b17023SJohn Marino {
349e4b17023SJohn Marino gcc_assert (dep_link_is_detached_p (DEP_NODE_BACK (n))
350e4b17023SJohn Marino && dep_link_is_detached_p (DEP_NODE_FORW (n)));
351e4b17023SJohn Marino
352e4b17023SJohn Marino --dn_pool_diff;
353e4b17023SJohn Marino
354e4b17023SJohn Marino pool_free (dn_pool, n);
355e4b17023SJohn Marino }
356e4b17023SJohn Marino
357e4b17023SJohn Marino /* Pool to hold dependencies lists (deps_list_t). */
358e4b17023SJohn Marino static alloc_pool dl_pool;
359e4b17023SJohn Marino
360e4b17023SJohn Marino /* Number of deps_lists out there. */
361e4b17023SJohn Marino static int dl_pool_diff = 0;
362e4b17023SJohn Marino
363e4b17023SJohn Marino /* Functions to operate with dependences lists - deps_list_t. */
364e4b17023SJohn Marino
365e4b17023SJohn Marino /* Return true if list L is empty. */
366e4b17023SJohn Marino static bool
deps_list_empty_p(deps_list_t l)367e4b17023SJohn Marino deps_list_empty_p (deps_list_t l)
368e4b17023SJohn Marino {
369e4b17023SJohn Marino return DEPS_LIST_N_LINKS (l) == 0;
370e4b17023SJohn Marino }
371e4b17023SJohn Marino
372e4b17023SJohn Marino /* Create a new deps_list. */
373e4b17023SJohn Marino static deps_list_t
create_deps_list(void)374e4b17023SJohn Marino create_deps_list (void)
375e4b17023SJohn Marino {
376e4b17023SJohn Marino deps_list_t l = (deps_list_t) pool_alloc (dl_pool);
377e4b17023SJohn Marino
378e4b17023SJohn Marino DEPS_LIST_FIRST (l) = NULL;
379e4b17023SJohn Marino DEPS_LIST_N_LINKS (l) = 0;
380e4b17023SJohn Marino
381e4b17023SJohn Marino ++dl_pool_diff;
382e4b17023SJohn Marino return l;
383e4b17023SJohn Marino }
384e4b17023SJohn Marino
385e4b17023SJohn Marino /* Free deps_list L. */
386e4b17023SJohn Marino static void
free_deps_list(deps_list_t l)387e4b17023SJohn Marino free_deps_list (deps_list_t l)
388e4b17023SJohn Marino {
389e4b17023SJohn Marino gcc_assert (deps_list_empty_p (l));
390e4b17023SJohn Marino
391e4b17023SJohn Marino --dl_pool_diff;
392e4b17023SJohn Marino
393e4b17023SJohn Marino pool_free (dl_pool, l);
394e4b17023SJohn Marino }
395e4b17023SJohn Marino
396e4b17023SJohn Marino /* Return true if there is no dep_nodes and deps_lists out there.
397e4b17023SJohn Marino After the region is scheduled all the dependency nodes and lists
398e4b17023SJohn Marino should [generally] be returned to pool. */
399e4b17023SJohn Marino bool
deps_pools_are_empty_p(void)400e4b17023SJohn Marino deps_pools_are_empty_p (void)
401e4b17023SJohn Marino {
402e4b17023SJohn Marino return dn_pool_diff == 0 && dl_pool_diff == 0;
403e4b17023SJohn Marino }
404e4b17023SJohn Marino
405e4b17023SJohn Marino /* Remove all elements from L. */
406e4b17023SJohn Marino static void
clear_deps_list(deps_list_t l)407e4b17023SJohn Marino clear_deps_list (deps_list_t l)
408e4b17023SJohn Marino {
409e4b17023SJohn Marino do
410e4b17023SJohn Marino {
411e4b17023SJohn Marino dep_link_t link = DEPS_LIST_FIRST (l);
412e4b17023SJohn Marino
413e4b17023SJohn Marino if (link == NULL)
414e4b17023SJohn Marino break;
415e4b17023SJohn Marino
416e4b17023SJohn Marino remove_from_deps_list (link, l);
417e4b17023SJohn Marino }
418e4b17023SJohn Marino while (1);
419e4b17023SJohn Marino }
420e4b17023SJohn Marino
421e4b17023SJohn Marino /* Decide whether a dependency should be treated as a hard or a speculative
422e4b17023SJohn Marino dependency. */
423e4b17023SJohn Marino static bool
dep_spec_p(dep_t dep)424e4b17023SJohn Marino dep_spec_p (dep_t dep)
425e4b17023SJohn Marino {
426e4b17023SJohn Marino if (current_sched_info->flags & DO_SPECULATION)
427e4b17023SJohn Marino {
428e4b17023SJohn Marino if (DEP_STATUS (dep) & SPECULATIVE)
429e4b17023SJohn Marino return true;
430e4b17023SJohn Marino }
431e4b17023SJohn Marino if (current_sched_info->flags & DO_PREDICATION)
432e4b17023SJohn Marino {
433e4b17023SJohn Marino if (DEP_TYPE (dep) == REG_DEP_CONTROL)
434e4b17023SJohn Marino return true;
435e4b17023SJohn Marino }
436e4b17023SJohn Marino return false;
437e4b17023SJohn Marino }
438e4b17023SJohn Marino
439e4b17023SJohn Marino static regset reg_pending_sets;
440e4b17023SJohn Marino static regset reg_pending_clobbers;
441e4b17023SJohn Marino static regset reg_pending_uses;
442e4b17023SJohn Marino static regset reg_pending_control_uses;
443e4b17023SJohn Marino static enum reg_pending_barrier_mode reg_pending_barrier;
444e4b17023SJohn Marino
445e4b17023SJohn Marino /* Hard registers implicitly clobbered or used (or may be implicitly
446e4b17023SJohn Marino clobbered or used) by the currently analyzed insn. For example,
447e4b17023SJohn Marino insn in its constraint has one register class. Even if there is
448e4b17023SJohn Marino currently no hard register in the insn, the particular hard
449e4b17023SJohn Marino register will be in the insn after reload pass because the
450e4b17023SJohn Marino constraint requires it. */
451e4b17023SJohn Marino static HARD_REG_SET implicit_reg_pending_clobbers;
452e4b17023SJohn Marino static HARD_REG_SET implicit_reg_pending_uses;
453e4b17023SJohn Marino
454e4b17023SJohn Marino /* To speed up the test for duplicate dependency links we keep a
455e4b17023SJohn Marino record of dependencies created by add_dependence when the average
456e4b17023SJohn Marino number of instructions in a basic block is very large.
457e4b17023SJohn Marino
458e4b17023SJohn Marino Studies have shown that there is typically around 5 instructions between
459e4b17023SJohn Marino branches for typical C code. So we can make a guess that the average
460e4b17023SJohn Marino basic block is approximately 5 instructions long; we will choose 100X
461e4b17023SJohn Marino the average size as a very large basic block.
462e4b17023SJohn Marino
463e4b17023SJohn Marino Each insn has associated bitmaps for its dependencies. Each bitmap
464e4b17023SJohn Marino has enough entries to represent a dependency on any other insn in
465e4b17023SJohn Marino the insn chain. All bitmap for true dependencies cache is
466e4b17023SJohn Marino allocated then the rest two ones are also allocated. */
467e4b17023SJohn Marino static bitmap_head *true_dependency_cache = NULL;
468e4b17023SJohn Marino static bitmap_head *output_dependency_cache = NULL;
469e4b17023SJohn Marino static bitmap_head *anti_dependency_cache = NULL;
470e4b17023SJohn Marino static bitmap_head *control_dependency_cache = NULL;
471e4b17023SJohn Marino static bitmap_head *spec_dependency_cache = NULL;
472e4b17023SJohn Marino static int cache_size;
473e4b17023SJohn Marino
474e4b17023SJohn Marino static int deps_may_trap_p (const_rtx);
475e4b17023SJohn Marino static void add_dependence_1 (rtx, rtx, enum reg_note);
476e4b17023SJohn Marino static void add_dependence_list (rtx, rtx, int, enum reg_note);
477e4b17023SJohn Marino static void add_dependence_list_and_free (struct deps_desc *, rtx,
478e4b17023SJohn Marino rtx *, int, enum reg_note);
479e4b17023SJohn Marino static void delete_all_dependences (rtx);
480e4b17023SJohn Marino static void fixup_sched_groups (rtx);
481e4b17023SJohn Marino
482e4b17023SJohn Marino static void flush_pending_lists (struct deps_desc *, rtx, int, int);
483e4b17023SJohn Marino static void sched_analyze_1 (struct deps_desc *, rtx, rtx);
484e4b17023SJohn Marino static void sched_analyze_2 (struct deps_desc *, rtx, rtx);
485e4b17023SJohn Marino static void sched_analyze_insn (struct deps_desc *, rtx, rtx);
486e4b17023SJohn Marino
487e4b17023SJohn Marino static bool sched_has_condition_p (const_rtx);
488e4b17023SJohn Marino static int conditions_mutex_p (const_rtx, const_rtx, bool, bool);
489e4b17023SJohn Marino
490e4b17023SJohn Marino static enum DEPS_ADJUST_RESULT maybe_add_or_update_dep_1 (dep_t, bool,
491e4b17023SJohn Marino rtx, rtx);
492e4b17023SJohn Marino static enum DEPS_ADJUST_RESULT add_or_update_dep_1 (dep_t, bool, rtx, rtx);
493e4b17023SJohn Marino
494e4b17023SJohn Marino #ifdef ENABLE_CHECKING
495e4b17023SJohn Marino static void check_dep (dep_t, bool);
496e4b17023SJohn Marino #endif
497e4b17023SJohn Marino
498e4b17023SJohn Marino /* Return nonzero if a load of the memory reference MEM can cause a trap. */
499e4b17023SJohn Marino
500e4b17023SJohn Marino static int
deps_may_trap_p(const_rtx mem)501e4b17023SJohn Marino deps_may_trap_p (const_rtx mem)
502e4b17023SJohn Marino {
503e4b17023SJohn Marino const_rtx addr = XEXP (mem, 0);
504e4b17023SJohn Marino
505e4b17023SJohn Marino if (REG_P (addr) && REGNO (addr) >= FIRST_PSEUDO_REGISTER)
506e4b17023SJohn Marino {
507e4b17023SJohn Marino const_rtx t = get_reg_known_value (REGNO (addr));
508e4b17023SJohn Marino if (t)
509e4b17023SJohn Marino addr = t;
510e4b17023SJohn Marino }
511e4b17023SJohn Marino return rtx_addr_can_trap_p (addr);
512e4b17023SJohn Marino }
513e4b17023SJohn Marino
514e4b17023SJohn Marino
515e4b17023SJohn Marino /* Find the condition under which INSN is executed. If REV is not NULL,
516e4b17023SJohn Marino it is set to TRUE when the returned comparison should be reversed
517e4b17023SJohn Marino to get the actual condition. */
518e4b17023SJohn Marino static rtx
sched_get_condition_with_rev_uncached(const_rtx insn,bool * rev)519e4b17023SJohn Marino sched_get_condition_with_rev_uncached (const_rtx insn, bool *rev)
520e4b17023SJohn Marino {
521e4b17023SJohn Marino rtx pat = PATTERN (insn);
522e4b17023SJohn Marino rtx src;
523e4b17023SJohn Marino
524e4b17023SJohn Marino if (rev)
525e4b17023SJohn Marino *rev = false;
526e4b17023SJohn Marino
527e4b17023SJohn Marino if (GET_CODE (pat) == COND_EXEC)
528e4b17023SJohn Marino return COND_EXEC_TEST (pat);
529e4b17023SJohn Marino
530e4b17023SJohn Marino if (!any_condjump_p (insn) || !onlyjump_p (insn))
531e4b17023SJohn Marino return 0;
532e4b17023SJohn Marino
533e4b17023SJohn Marino src = SET_SRC (pc_set (insn));
534e4b17023SJohn Marino
535e4b17023SJohn Marino if (XEXP (src, 2) == pc_rtx)
536e4b17023SJohn Marino return XEXP (src, 0);
537e4b17023SJohn Marino else if (XEXP (src, 1) == pc_rtx)
538e4b17023SJohn Marino {
539e4b17023SJohn Marino rtx cond = XEXP (src, 0);
540e4b17023SJohn Marino enum rtx_code revcode = reversed_comparison_code (cond, insn);
541e4b17023SJohn Marino
542e4b17023SJohn Marino if (revcode == UNKNOWN)
543e4b17023SJohn Marino return 0;
544e4b17023SJohn Marino
545e4b17023SJohn Marino if (rev)
546e4b17023SJohn Marino *rev = true;
547e4b17023SJohn Marino return cond;
548e4b17023SJohn Marino }
549e4b17023SJohn Marino
550e4b17023SJohn Marino return 0;
551e4b17023SJohn Marino }
552e4b17023SJohn Marino
553e4b17023SJohn Marino /* Return the condition under which INSN does not execute (i.e. the
554e4b17023SJohn Marino not-taken condition for a conditional branch), or NULL if we cannot
555e4b17023SJohn Marino find such a condition. The caller should make a copy of the condition
556e4b17023SJohn Marino before using it. */
557e4b17023SJohn Marino rtx
sched_get_reverse_condition_uncached(const_rtx insn)558e4b17023SJohn Marino sched_get_reverse_condition_uncached (const_rtx insn)
559e4b17023SJohn Marino {
560e4b17023SJohn Marino bool rev;
561e4b17023SJohn Marino rtx cond = sched_get_condition_with_rev_uncached (insn, &rev);
562e4b17023SJohn Marino if (cond == NULL_RTX)
563e4b17023SJohn Marino return cond;
564e4b17023SJohn Marino if (!rev)
565e4b17023SJohn Marino {
566e4b17023SJohn Marino enum rtx_code revcode = reversed_comparison_code (cond, insn);
567e4b17023SJohn Marino cond = gen_rtx_fmt_ee (revcode, GET_MODE (cond),
568e4b17023SJohn Marino XEXP (cond, 0),
569e4b17023SJohn Marino XEXP (cond, 1));
570e4b17023SJohn Marino }
571e4b17023SJohn Marino return cond;
572e4b17023SJohn Marino }
573e4b17023SJohn Marino
574e4b17023SJohn Marino /* Caching variant of sched_get_condition_with_rev_uncached.
575e4b17023SJohn Marino We only do actual work the first time we come here for an insn; the
576e4b17023SJohn Marino results are cached in INSN_CACHED_COND and INSN_REVERSE_COND. */
577e4b17023SJohn Marino static rtx
sched_get_condition_with_rev(const_rtx insn,bool * rev)578e4b17023SJohn Marino sched_get_condition_with_rev (const_rtx insn, bool *rev)
579e4b17023SJohn Marino {
580e4b17023SJohn Marino bool tmp;
581e4b17023SJohn Marino
582e4b17023SJohn Marino if (INSN_LUID (insn) == 0)
583e4b17023SJohn Marino return sched_get_condition_with_rev_uncached (insn, rev);
584e4b17023SJohn Marino
585e4b17023SJohn Marino if (INSN_CACHED_COND (insn) == const_true_rtx)
586e4b17023SJohn Marino return NULL_RTX;
587e4b17023SJohn Marino
588e4b17023SJohn Marino if (INSN_CACHED_COND (insn) != NULL_RTX)
589e4b17023SJohn Marino {
590e4b17023SJohn Marino if (rev)
591e4b17023SJohn Marino *rev = INSN_REVERSE_COND (insn);
592e4b17023SJohn Marino return INSN_CACHED_COND (insn);
593e4b17023SJohn Marino }
594e4b17023SJohn Marino
595e4b17023SJohn Marino INSN_CACHED_COND (insn) = sched_get_condition_with_rev_uncached (insn, &tmp);
596e4b17023SJohn Marino INSN_REVERSE_COND (insn) = tmp;
597e4b17023SJohn Marino
598e4b17023SJohn Marino if (INSN_CACHED_COND (insn) == NULL_RTX)
599e4b17023SJohn Marino {
600e4b17023SJohn Marino INSN_CACHED_COND (insn) = const_true_rtx;
601e4b17023SJohn Marino return NULL_RTX;
602e4b17023SJohn Marino }
603e4b17023SJohn Marino
604e4b17023SJohn Marino if (rev)
605e4b17023SJohn Marino *rev = INSN_REVERSE_COND (insn);
606e4b17023SJohn Marino return INSN_CACHED_COND (insn);
607e4b17023SJohn Marino }
608e4b17023SJohn Marino
609e4b17023SJohn Marino /* True when we can find a condition under which INSN is executed. */
610e4b17023SJohn Marino static bool
sched_has_condition_p(const_rtx insn)611e4b17023SJohn Marino sched_has_condition_p (const_rtx insn)
612e4b17023SJohn Marino {
613e4b17023SJohn Marino return !! sched_get_condition_with_rev (insn, NULL);
614e4b17023SJohn Marino }
615e4b17023SJohn Marino
616e4b17023SJohn Marino
617e4b17023SJohn Marino
618e4b17023SJohn Marino /* Return nonzero if conditions COND1 and COND2 can never be both true. */
619e4b17023SJohn Marino static int
conditions_mutex_p(const_rtx cond1,const_rtx cond2,bool rev1,bool rev2)620e4b17023SJohn Marino conditions_mutex_p (const_rtx cond1, const_rtx cond2, bool rev1, bool rev2)
621e4b17023SJohn Marino {
622e4b17023SJohn Marino if (COMPARISON_P (cond1)
623e4b17023SJohn Marino && COMPARISON_P (cond2)
624e4b17023SJohn Marino && GET_CODE (cond1) ==
625e4b17023SJohn Marino (rev1==rev2
626e4b17023SJohn Marino ? reversed_comparison_code (cond2, NULL)
627e4b17023SJohn Marino : GET_CODE (cond2))
628e4b17023SJohn Marino && rtx_equal_p (XEXP (cond1, 0), XEXP (cond2, 0))
629e4b17023SJohn Marino && XEXP (cond1, 1) == XEXP (cond2, 1))
630e4b17023SJohn Marino return 1;
631e4b17023SJohn Marino return 0;
632e4b17023SJohn Marino }
633e4b17023SJohn Marino
634e4b17023SJohn Marino /* Return true if insn1 and insn2 can never depend on one another because
635e4b17023SJohn Marino the conditions under which they are executed are mutually exclusive. */
636e4b17023SJohn Marino bool
sched_insns_conditions_mutex_p(const_rtx insn1,const_rtx insn2)637e4b17023SJohn Marino sched_insns_conditions_mutex_p (const_rtx insn1, const_rtx insn2)
638e4b17023SJohn Marino {
639e4b17023SJohn Marino rtx cond1, cond2;
640e4b17023SJohn Marino bool rev1 = false, rev2 = false;
641e4b17023SJohn Marino
642e4b17023SJohn Marino /* df doesn't handle conditional lifetimes entirely correctly;
643e4b17023SJohn Marino calls mess up the conditional lifetimes. */
644e4b17023SJohn Marino if (!CALL_P (insn1) && !CALL_P (insn2))
645e4b17023SJohn Marino {
646e4b17023SJohn Marino cond1 = sched_get_condition_with_rev (insn1, &rev1);
647e4b17023SJohn Marino cond2 = sched_get_condition_with_rev (insn2, &rev2);
648e4b17023SJohn Marino if (cond1 && cond2
649e4b17023SJohn Marino && conditions_mutex_p (cond1, cond2, rev1, rev2)
650e4b17023SJohn Marino /* Make sure first instruction doesn't affect condition of second
651e4b17023SJohn Marino instruction if switched. */
652e4b17023SJohn Marino && !modified_in_p (cond1, insn2)
653e4b17023SJohn Marino /* Make sure second instruction doesn't affect condition of first
654e4b17023SJohn Marino instruction if switched. */
655e4b17023SJohn Marino && !modified_in_p (cond2, insn1))
656e4b17023SJohn Marino return true;
657e4b17023SJohn Marino }
658e4b17023SJohn Marino return false;
659e4b17023SJohn Marino }
660e4b17023SJohn Marino
661e4b17023SJohn Marino
662e4b17023SJohn Marino /* Return true if INSN can potentially be speculated with type DS. */
663e4b17023SJohn Marino bool
sched_insn_is_legitimate_for_speculation_p(const_rtx insn,ds_t ds)664e4b17023SJohn Marino sched_insn_is_legitimate_for_speculation_p (const_rtx insn, ds_t ds)
665e4b17023SJohn Marino {
666e4b17023SJohn Marino if (HAS_INTERNAL_DEP (insn))
667e4b17023SJohn Marino return false;
668e4b17023SJohn Marino
669e4b17023SJohn Marino if (!NONJUMP_INSN_P (insn))
670e4b17023SJohn Marino return false;
671e4b17023SJohn Marino
672e4b17023SJohn Marino if (SCHED_GROUP_P (insn))
673e4b17023SJohn Marino return false;
674e4b17023SJohn Marino
675e4b17023SJohn Marino if (IS_SPECULATION_CHECK_P (CONST_CAST_RTX (insn)))
676e4b17023SJohn Marino return false;
677e4b17023SJohn Marino
678e4b17023SJohn Marino if (side_effects_p (PATTERN (insn)))
679e4b17023SJohn Marino return false;
680e4b17023SJohn Marino
681e4b17023SJohn Marino if (ds & BE_IN_SPEC)
682e4b17023SJohn Marino /* The following instructions, which depend on a speculatively scheduled
683e4b17023SJohn Marino instruction, cannot be speculatively scheduled along. */
684e4b17023SJohn Marino {
685e4b17023SJohn Marino if (may_trap_or_fault_p (PATTERN (insn)))
686e4b17023SJohn Marino /* If instruction might fault, it cannot be speculatively scheduled.
687e4b17023SJohn Marino For control speculation it's obvious why and for data speculation
688e4b17023SJohn Marino it's because the insn might get wrong input if speculation
689e4b17023SJohn Marino wasn't successful. */
690e4b17023SJohn Marino return false;
691e4b17023SJohn Marino
692e4b17023SJohn Marino if ((ds & BE_IN_DATA)
693e4b17023SJohn Marino && sched_has_condition_p (insn))
694e4b17023SJohn Marino /* If this is a predicated instruction, then it cannot be
695e4b17023SJohn Marino speculatively scheduled. See PR35659. */
696e4b17023SJohn Marino return false;
697e4b17023SJohn Marino }
698e4b17023SJohn Marino
699e4b17023SJohn Marino return true;
700e4b17023SJohn Marino }
701e4b17023SJohn Marino
702e4b17023SJohn Marino /* Initialize LIST_PTR to point to one of the lists present in TYPES_PTR,
703e4b17023SJohn Marino initialize RESOLVED_P_PTR with true if that list consists of resolved deps,
704e4b17023SJohn Marino and remove the type of returned [through LIST_PTR] list from TYPES_PTR.
705e4b17023SJohn Marino This function is used to switch sd_iterator to the next list.
706e4b17023SJohn Marino !!! For internal use only. Might consider moving it to sched-int.h. */
707e4b17023SJohn Marino void
sd_next_list(const_rtx insn,sd_list_types_def * types_ptr,deps_list_t * list_ptr,bool * resolved_p_ptr)708e4b17023SJohn Marino sd_next_list (const_rtx insn, sd_list_types_def *types_ptr,
709e4b17023SJohn Marino deps_list_t *list_ptr, bool *resolved_p_ptr)
710e4b17023SJohn Marino {
711e4b17023SJohn Marino sd_list_types_def types = *types_ptr;
712e4b17023SJohn Marino
713e4b17023SJohn Marino if (types & SD_LIST_HARD_BACK)
714e4b17023SJohn Marino {
715e4b17023SJohn Marino *list_ptr = INSN_HARD_BACK_DEPS (insn);
716e4b17023SJohn Marino *resolved_p_ptr = false;
717e4b17023SJohn Marino *types_ptr = types & ~SD_LIST_HARD_BACK;
718e4b17023SJohn Marino }
719e4b17023SJohn Marino else if (types & SD_LIST_SPEC_BACK)
720e4b17023SJohn Marino {
721e4b17023SJohn Marino *list_ptr = INSN_SPEC_BACK_DEPS (insn);
722e4b17023SJohn Marino *resolved_p_ptr = false;
723e4b17023SJohn Marino *types_ptr = types & ~SD_LIST_SPEC_BACK;
724e4b17023SJohn Marino }
725e4b17023SJohn Marino else if (types & SD_LIST_FORW)
726e4b17023SJohn Marino {
727e4b17023SJohn Marino *list_ptr = INSN_FORW_DEPS (insn);
728e4b17023SJohn Marino *resolved_p_ptr = false;
729e4b17023SJohn Marino *types_ptr = types & ~SD_LIST_FORW;
730e4b17023SJohn Marino }
731e4b17023SJohn Marino else if (types & SD_LIST_RES_BACK)
732e4b17023SJohn Marino {
733e4b17023SJohn Marino *list_ptr = INSN_RESOLVED_BACK_DEPS (insn);
734e4b17023SJohn Marino *resolved_p_ptr = true;
735e4b17023SJohn Marino *types_ptr = types & ~SD_LIST_RES_BACK;
736e4b17023SJohn Marino }
737e4b17023SJohn Marino else if (types & SD_LIST_RES_FORW)
738e4b17023SJohn Marino {
739e4b17023SJohn Marino *list_ptr = INSN_RESOLVED_FORW_DEPS (insn);
740e4b17023SJohn Marino *resolved_p_ptr = true;
741e4b17023SJohn Marino *types_ptr = types & ~SD_LIST_RES_FORW;
742e4b17023SJohn Marino }
743e4b17023SJohn Marino else
744e4b17023SJohn Marino {
745e4b17023SJohn Marino *list_ptr = NULL;
746e4b17023SJohn Marino *resolved_p_ptr = false;
747e4b17023SJohn Marino *types_ptr = SD_LIST_NONE;
748e4b17023SJohn Marino }
749e4b17023SJohn Marino }
750e4b17023SJohn Marino
751e4b17023SJohn Marino /* Return the summary size of INSN's lists defined by LIST_TYPES. */
752e4b17023SJohn Marino int
sd_lists_size(const_rtx insn,sd_list_types_def list_types)753e4b17023SJohn Marino sd_lists_size (const_rtx insn, sd_list_types_def list_types)
754e4b17023SJohn Marino {
755e4b17023SJohn Marino int size = 0;
756e4b17023SJohn Marino
757e4b17023SJohn Marino while (list_types != SD_LIST_NONE)
758e4b17023SJohn Marino {
759e4b17023SJohn Marino deps_list_t list;
760e4b17023SJohn Marino bool resolved_p;
761e4b17023SJohn Marino
762e4b17023SJohn Marino sd_next_list (insn, &list_types, &list, &resolved_p);
763e4b17023SJohn Marino if (list)
764e4b17023SJohn Marino size += DEPS_LIST_N_LINKS (list);
765e4b17023SJohn Marino }
766e4b17023SJohn Marino
767e4b17023SJohn Marino return size;
768e4b17023SJohn Marino }
769e4b17023SJohn Marino
770e4b17023SJohn Marino /* Return true if INSN's lists defined by LIST_TYPES are all empty. */
771e4b17023SJohn Marino
772e4b17023SJohn Marino bool
sd_lists_empty_p(const_rtx insn,sd_list_types_def list_types)773e4b17023SJohn Marino sd_lists_empty_p (const_rtx insn, sd_list_types_def list_types)
774e4b17023SJohn Marino {
775e4b17023SJohn Marino while (list_types != SD_LIST_NONE)
776e4b17023SJohn Marino {
777e4b17023SJohn Marino deps_list_t list;
778e4b17023SJohn Marino bool resolved_p;
779e4b17023SJohn Marino
780e4b17023SJohn Marino sd_next_list (insn, &list_types, &list, &resolved_p);
781e4b17023SJohn Marino if (!deps_list_empty_p (list))
782e4b17023SJohn Marino return false;
783e4b17023SJohn Marino }
784e4b17023SJohn Marino
785e4b17023SJohn Marino return true;
786e4b17023SJohn Marino }
787e4b17023SJohn Marino
788e4b17023SJohn Marino /* Initialize data for INSN. */
789e4b17023SJohn Marino void
sd_init_insn(rtx insn)790e4b17023SJohn Marino sd_init_insn (rtx insn)
791e4b17023SJohn Marino {
792e4b17023SJohn Marino INSN_HARD_BACK_DEPS (insn) = create_deps_list ();
793e4b17023SJohn Marino INSN_SPEC_BACK_DEPS (insn) = create_deps_list ();
794e4b17023SJohn Marino INSN_RESOLVED_BACK_DEPS (insn) = create_deps_list ();
795e4b17023SJohn Marino INSN_FORW_DEPS (insn) = create_deps_list ();
796e4b17023SJohn Marino INSN_RESOLVED_FORW_DEPS (insn) = create_deps_list ();
797e4b17023SJohn Marino
798e4b17023SJohn Marino /* ??? It would be nice to allocate dependency caches here. */
799e4b17023SJohn Marino }
800e4b17023SJohn Marino
801e4b17023SJohn Marino /* Free data for INSN. */
802e4b17023SJohn Marino void
sd_finish_insn(rtx insn)803e4b17023SJohn Marino sd_finish_insn (rtx insn)
804e4b17023SJohn Marino {
805e4b17023SJohn Marino /* ??? It would be nice to deallocate dependency caches here. */
806e4b17023SJohn Marino
807e4b17023SJohn Marino free_deps_list (INSN_HARD_BACK_DEPS (insn));
808e4b17023SJohn Marino INSN_HARD_BACK_DEPS (insn) = NULL;
809e4b17023SJohn Marino
810e4b17023SJohn Marino free_deps_list (INSN_SPEC_BACK_DEPS (insn));
811e4b17023SJohn Marino INSN_SPEC_BACK_DEPS (insn) = NULL;
812e4b17023SJohn Marino
813e4b17023SJohn Marino free_deps_list (INSN_RESOLVED_BACK_DEPS (insn));
814e4b17023SJohn Marino INSN_RESOLVED_BACK_DEPS (insn) = NULL;
815e4b17023SJohn Marino
816e4b17023SJohn Marino free_deps_list (INSN_FORW_DEPS (insn));
817e4b17023SJohn Marino INSN_FORW_DEPS (insn) = NULL;
818e4b17023SJohn Marino
819e4b17023SJohn Marino free_deps_list (INSN_RESOLVED_FORW_DEPS (insn));
820e4b17023SJohn Marino INSN_RESOLVED_FORW_DEPS (insn) = NULL;
821e4b17023SJohn Marino }
822e4b17023SJohn Marino
823e4b17023SJohn Marino /* Find a dependency between producer PRO and consumer CON.
824e4b17023SJohn Marino Search through resolved dependency lists if RESOLVED_P is true.
825e4b17023SJohn Marino If no such dependency is found return NULL,
826e4b17023SJohn Marino otherwise return the dependency and initialize SD_IT_PTR [if it is nonnull]
827e4b17023SJohn Marino with an iterator pointing to it. */
828e4b17023SJohn Marino static dep_t
sd_find_dep_between_no_cache(rtx pro,rtx con,bool resolved_p,sd_iterator_def * sd_it_ptr)829e4b17023SJohn Marino sd_find_dep_between_no_cache (rtx pro, rtx con, bool resolved_p,
830e4b17023SJohn Marino sd_iterator_def *sd_it_ptr)
831e4b17023SJohn Marino {
832e4b17023SJohn Marino sd_list_types_def pro_list_type;
833e4b17023SJohn Marino sd_list_types_def con_list_type;
834e4b17023SJohn Marino sd_iterator_def sd_it;
835e4b17023SJohn Marino dep_t dep;
836e4b17023SJohn Marino bool found_p = false;
837e4b17023SJohn Marino
838e4b17023SJohn Marino if (resolved_p)
839e4b17023SJohn Marino {
840e4b17023SJohn Marino pro_list_type = SD_LIST_RES_FORW;
841e4b17023SJohn Marino con_list_type = SD_LIST_RES_BACK;
842e4b17023SJohn Marino }
843e4b17023SJohn Marino else
844e4b17023SJohn Marino {
845e4b17023SJohn Marino pro_list_type = SD_LIST_FORW;
846e4b17023SJohn Marino con_list_type = SD_LIST_BACK;
847e4b17023SJohn Marino }
848e4b17023SJohn Marino
849e4b17023SJohn Marino /* Walk through either back list of INSN or forw list of ELEM
850e4b17023SJohn Marino depending on which one is shorter. */
851e4b17023SJohn Marino if (sd_lists_size (con, con_list_type) < sd_lists_size (pro, pro_list_type))
852e4b17023SJohn Marino {
853e4b17023SJohn Marino /* Find the dep_link with producer PRO in consumer's back_deps. */
854e4b17023SJohn Marino FOR_EACH_DEP (con, con_list_type, sd_it, dep)
855e4b17023SJohn Marino if (DEP_PRO (dep) == pro)
856e4b17023SJohn Marino {
857e4b17023SJohn Marino found_p = true;
858e4b17023SJohn Marino break;
859e4b17023SJohn Marino }
860e4b17023SJohn Marino }
861e4b17023SJohn Marino else
862e4b17023SJohn Marino {
863e4b17023SJohn Marino /* Find the dep_link with consumer CON in producer's forw_deps. */
864e4b17023SJohn Marino FOR_EACH_DEP (pro, pro_list_type, sd_it, dep)
865e4b17023SJohn Marino if (DEP_CON (dep) == con)
866e4b17023SJohn Marino {
867e4b17023SJohn Marino found_p = true;
868e4b17023SJohn Marino break;
869e4b17023SJohn Marino }
870e4b17023SJohn Marino }
871e4b17023SJohn Marino
872e4b17023SJohn Marino if (found_p)
873e4b17023SJohn Marino {
874e4b17023SJohn Marino if (sd_it_ptr != NULL)
875e4b17023SJohn Marino *sd_it_ptr = sd_it;
876e4b17023SJohn Marino
877e4b17023SJohn Marino return dep;
878e4b17023SJohn Marino }
879e4b17023SJohn Marino
880e4b17023SJohn Marino return NULL;
881e4b17023SJohn Marino }
882e4b17023SJohn Marino
883e4b17023SJohn Marino /* Find a dependency between producer PRO and consumer CON.
884e4b17023SJohn Marino Use dependency [if available] to check if dependency is present at all.
885e4b17023SJohn Marino Search through resolved dependency lists if RESOLVED_P is true.
886e4b17023SJohn Marino If the dependency or NULL if none found. */
887e4b17023SJohn Marino dep_t
sd_find_dep_between(rtx pro,rtx con,bool resolved_p)888e4b17023SJohn Marino sd_find_dep_between (rtx pro, rtx con, bool resolved_p)
889e4b17023SJohn Marino {
890e4b17023SJohn Marino if (true_dependency_cache != NULL)
891e4b17023SJohn Marino /* Avoiding the list walk below can cut compile times dramatically
892e4b17023SJohn Marino for some code. */
893e4b17023SJohn Marino {
894e4b17023SJohn Marino int elem_luid = INSN_LUID (pro);
895e4b17023SJohn Marino int insn_luid = INSN_LUID (con);
896e4b17023SJohn Marino
897e4b17023SJohn Marino if (!bitmap_bit_p (&true_dependency_cache[insn_luid], elem_luid)
898e4b17023SJohn Marino && !bitmap_bit_p (&output_dependency_cache[insn_luid], elem_luid)
899e4b17023SJohn Marino && !bitmap_bit_p (&anti_dependency_cache[insn_luid], elem_luid)
900e4b17023SJohn Marino && !bitmap_bit_p (&control_dependency_cache[insn_luid], elem_luid))
901e4b17023SJohn Marino return NULL;
902e4b17023SJohn Marino }
903e4b17023SJohn Marino
904e4b17023SJohn Marino return sd_find_dep_between_no_cache (pro, con, resolved_p, NULL);
905e4b17023SJohn Marino }
906e4b17023SJohn Marino
907e4b17023SJohn Marino /* Add or update a dependence described by DEP.
908e4b17023SJohn Marino MEM1 and MEM2, if non-null, correspond to memory locations in case of
909e4b17023SJohn Marino data speculation.
910e4b17023SJohn Marino
911e4b17023SJohn Marino The function returns a value indicating if an old entry has been changed
912e4b17023SJohn Marino or a new entry has been added to insn's backward deps.
913e4b17023SJohn Marino
914e4b17023SJohn Marino This function merely checks if producer and consumer is the same insn
915e4b17023SJohn Marino and doesn't create a dep in this case. Actual manipulation of
916e4b17023SJohn Marino dependence data structures is performed in add_or_update_dep_1. */
917e4b17023SJohn Marino static enum DEPS_ADJUST_RESULT
maybe_add_or_update_dep_1(dep_t dep,bool resolved_p,rtx mem1,rtx mem2)918e4b17023SJohn Marino maybe_add_or_update_dep_1 (dep_t dep, bool resolved_p, rtx mem1, rtx mem2)
919e4b17023SJohn Marino {
920e4b17023SJohn Marino rtx elem = DEP_PRO (dep);
921e4b17023SJohn Marino rtx insn = DEP_CON (dep);
922e4b17023SJohn Marino
923e4b17023SJohn Marino gcc_assert (INSN_P (insn) && INSN_P (elem));
924e4b17023SJohn Marino
925e4b17023SJohn Marino /* Don't depend an insn on itself. */
926e4b17023SJohn Marino if (insn == elem)
927e4b17023SJohn Marino {
928e4b17023SJohn Marino if (sched_deps_info->generate_spec_deps)
929e4b17023SJohn Marino /* INSN has an internal dependence, which we can't overcome. */
930e4b17023SJohn Marino HAS_INTERNAL_DEP (insn) = 1;
931e4b17023SJohn Marino
932e4b17023SJohn Marino return DEP_NODEP;
933e4b17023SJohn Marino }
934e4b17023SJohn Marino
935e4b17023SJohn Marino return add_or_update_dep_1 (dep, resolved_p, mem1, mem2);
936e4b17023SJohn Marino }
937e4b17023SJohn Marino
938e4b17023SJohn Marino /* Ask dependency caches what needs to be done for dependence DEP.
939e4b17023SJohn Marino Return DEP_CREATED if new dependence should be created and there is no
940e4b17023SJohn Marino need to try to find one searching the dependencies lists.
941e4b17023SJohn Marino Return DEP_PRESENT if there already is a dependence described by DEP and
942e4b17023SJohn Marino hence nothing is to be done.
943e4b17023SJohn Marino Return DEP_CHANGED if there already is a dependence, but it should be
944e4b17023SJohn Marino updated to incorporate additional information from DEP. */
945e4b17023SJohn Marino static enum DEPS_ADJUST_RESULT
ask_dependency_caches(dep_t dep)946e4b17023SJohn Marino ask_dependency_caches (dep_t dep)
947e4b17023SJohn Marino {
948e4b17023SJohn Marino int elem_luid = INSN_LUID (DEP_PRO (dep));
949e4b17023SJohn Marino int insn_luid = INSN_LUID (DEP_CON (dep));
950e4b17023SJohn Marino
951e4b17023SJohn Marino gcc_assert (true_dependency_cache != NULL
952e4b17023SJohn Marino && output_dependency_cache != NULL
953e4b17023SJohn Marino && anti_dependency_cache != NULL
954e4b17023SJohn Marino && control_dependency_cache != NULL);
955e4b17023SJohn Marino
956e4b17023SJohn Marino if (!(current_sched_info->flags & USE_DEPS_LIST))
957e4b17023SJohn Marino {
958e4b17023SJohn Marino enum reg_note present_dep_type;
959e4b17023SJohn Marino
960e4b17023SJohn Marino if (bitmap_bit_p (&true_dependency_cache[insn_luid], elem_luid))
961e4b17023SJohn Marino present_dep_type = REG_DEP_TRUE;
962e4b17023SJohn Marino else if (bitmap_bit_p (&output_dependency_cache[insn_luid], elem_luid))
963e4b17023SJohn Marino present_dep_type = REG_DEP_OUTPUT;
964e4b17023SJohn Marino else if (bitmap_bit_p (&anti_dependency_cache[insn_luid], elem_luid))
965e4b17023SJohn Marino present_dep_type = REG_DEP_ANTI;
966e4b17023SJohn Marino else if (bitmap_bit_p (&control_dependency_cache[insn_luid], elem_luid))
967e4b17023SJohn Marino present_dep_type = REG_DEP_CONTROL;
968e4b17023SJohn Marino else
969e4b17023SJohn Marino /* There is no existing dep so it should be created. */
970e4b17023SJohn Marino return DEP_CREATED;
971e4b17023SJohn Marino
972e4b17023SJohn Marino if ((int) DEP_TYPE (dep) >= (int) present_dep_type)
973e4b17023SJohn Marino /* DEP does not add anything to the existing dependence. */
974e4b17023SJohn Marino return DEP_PRESENT;
975e4b17023SJohn Marino }
976e4b17023SJohn Marino else
977e4b17023SJohn Marino {
978e4b17023SJohn Marino ds_t present_dep_types = 0;
979e4b17023SJohn Marino
980e4b17023SJohn Marino if (bitmap_bit_p (&true_dependency_cache[insn_luid], elem_luid))
981e4b17023SJohn Marino present_dep_types |= DEP_TRUE;
982e4b17023SJohn Marino if (bitmap_bit_p (&output_dependency_cache[insn_luid], elem_luid))
983e4b17023SJohn Marino present_dep_types |= DEP_OUTPUT;
984e4b17023SJohn Marino if (bitmap_bit_p (&anti_dependency_cache[insn_luid], elem_luid))
985e4b17023SJohn Marino present_dep_types |= DEP_ANTI;
986e4b17023SJohn Marino if (bitmap_bit_p (&control_dependency_cache[insn_luid], elem_luid))
987e4b17023SJohn Marino present_dep_types |= DEP_CONTROL;
988e4b17023SJohn Marino
989e4b17023SJohn Marino if (present_dep_types == 0)
990e4b17023SJohn Marino /* There is no existing dep so it should be created. */
991e4b17023SJohn Marino return DEP_CREATED;
992e4b17023SJohn Marino
993e4b17023SJohn Marino if (!(current_sched_info->flags & DO_SPECULATION)
994e4b17023SJohn Marino || !bitmap_bit_p (&spec_dependency_cache[insn_luid], elem_luid))
995e4b17023SJohn Marino {
996e4b17023SJohn Marino if ((present_dep_types | (DEP_STATUS (dep) & DEP_TYPES))
997e4b17023SJohn Marino == present_dep_types)
998e4b17023SJohn Marino /* DEP does not add anything to the existing dependence. */
999e4b17023SJohn Marino return DEP_PRESENT;
1000e4b17023SJohn Marino }
1001e4b17023SJohn Marino else
1002e4b17023SJohn Marino {
1003e4b17023SJohn Marino /* Only true dependencies can be data speculative and
1004e4b17023SJohn Marino only anti dependencies can be control speculative. */
1005e4b17023SJohn Marino gcc_assert ((present_dep_types & (DEP_TRUE | DEP_ANTI))
1006e4b17023SJohn Marino == present_dep_types);
1007e4b17023SJohn Marino
1008e4b17023SJohn Marino /* if (DEP is SPECULATIVE) then
1009e4b17023SJohn Marino ..we should update DEP_STATUS
1010e4b17023SJohn Marino else
1011e4b17023SJohn Marino ..we should reset existing dep to non-speculative. */
1012e4b17023SJohn Marino }
1013e4b17023SJohn Marino }
1014e4b17023SJohn Marino
1015e4b17023SJohn Marino return DEP_CHANGED;
1016e4b17023SJohn Marino }
1017e4b17023SJohn Marino
1018e4b17023SJohn Marino /* Set dependency caches according to DEP. */
1019e4b17023SJohn Marino static void
set_dependency_caches(dep_t dep)1020e4b17023SJohn Marino set_dependency_caches (dep_t dep)
1021e4b17023SJohn Marino {
1022e4b17023SJohn Marino int elem_luid = INSN_LUID (DEP_PRO (dep));
1023e4b17023SJohn Marino int insn_luid = INSN_LUID (DEP_CON (dep));
1024e4b17023SJohn Marino
1025e4b17023SJohn Marino if (!(current_sched_info->flags & USE_DEPS_LIST))
1026e4b17023SJohn Marino {
1027e4b17023SJohn Marino switch (DEP_TYPE (dep))
1028e4b17023SJohn Marino {
1029e4b17023SJohn Marino case REG_DEP_TRUE:
1030e4b17023SJohn Marino bitmap_set_bit (&true_dependency_cache[insn_luid], elem_luid);
1031e4b17023SJohn Marino break;
1032e4b17023SJohn Marino
1033e4b17023SJohn Marino case REG_DEP_OUTPUT:
1034e4b17023SJohn Marino bitmap_set_bit (&output_dependency_cache[insn_luid], elem_luid);
1035e4b17023SJohn Marino break;
1036e4b17023SJohn Marino
1037e4b17023SJohn Marino case REG_DEP_ANTI:
1038e4b17023SJohn Marino bitmap_set_bit (&anti_dependency_cache[insn_luid], elem_luid);
1039e4b17023SJohn Marino break;
1040e4b17023SJohn Marino
1041e4b17023SJohn Marino case REG_DEP_CONTROL:
1042e4b17023SJohn Marino bitmap_set_bit (&control_dependency_cache[insn_luid], elem_luid);
1043e4b17023SJohn Marino break;
1044e4b17023SJohn Marino
1045e4b17023SJohn Marino default:
1046e4b17023SJohn Marino gcc_unreachable ();
1047e4b17023SJohn Marino }
1048e4b17023SJohn Marino }
1049e4b17023SJohn Marino else
1050e4b17023SJohn Marino {
1051e4b17023SJohn Marino ds_t ds = DEP_STATUS (dep);
1052e4b17023SJohn Marino
1053e4b17023SJohn Marino if (ds & DEP_TRUE)
1054e4b17023SJohn Marino bitmap_set_bit (&true_dependency_cache[insn_luid], elem_luid);
1055e4b17023SJohn Marino if (ds & DEP_OUTPUT)
1056e4b17023SJohn Marino bitmap_set_bit (&output_dependency_cache[insn_luid], elem_luid);
1057e4b17023SJohn Marino if (ds & DEP_ANTI)
1058e4b17023SJohn Marino bitmap_set_bit (&anti_dependency_cache[insn_luid], elem_luid);
1059e4b17023SJohn Marino if (ds & DEP_CONTROL)
1060e4b17023SJohn Marino bitmap_set_bit (&control_dependency_cache[insn_luid], elem_luid);
1061e4b17023SJohn Marino
1062e4b17023SJohn Marino if (ds & SPECULATIVE)
1063e4b17023SJohn Marino {
1064e4b17023SJohn Marino gcc_assert (current_sched_info->flags & DO_SPECULATION);
1065e4b17023SJohn Marino bitmap_set_bit (&spec_dependency_cache[insn_luid], elem_luid);
1066e4b17023SJohn Marino }
1067e4b17023SJohn Marino }
1068e4b17023SJohn Marino }
1069e4b17023SJohn Marino
1070e4b17023SJohn Marino /* Type of dependence DEP have changed from OLD_TYPE. Update dependency
1071e4b17023SJohn Marino caches accordingly. */
1072e4b17023SJohn Marino static void
update_dependency_caches(dep_t dep,enum reg_note old_type)1073e4b17023SJohn Marino update_dependency_caches (dep_t dep, enum reg_note old_type)
1074e4b17023SJohn Marino {
1075e4b17023SJohn Marino int elem_luid = INSN_LUID (DEP_PRO (dep));
1076e4b17023SJohn Marino int insn_luid = INSN_LUID (DEP_CON (dep));
1077e4b17023SJohn Marino
1078e4b17023SJohn Marino /* Clear corresponding cache entry because type of the link
1079e4b17023SJohn Marino may have changed. Keep them if we use_deps_list. */
1080e4b17023SJohn Marino if (!(current_sched_info->flags & USE_DEPS_LIST))
1081e4b17023SJohn Marino {
1082e4b17023SJohn Marino switch (old_type)
1083e4b17023SJohn Marino {
1084e4b17023SJohn Marino case REG_DEP_OUTPUT:
1085e4b17023SJohn Marino bitmap_clear_bit (&output_dependency_cache[insn_luid], elem_luid);
1086e4b17023SJohn Marino break;
1087e4b17023SJohn Marino
1088e4b17023SJohn Marino case REG_DEP_ANTI:
1089e4b17023SJohn Marino bitmap_clear_bit (&anti_dependency_cache[insn_luid], elem_luid);
1090e4b17023SJohn Marino break;
1091e4b17023SJohn Marino
1092e4b17023SJohn Marino case REG_DEP_CONTROL:
1093e4b17023SJohn Marino bitmap_clear_bit (&control_dependency_cache[insn_luid], elem_luid);
1094e4b17023SJohn Marino break;
1095e4b17023SJohn Marino
1096e4b17023SJohn Marino default:
1097e4b17023SJohn Marino gcc_unreachable ();
1098e4b17023SJohn Marino }
1099e4b17023SJohn Marino }
1100e4b17023SJohn Marino
1101e4b17023SJohn Marino set_dependency_caches (dep);
1102e4b17023SJohn Marino }
1103e4b17023SJohn Marino
1104e4b17023SJohn Marino /* Convert a dependence pointed to by SD_IT to be non-speculative. */
1105e4b17023SJohn Marino static void
change_spec_dep_to_hard(sd_iterator_def sd_it)1106e4b17023SJohn Marino change_spec_dep_to_hard (sd_iterator_def sd_it)
1107e4b17023SJohn Marino {
1108e4b17023SJohn Marino dep_node_t node = DEP_LINK_NODE (*sd_it.linkp);
1109e4b17023SJohn Marino dep_link_t link = DEP_NODE_BACK (node);
1110e4b17023SJohn Marino dep_t dep = DEP_NODE_DEP (node);
1111e4b17023SJohn Marino rtx elem = DEP_PRO (dep);
1112e4b17023SJohn Marino rtx insn = DEP_CON (dep);
1113e4b17023SJohn Marino
1114e4b17023SJohn Marino move_dep_link (link, INSN_SPEC_BACK_DEPS (insn), INSN_HARD_BACK_DEPS (insn));
1115e4b17023SJohn Marino
1116e4b17023SJohn Marino DEP_STATUS (dep) &= ~SPECULATIVE;
1117e4b17023SJohn Marino
1118e4b17023SJohn Marino if (true_dependency_cache != NULL)
1119e4b17023SJohn Marino /* Clear the cache entry. */
1120e4b17023SJohn Marino bitmap_clear_bit (&spec_dependency_cache[INSN_LUID (insn)],
1121e4b17023SJohn Marino INSN_LUID (elem));
1122e4b17023SJohn Marino }
1123e4b17023SJohn Marino
1124e4b17023SJohn Marino /* Update DEP to incorporate information from NEW_DEP.
1125e4b17023SJohn Marino SD_IT points to DEP in case it should be moved to another list.
1126e4b17023SJohn Marino MEM1 and MEM2, if nonnull, correspond to memory locations in case if
1127e4b17023SJohn Marino data-speculative dependence should be updated. */
1128e4b17023SJohn Marino static enum DEPS_ADJUST_RESULT
update_dep(dep_t dep,dep_t new_dep,sd_iterator_def sd_it ATTRIBUTE_UNUSED,rtx mem1 ATTRIBUTE_UNUSED,rtx mem2 ATTRIBUTE_UNUSED)1129e4b17023SJohn Marino update_dep (dep_t dep, dep_t new_dep,
1130e4b17023SJohn Marino sd_iterator_def sd_it ATTRIBUTE_UNUSED,
1131e4b17023SJohn Marino rtx mem1 ATTRIBUTE_UNUSED,
1132e4b17023SJohn Marino rtx mem2 ATTRIBUTE_UNUSED)
1133e4b17023SJohn Marino {
1134e4b17023SJohn Marino enum DEPS_ADJUST_RESULT res = DEP_PRESENT;
1135e4b17023SJohn Marino enum reg_note old_type = DEP_TYPE (dep);
1136e4b17023SJohn Marino bool was_spec = dep_spec_p (dep);
1137e4b17023SJohn Marino
1138e4b17023SJohn Marino /* If this is a more restrictive type of dependence than the
1139e4b17023SJohn Marino existing one, then change the existing dependence to this
1140e4b17023SJohn Marino type. */
1141e4b17023SJohn Marino if ((int) DEP_TYPE (new_dep) < (int) old_type)
1142e4b17023SJohn Marino {
1143e4b17023SJohn Marino DEP_TYPE (dep) = DEP_TYPE (new_dep);
1144e4b17023SJohn Marino res = DEP_CHANGED;
1145e4b17023SJohn Marino }
1146e4b17023SJohn Marino
1147e4b17023SJohn Marino if (current_sched_info->flags & USE_DEPS_LIST)
1148e4b17023SJohn Marino /* Update DEP_STATUS. */
1149e4b17023SJohn Marino {
1150e4b17023SJohn Marino ds_t dep_status = DEP_STATUS (dep);
1151e4b17023SJohn Marino ds_t ds = DEP_STATUS (new_dep);
1152e4b17023SJohn Marino ds_t new_status = ds | dep_status;
1153e4b17023SJohn Marino
1154e4b17023SJohn Marino if (new_status & SPECULATIVE)
1155e4b17023SJohn Marino {
1156e4b17023SJohn Marino /* Either existing dep or a dep we're adding or both are
1157e4b17023SJohn Marino speculative. */
1158e4b17023SJohn Marino if (!(ds & SPECULATIVE)
1159e4b17023SJohn Marino || !(dep_status & SPECULATIVE))
1160e4b17023SJohn Marino /* The new dep can't be speculative. */
1161e4b17023SJohn Marino new_status &= ~SPECULATIVE;
1162e4b17023SJohn Marino else
1163e4b17023SJohn Marino {
1164e4b17023SJohn Marino /* Both are speculative. Merge probabilities. */
1165e4b17023SJohn Marino if (mem1 != NULL)
1166e4b17023SJohn Marino {
1167e4b17023SJohn Marino dw_t dw;
1168e4b17023SJohn Marino
1169e4b17023SJohn Marino dw = estimate_dep_weak (mem1, mem2);
1170e4b17023SJohn Marino ds = set_dep_weak (ds, BEGIN_DATA, dw);
1171e4b17023SJohn Marino }
1172e4b17023SJohn Marino
1173e4b17023SJohn Marino new_status = ds_merge (dep_status, ds);
1174e4b17023SJohn Marino }
1175e4b17023SJohn Marino }
1176e4b17023SJohn Marino
1177e4b17023SJohn Marino ds = new_status;
1178e4b17023SJohn Marino
1179e4b17023SJohn Marino if (dep_status != ds)
1180e4b17023SJohn Marino {
1181e4b17023SJohn Marino DEP_STATUS (dep) = ds;
1182e4b17023SJohn Marino res = DEP_CHANGED;
1183e4b17023SJohn Marino }
1184e4b17023SJohn Marino }
1185e4b17023SJohn Marino
1186e4b17023SJohn Marino if (was_spec && !dep_spec_p (dep))
1187e4b17023SJohn Marino /* The old dep was speculative, but now it isn't. */
1188e4b17023SJohn Marino change_spec_dep_to_hard (sd_it);
1189e4b17023SJohn Marino
1190e4b17023SJohn Marino if (true_dependency_cache != NULL
1191e4b17023SJohn Marino && res == DEP_CHANGED)
1192e4b17023SJohn Marino update_dependency_caches (dep, old_type);
1193e4b17023SJohn Marino
1194e4b17023SJohn Marino return res;
1195e4b17023SJohn Marino }
1196e4b17023SJohn Marino
1197e4b17023SJohn Marino /* Add or update a dependence described by DEP.
1198e4b17023SJohn Marino MEM1 and MEM2, if non-null, correspond to memory locations in case of
1199e4b17023SJohn Marino data speculation.
1200e4b17023SJohn Marino
1201e4b17023SJohn Marino The function returns a value indicating if an old entry has been changed
1202e4b17023SJohn Marino or a new entry has been added to insn's backward deps or nothing has
1203e4b17023SJohn Marino been updated at all. */
1204e4b17023SJohn Marino static enum DEPS_ADJUST_RESULT
add_or_update_dep_1(dep_t new_dep,bool resolved_p,rtx mem1 ATTRIBUTE_UNUSED,rtx mem2 ATTRIBUTE_UNUSED)1205e4b17023SJohn Marino add_or_update_dep_1 (dep_t new_dep, bool resolved_p,
1206e4b17023SJohn Marino rtx mem1 ATTRIBUTE_UNUSED, rtx mem2 ATTRIBUTE_UNUSED)
1207e4b17023SJohn Marino {
1208e4b17023SJohn Marino bool maybe_present_p = true;
1209e4b17023SJohn Marino bool present_p = false;
1210e4b17023SJohn Marino
1211e4b17023SJohn Marino gcc_assert (INSN_P (DEP_PRO (new_dep)) && INSN_P (DEP_CON (new_dep))
1212e4b17023SJohn Marino && DEP_PRO (new_dep) != DEP_CON (new_dep));
1213e4b17023SJohn Marino
1214e4b17023SJohn Marino #ifdef ENABLE_CHECKING
1215e4b17023SJohn Marino check_dep (new_dep, mem1 != NULL);
1216e4b17023SJohn Marino #endif
1217e4b17023SJohn Marino
1218e4b17023SJohn Marino if (true_dependency_cache != NULL)
1219e4b17023SJohn Marino {
1220e4b17023SJohn Marino switch (ask_dependency_caches (new_dep))
1221e4b17023SJohn Marino {
1222e4b17023SJohn Marino case DEP_PRESENT:
1223e4b17023SJohn Marino return DEP_PRESENT;
1224e4b17023SJohn Marino
1225e4b17023SJohn Marino case DEP_CHANGED:
1226e4b17023SJohn Marino maybe_present_p = true;
1227e4b17023SJohn Marino present_p = true;
1228e4b17023SJohn Marino break;
1229e4b17023SJohn Marino
1230e4b17023SJohn Marino case DEP_CREATED:
1231e4b17023SJohn Marino maybe_present_p = false;
1232e4b17023SJohn Marino present_p = false;
1233e4b17023SJohn Marino break;
1234e4b17023SJohn Marino
1235e4b17023SJohn Marino default:
1236e4b17023SJohn Marino gcc_unreachable ();
1237e4b17023SJohn Marino break;
1238e4b17023SJohn Marino }
1239e4b17023SJohn Marino }
1240e4b17023SJohn Marino
1241e4b17023SJohn Marino /* Check that we don't already have this dependence. */
1242e4b17023SJohn Marino if (maybe_present_p)
1243e4b17023SJohn Marino {
1244e4b17023SJohn Marino dep_t present_dep;
1245e4b17023SJohn Marino sd_iterator_def sd_it;
1246e4b17023SJohn Marino
1247e4b17023SJohn Marino gcc_assert (true_dependency_cache == NULL || present_p);
1248e4b17023SJohn Marino
1249e4b17023SJohn Marino present_dep = sd_find_dep_between_no_cache (DEP_PRO (new_dep),
1250e4b17023SJohn Marino DEP_CON (new_dep),
1251e4b17023SJohn Marino resolved_p, &sd_it);
1252e4b17023SJohn Marino
1253e4b17023SJohn Marino if (present_dep != NULL)
1254e4b17023SJohn Marino /* We found an existing dependency between ELEM and INSN. */
1255e4b17023SJohn Marino return update_dep (present_dep, new_dep, sd_it, mem1, mem2);
1256e4b17023SJohn Marino else
1257e4b17023SJohn Marino /* We didn't find a dep, it shouldn't present in the cache. */
1258e4b17023SJohn Marino gcc_assert (!present_p);
1259e4b17023SJohn Marino }
1260e4b17023SJohn Marino
1261e4b17023SJohn Marino /* Might want to check one level of transitivity to save conses.
1262e4b17023SJohn Marino This check should be done in maybe_add_or_update_dep_1.
1263e4b17023SJohn Marino Since we made it to add_or_update_dep_1, we must create
1264e4b17023SJohn Marino (or update) a link. */
1265e4b17023SJohn Marino
1266e4b17023SJohn Marino if (mem1 != NULL_RTX)
1267e4b17023SJohn Marino {
1268e4b17023SJohn Marino gcc_assert (sched_deps_info->generate_spec_deps);
1269e4b17023SJohn Marino DEP_STATUS (new_dep) = set_dep_weak (DEP_STATUS (new_dep), BEGIN_DATA,
1270e4b17023SJohn Marino estimate_dep_weak (mem1, mem2));
1271e4b17023SJohn Marino }
1272e4b17023SJohn Marino
1273e4b17023SJohn Marino sd_add_dep (new_dep, resolved_p);
1274e4b17023SJohn Marino
1275e4b17023SJohn Marino return DEP_CREATED;
1276e4b17023SJohn Marino }
1277e4b17023SJohn Marino
1278e4b17023SJohn Marino /* Initialize BACK_LIST_PTR with consumer's backward list and
1279e4b17023SJohn Marino FORW_LIST_PTR with producer's forward list. If RESOLVED_P is true
1280e4b17023SJohn Marino initialize with lists that hold resolved deps. */
1281e4b17023SJohn Marino static void
get_back_and_forw_lists(dep_t dep,bool resolved_p,deps_list_t * back_list_ptr,deps_list_t * forw_list_ptr)1282e4b17023SJohn Marino get_back_and_forw_lists (dep_t dep, bool resolved_p,
1283e4b17023SJohn Marino deps_list_t *back_list_ptr,
1284e4b17023SJohn Marino deps_list_t *forw_list_ptr)
1285e4b17023SJohn Marino {
1286e4b17023SJohn Marino rtx con = DEP_CON (dep);
1287e4b17023SJohn Marino
1288e4b17023SJohn Marino if (!resolved_p)
1289e4b17023SJohn Marino {
1290e4b17023SJohn Marino if (dep_spec_p (dep))
1291e4b17023SJohn Marino *back_list_ptr = INSN_SPEC_BACK_DEPS (con);
1292e4b17023SJohn Marino else
1293e4b17023SJohn Marino *back_list_ptr = INSN_HARD_BACK_DEPS (con);
1294e4b17023SJohn Marino
1295e4b17023SJohn Marino *forw_list_ptr = INSN_FORW_DEPS (DEP_PRO (dep));
1296e4b17023SJohn Marino }
1297e4b17023SJohn Marino else
1298e4b17023SJohn Marino {
1299e4b17023SJohn Marino *back_list_ptr = INSN_RESOLVED_BACK_DEPS (con);
1300e4b17023SJohn Marino *forw_list_ptr = INSN_RESOLVED_FORW_DEPS (DEP_PRO (dep));
1301e4b17023SJohn Marino }
1302e4b17023SJohn Marino }
1303e4b17023SJohn Marino
1304e4b17023SJohn Marino /* Add dependence described by DEP.
1305e4b17023SJohn Marino If RESOLVED_P is true treat the dependence as a resolved one. */
1306e4b17023SJohn Marino void
sd_add_dep(dep_t dep,bool resolved_p)1307e4b17023SJohn Marino sd_add_dep (dep_t dep, bool resolved_p)
1308e4b17023SJohn Marino {
1309e4b17023SJohn Marino dep_node_t n = create_dep_node ();
1310e4b17023SJohn Marino deps_list_t con_back_deps;
1311e4b17023SJohn Marino deps_list_t pro_forw_deps;
1312e4b17023SJohn Marino rtx elem = DEP_PRO (dep);
1313e4b17023SJohn Marino rtx insn = DEP_CON (dep);
1314e4b17023SJohn Marino
1315e4b17023SJohn Marino gcc_assert (INSN_P (insn) && INSN_P (elem) && insn != elem);
1316e4b17023SJohn Marino
1317e4b17023SJohn Marino if ((current_sched_info->flags & DO_SPECULATION) == 0
1318e4b17023SJohn Marino || !sched_insn_is_legitimate_for_speculation_p (insn, DEP_STATUS (dep)))
1319e4b17023SJohn Marino DEP_STATUS (dep) &= ~SPECULATIVE;
1320e4b17023SJohn Marino
1321e4b17023SJohn Marino copy_dep (DEP_NODE_DEP (n), dep);
1322e4b17023SJohn Marino
1323e4b17023SJohn Marino get_back_and_forw_lists (dep, resolved_p, &con_back_deps, &pro_forw_deps);
1324e4b17023SJohn Marino
1325e4b17023SJohn Marino add_to_deps_list (DEP_NODE_BACK (n), con_back_deps);
1326e4b17023SJohn Marino
1327e4b17023SJohn Marino #ifdef ENABLE_CHECKING
1328e4b17023SJohn Marino check_dep (dep, false);
1329e4b17023SJohn Marino #endif
1330e4b17023SJohn Marino
1331e4b17023SJohn Marino add_to_deps_list (DEP_NODE_FORW (n), pro_forw_deps);
1332e4b17023SJohn Marino
1333e4b17023SJohn Marino /* If we are adding a dependency to INSN's LOG_LINKs, then note that
1334e4b17023SJohn Marino in the bitmap caches of dependency information. */
1335e4b17023SJohn Marino if (true_dependency_cache != NULL)
1336e4b17023SJohn Marino set_dependency_caches (dep);
1337e4b17023SJohn Marino }
1338e4b17023SJohn Marino
1339e4b17023SJohn Marino /* Add or update backward dependence between INSN and ELEM
1340e4b17023SJohn Marino with given type DEP_TYPE and dep_status DS.
1341e4b17023SJohn Marino This function is a convenience wrapper. */
1342e4b17023SJohn Marino enum DEPS_ADJUST_RESULT
sd_add_or_update_dep(dep_t dep,bool resolved_p)1343e4b17023SJohn Marino sd_add_or_update_dep (dep_t dep, bool resolved_p)
1344e4b17023SJohn Marino {
1345e4b17023SJohn Marino return add_or_update_dep_1 (dep, resolved_p, NULL_RTX, NULL_RTX);
1346e4b17023SJohn Marino }
1347e4b17023SJohn Marino
1348e4b17023SJohn Marino /* Resolved dependence pointed to by SD_IT.
1349e4b17023SJohn Marino SD_IT will advance to the next element. */
1350e4b17023SJohn Marino void
sd_resolve_dep(sd_iterator_def sd_it)1351e4b17023SJohn Marino sd_resolve_dep (sd_iterator_def sd_it)
1352e4b17023SJohn Marino {
1353e4b17023SJohn Marino dep_node_t node = DEP_LINK_NODE (*sd_it.linkp);
1354e4b17023SJohn Marino dep_t dep = DEP_NODE_DEP (node);
1355e4b17023SJohn Marino rtx pro = DEP_PRO (dep);
1356e4b17023SJohn Marino rtx con = DEP_CON (dep);
1357e4b17023SJohn Marino
1358e4b17023SJohn Marino if (dep_spec_p (dep))
1359e4b17023SJohn Marino move_dep_link (DEP_NODE_BACK (node), INSN_SPEC_BACK_DEPS (con),
1360e4b17023SJohn Marino INSN_RESOLVED_BACK_DEPS (con));
1361e4b17023SJohn Marino else
1362e4b17023SJohn Marino move_dep_link (DEP_NODE_BACK (node), INSN_HARD_BACK_DEPS (con),
1363e4b17023SJohn Marino INSN_RESOLVED_BACK_DEPS (con));
1364e4b17023SJohn Marino
1365e4b17023SJohn Marino move_dep_link (DEP_NODE_FORW (node), INSN_FORW_DEPS (pro),
1366e4b17023SJohn Marino INSN_RESOLVED_FORW_DEPS (pro));
1367e4b17023SJohn Marino }
1368e4b17023SJohn Marino
1369e4b17023SJohn Marino /* Perform the inverse operation of sd_resolve_dep. Restore the dependence
1370e4b17023SJohn Marino pointed to by SD_IT to unresolved state. */
1371e4b17023SJohn Marino void
sd_unresolve_dep(sd_iterator_def sd_it)1372e4b17023SJohn Marino sd_unresolve_dep (sd_iterator_def sd_it)
1373e4b17023SJohn Marino {
1374e4b17023SJohn Marino dep_node_t node = DEP_LINK_NODE (*sd_it.linkp);
1375e4b17023SJohn Marino dep_t dep = DEP_NODE_DEP (node);
1376e4b17023SJohn Marino rtx pro = DEP_PRO (dep);
1377e4b17023SJohn Marino rtx con = DEP_CON (dep);
1378e4b17023SJohn Marino
1379e4b17023SJohn Marino if (dep_spec_p (dep))
1380e4b17023SJohn Marino move_dep_link (DEP_NODE_BACK (node), INSN_RESOLVED_BACK_DEPS (con),
1381e4b17023SJohn Marino INSN_SPEC_BACK_DEPS (con));
1382e4b17023SJohn Marino else
1383e4b17023SJohn Marino move_dep_link (DEP_NODE_BACK (node), INSN_RESOLVED_BACK_DEPS (con),
1384e4b17023SJohn Marino INSN_HARD_BACK_DEPS (con));
1385e4b17023SJohn Marino
1386e4b17023SJohn Marino move_dep_link (DEP_NODE_FORW (node), INSN_RESOLVED_FORW_DEPS (pro),
1387e4b17023SJohn Marino INSN_FORW_DEPS (pro));
1388e4b17023SJohn Marino }
1389e4b17023SJohn Marino
1390e4b17023SJohn Marino /* Make TO depend on all the FROM's producers.
1391e4b17023SJohn Marino If RESOLVED_P is true add dependencies to the resolved lists. */
1392e4b17023SJohn Marino void
sd_copy_back_deps(rtx to,rtx from,bool resolved_p)1393e4b17023SJohn Marino sd_copy_back_deps (rtx to, rtx from, bool resolved_p)
1394e4b17023SJohn Marino {
1395e4b17023SJohn Marino sd_list_types_def list_type;
1396e4b17023SJohn Marino sd_iterator_def sd_it;
1397e4b17023SJohn Marino dep_t dep;
1398e4b17023SJohn Marino
1399e4b17023SJohn Marino list_type = resolved_p ? SD_LIST_RES_BACK : SD_LIST_BACK;
1400e4b17023SJohn Marino
1401e4b17023SJohn Marino FOR_EACH_DEP (from, list_type, sd_it, dep)
1402e4b17023SJohn Marino {
1403e4b17023SJohn Marino dep_def _new_dep, *new_dep = &_new_dep;
1404e4b17023SJohn Marino
1405e4b17023SJohn Marino copy_dep (new_dep, dep);
1406e4b17023SJohn Marino DEP_CON (new_dep) = to;
1407e4b17023SJohn Marino sd_add_dep (new_dep, resolved_p);
1408e4b17023SJohn Marino }
1409e4b17023SJohn Marino }
1410e4b17023SJohn Marino
1411e4b17023SJohn Marino /* Remove a dependency referred to by SD_IT.
1412e4b17023SJohn Marino SD_IT will point to the next dependence after removal. */
1413e4b17023SJohn Marino void
sd_delete_dep(sd_iterator_def sd_it)1414e4b17023SJohn Marino sd_delete_dep (sd_iterator_def sd_it)
1415e4b17023SJohn Marino {
1416e4b17023SJohn Marino dep_node_t n = DEP_LINK_NODE (*sd_it.linkp);
1417e4b17023SJohn Marino dep_t dep = DEP_NODE_DEP (n);
1418e4b17023SJohn Marino rtx pro = DEP_PRO (dep);
1419e4b17023SJohn Marino rtx con = DEP_CON (dep);
1420e4b17023SJohn Marino deps_list_t con_back_deps;
1421e4b17023SJohn Marino deps_list_t pro_forw_deps;
1422e4b17023SJohn Marino
1423e4b17023SJohn Marino if (true_dependency_cache != NULL)
1424e4b17023SJohn Marino {
1425e4b17023SJohn Marino int elem_luid = INSN_LUID (pro);
1426e4b17023SJohn Marino int insn_luid = INSN_LUID (con);
1427e4b17023SJohn Marino
1428e4b17023SJohn Marino bitmap_clear_bit (&true_dependency_cache[insn_luid], elem_luid);
1429e4b17023SJohn Marino bitmap_clear_bit (&anti_dependency_cache[insn_luid], elem_luid);
1430e4b17023SJohn Marino bitmap_clear_bit (&control_dependency_cache[insn_luid], elem_luid);
1431e4b17023SJohn Marino bitmap_clear_bit (&output_dependency_cache[insn_luid], elem_luid);
1432e4b17023SJohn Marino
1433e4b17023SJohn Marino if (current_sched_info->flags & DO_SPECULATION)
1434e4b17023SJohn Marino bitmap_clear_bit (&spec_dependency_cache[insn_luid], elem_luid);
1435e4b17023SJohn Marino }
1436e4b17023SJohn Marino
1437e4b17023SJohn Marino get_back_and_forw_lists (dep, sd_it.resolved_p,
1438e4b17023SJohn Marino &con_back_deps, &pro_forw_deps);
1439e4b17023SJohn Marino
1440e4b17023SJohn Marino remove_from_deps_list (DEP_NODE_BACK (n), con_back_deps);
1441e4b17023SJohn Marino remove_from_deps_list (DEP_NODE_FORW (n), pro_forw_deps);
1442e4b17023SJohn Marino
1443e4b17023SJohn Marino delete_dep_node (n);
1444e4b17023SJohn Marino }
1445e4b17023SJohn Marino
1446e4b17023SJohn Marino /* Dump size of the lists. */
1447e4b17023SJohn Marino #define DUMP_LISTS_SIZE (2)
1448e4b17023SJohn Marino
1449e4b17023SJohn Marino /* Dump dependencies of the lists. */
1450e4b17023SJohn Marino #define DUMP_LISTS_DEPS (4)
1451e4b17023SJohn Marino
1452e4b17023SJohn Marino /* Dump all information about the lists. */
1453e4b17023SJohn Marino #define DUMP_LISTS_ALL (DUMP_LISTS_SIZE | DUMP_LISTS_DEPS)
1454e4b17023SJohn Marino
1455e4b17023SJohn Marino /* Dump deps_lists of INSN specified by TYPES to DUMP.
1456e4b17023SJohn Marino FLAGS is a bit mask specifying what information about the lists needs
1457e4b17023SJohn Marino to be printed.
1458e4b17023SJohn Marino If FLAGS has the very first bit set, then dump all information about
1459e4b17023SJohn Marino the lists and propagate this bit into the callee dump functions. */
1460e4b17023SJohn Marino static void
dump_lists(FILE * dump,rtx insn,sd_list_types_def types,int flags)1461e4b17023SJohn Marino dump_lists (FILE *dump, rtx insn, sd_list_types_def types, int flags)
1462e4b17023SJohn Marino {
1463e4b17023SJohn Marino sd_iterator_def sd_it;
1464e4b17023SJohn Marino dep_t dep;
1465e4b17023SJohn Marino int all;
1466e4b17023SJohn Marino
1467e4b17023SJohn Marino all = (flags & 1);
1468e4b17023SJohn Marino
1469e4b17023SJohn Marino if (all)
1470e4b17023SJohn Marino flags |= DUMP_LISTS_ALL;
1471e4b17023SJohn Marino
1472e4b17023SJohn Marino fprintf (dump, "[");
1473e4b17023SJohn Marino
1474e4b17023SJohn Marino if (flags & DUMP_LISTS_SIZE)
1475e4b17023SJohn Marino fprintf (dump, "%d; ", sd_lists_size (insn, types));
1476e4b17023SJohn Marino
1477e4b17023SJohn Marino if (flags & DUMP_LISTS_DEPS)
1478e4b17023SJohn Marino {
1479e4b17023SJohn Marino FOR_EACH_DEP (insn, types, sd_it, dep)
1480e4b17023SJohn Marino {
1481e4b17023SJohn Marino dump_dep (dump, dep, dump_dep_flags | all);
1482e4b17023SJohn Marino fprintf (dump, " ");
1483e4b17023SJohn Marino }
1484e4b17023SJohn Marino }
1485e4b17023SJohn Marino }
1486e4b17023SJohn Marino
1487e4b17023SJohn Marino /* Dump all information about deps_lists of INSN specified by TYPES
1488e4b17023SJohn Marino to STDERR. */
1489e4b17023SJohn Marino void
sd_debug_lists(rtx insn,sd_list_types_def types)1490e4b17023SJohn Marino sd_debug_lists (rtx insn, sd_list_types_def types)
1491e4b17023SJohn Marino {
1492e4b17023SJohn Marino dump_lists (stderr, insn, types, 1);
1493e4b17023SJohn Marino fprintf (stderr, "\n");
1494e4b17023SJohn Marino }
1495e4b17023SJohn Marino
1496e4b17023SJohn Marino /* A wrapper around add_dependence_1, to add a dependence of CON on
1497e4b17023SJohn Marino PRO, with type DEP_TYPE. This function implements special handling
1498e4b17023SJohn Marino for REG_DEP_CONTROL dependencies. For these, we optionally promote
1499e4b17023SJohn Marino the type to REG_DEP_ANTI if we can determine that predication is
1500e4b17023SJohn Marino impossible; otherwise we add additional true dependencies on the
1501e4b17023SJohn Marino INSN_COND_DEPS list of the jump (which PRO must be). */
1502e4b17023SJohn Marino void
add_dependence(rtx con,rtx pro,enum reg_note dep_type)1503e4b17023SJohn Marino add_dependence (rtx con, rtx pro, enum reg_note dep_type)
1504e4b17023SJohn Marino {
1505e4b17023SJohn Marino if (dep_type == REG_DEP_CONTROL
1506e4b17023SJohn Marino && !(current_sched_info->flags & DO_PREDICATION))
1507e4b17023SJohn Marino dep_type = REG_DEP_ANTI;
1508e4b17023SJohn Marino
1509e4b17023SJohn Marino /* A REG_DEP_CONTROL dependence may be eliminated through predication,
1510e4b17023SJohn Marino so we must also make the insn dependent on the setter of the
1511e4b17023SJohn Marino condition. */
1512e4b17023SJohn Marino if (dep_type == REG_DEP_CONTROL)
1513e4b17023SJohn Marino {
1514e4b17023SJohn Marino rtx real_pro = pro;
1515e4b17023SJohn Marino rtx other = real_insn_for_shadow (real_pro);
1516e4b17023SJohn Marino rtx cond;
1517e4b17023SJohn Marino
1518e4b17023SJohn Marino if (other != NULL_RTX)
1519e4b17023SJohn Marino real_pro = other;
1520e4b17023SJohn Marino cond = sched_get_reverse_condition_uncached (real_pro);
1521e4b17023SJohn Marino /* Verify that the insn does not use a different value in
1522e4b17023SJohn Marino the condition register than the one that was present at
1523e4b17023SJohn Marino the jump. */
1524e4b17023SJohn Marino if (cond == NULL_RTX)
1525e4b17023SJohn Marino dep_type = REG_DEP_ANTI;
1526e4b17023SJohn Marino else if (INSN_CACHED_COND (real_pro) == const_true_rtx)
1527e4b17023SJohn Marino {
1528e4b17023SJohn Marino HARD_REG_SET uses;
1529e4b17023SJohn Marino CLEAR_HARD_REG_SET (uses);
1530e4b17023SJohn Marino note_uses (&PATTERN (con), record_hard_reg_uses, &uses);
1531e4b17023SJohn Marino if (TEST_HARD_REG_BIT (uses, REGNO (XEXP (cond, 0))))
1532e4b17023SJohn Marino dep_type = REG_DEP_ANTI;
1533e4b17023SJohn Marino }
1534e4b17023SJohn Marino if (dep_type == REG_DEP_CONTROL)
1535e4b17023SJohn Marino {
1536e4b17023SJohn Marino if (sched_verbose >= 5)
1537e4b17023SJohn Marino fprintf (sched_dump, "making DEP_CONTROL for %d\n",
1538e4b17023SJohn Marino INSN_UID (real_pro));
1539e4b17023SJohn Marino add_dependence_list (con, INSN_COND_DEPS (real_pro), 0,
1540e4b17023SJohn Marino REG_DEP_TRUE);
1541e4b17023SJohn Marino }
1542e4b17023SJohn Marino }
1543e4b17023SJohn Marino
1544e4b17023SJohn Marino add_dependence_1 (con, pro, dep_type);
1545e4b17023SJohn Marino }
1546e4b17023SJohn Marino
1547e4b17023SJohn Marino /* A convenience wrapper to operate on an entire list. */
1548e4b17023SJohn Marino
1549e4b17023SJohn Marino static void
add_dependence_list(rtx insn,rtx list,int uncond,enum reg_note dep_type)1550e4b17023SJohn Marino add_dependence_list (rtx insn, rtx list, int uncond, enum reg_note dep_type)
1551e4b17023SJohn Marino {
1552e4b17023SJohn Marino for (; list; list = XEXP (list, 1))
1553e4b17023SJohn Marino {
1554e4b17023SJohn Marino if (uncond || ! sched_insns_conditions_mutex_p (insn, XEXP (list, 0)))
1555e4b17023SJohn Marino add_dependence (insn, XEXP (list, 0), dep_type);
1556e4b17023SJohn Marino }
1557e4b17023SJohn Marino }
1558e4b17023SJohn Marino
1559e4b17023SJohn Marino /* Similar, but free *LISTP at the same time, when the context
1560e4b17023SJohn Marino is not readonly. */
1561e4b17023SJohn Marino
1562e4b17023SJohn Marino static void
add_dependence_list_and_free(struct deps_desc * deps,rtx insn,rtx * listp,int uncond,enum reg_note dep_type)1563e4b17023SJohn Marino add_dependence_list_and_free (struct deps_desc *deps, rtx insn, rtx *listp,
1564e4b17023SJohn Marino int uncond, enum reg_note dep_type)
1565e4b17023SJohn Marino {
1566*95d28233SJohn Marino add_dependence_list (insn, *listp, uncond, dep_type);
1567e4b17023SJohn Marino
1568e4b17023SJohn Marino /* We don't want to short-circuit dependencies involving debug
1569e4b17023SJohn Marino insns, because they may cause actual dependencies to be
1570e4b17023SJohn Marino disregarded. */
1571e4b17023SJohn Marino if (deps->readonly || DEBUG_INSN_P (insn))
1572e4b17023SJohn Marino return;
1573e4b17023SJohn Marino
1574*95d28233SJohn Marino free_INSN_LIST_list (listp);
1575e4b17023SJohn Marino }
1576e4b17023SJohn Marino
1577e4b17023SJohn Marino /* Remove all occurences of INSN from LIST. Return the number of
1578e4b17023SJohn Marino occurences removed. */
1579e4b17023SJohn Marino
1580e4b17023SJohn Marino static int
remove_from_dependence_list(rtx insn,rtx * listp)1581e4b17023SJohn Marino remove_from_dependence_list (rtx insn, rtx* listp)
1582e4b17023SJohn Marino {
1583e4b17023SJohn Marino int removed = 0;
1584e4b17023SJohn Marino
1585e4b17023SJohn Marino while (*listp)
1586e4b17023SJohn Marino {
1587e4b17023SJohn Marino if (XEXP (*listp, 0) == insn)
1588e4b17023SJohn Marino {
1589e4b17023SJohn Marino remove_free_INSN_LIST_node (listp);
1590e4b17023SJohn Marino removed++;
1591e4b17023SJohn Marino continue;
1592e4b17023SJohn Marino }
1593e4b17023SJohn Marino
1594e4b17023SJohn Marino listp = &XEXP (*listp, 1);
1595e4b17023SJohn Marino }
1596e4b17023SJohn Marino
1597e4b17023SJohn Marino return removed;
1598e4b17023SJohn Marino }
1599e4b17023SJohn Marino
1600e4b17023SJohn Marino /* Same as above, but process two lists at once. */
1601e4b17023SJohn Marino static int
remove_from_both_dependence_lists(rtx insn,rtx * listp,rtx * exprp)1602e4b17023SJohn Marino remove_from_both_dependence_lists (rtx insn, rtx *listp, rtx *exprp)
1603e4b17023SJohn Marino {
1604e4b17023SJohn Marino int removed = 0;
1605e4b17023SJohn Marino
1606e4b17023SJohn Marino while (*listp)
1607e4b17023SJohn Marino {
1608e4b17023SJohn Marino if (XEXP (*listp, 0) == insn)
1609e4b17023SJohn Marino {
1610e4b17023SJohn Marino remove_free_INSN_LIST_node (listp);
1611e4b17023SJohn Marino remove_free_EXPR_LIST_node (exprp);
1612e4b17023SJohn Marino removed++;
1613e4b17023SJohn Marino continue;
1614e4b17023SJohn Marino }
1615e4b17023SJohn Marino
1616e4b17023SJohn Marino listp = &XEXP (*listp, 1);
1617e4b17023SJohn Marino exprp = &XEXP (*exprp, 1);
1618e4b17023SJohn Marino }
1619e4b17023SJohn Marino
1620e4b17023SJohn Marino return removed;
1621e4b17023SJohn Marino }
1622e4b17023SJohn Marino
1623e4b17023SJohn Marino /* Clear all dependencies for an insn. */
1624e4b17023SJohn Marino static void
delete_all_dependences(rtx insn)1625e4b17023SJohn Marino delete_all_dependences (rtx insn)
1626e4b17023SJohn Marino {
1627e4b17023SJohn Marino sd_iterator_def sd_it;
1628e4b17023SJohn Marino dep_t dep;
1629e4b17023SJohn Marino
1630e4b17023SJohn Marino /* The below cycle can be optimized to clear the caches and back_deps
1631e4b17023SJohn Marino in one call but that would provoke duplication of code from
1632e4b17023SJohn Marino delete_dep (). */
1633e4b17023SJohn Marino
1634e4b17023SJohn Marino for (sd_it = sd_iterator_start (insn, SD_LIST_BACK);
1635e4b17023SJohn Marino sd_iterator_cond (&sd_it, &dep);)
1636e4b17023SJohn Marino sd_delete_dep (sd_it);
1637e4b17023SJohn Marino }
1638e4b17023SJohn Marino
1639e4b17023SJohn Marino /* All insns in a scheduling group except the first should only have
1640e4b17023SJohn Marino dependencies on the previous insn in the group. So we find the
1641e4b17023SJohn Marino first instruction in the scheduling group by walking the dependence
1642e4b17023SJohn Marino chains backwards. Then we add the dependencies for the group to
1643e4b17023SJohn Marino the previous nonnote insn. */
1644e4b17023SJohn Marino
1645e4b17023SJohn Marino static void
fixup_sched_groups(rtx insn)1646e4b17023SJohn Marino fixup_sched_groups (rtx insn)
1647e4b17023SJohn Marino {
1648e4b17023SJohn Marino sd_iterator_def sd_it;
1649e4b17023SJohn Marino dep_t dep;
1650e4b17023SJohn Marino rtx prev_nonnote;
1651e4b17023SJohn Marino
1652e4b17023SJohn Marino FOR_EACH_DEP (insn, SD_LIST_BACK, sd_it, dep)
1653e4b17023SJohn Marino {
1654e4b17023SJohn Marino rtx i = insn;
1655e4b17023SJohn Marino rtx pro = DEP_PRO (dep);
1656e4b17023SJohn Marino
1657e4b17023SJohn Marino do
1658e4b17023SJohn Marino {
1659e4b17023SJohn Marino i = prev_nonnote_insn (i);
1660e4b17023SJohn Marino
1661e4b17023SJohn Marino if (pro == i)
1662e4b17023SJohn Marino goto next_link;
1663e4b17023SJohn Marino } while (SCHED_GROUP_P (i) || DEBUG_INSN_P (i));
1664e4b17023SJohn Marino
1665e4b17023SJohn Marino if (! sched_insns_conditions_mutex_p (i, pro))
1666e4b17023SJohn Marino add_dependence (i, pro, DEP_TYPE (dep));
1667e4b17023SJohn Marino next_link:;
1668e4b17023SJohn Marino }
1669e4b17023SJohn Marino
1670e4b17023SJohn Marino delete_all_dependences (insn);
1671e4b17023SJohn Marino
1672e4b17023SJohn Marino prev_nonnote = prev_nonnote_nondebug_insn (insn);
1673e4b17023SJohn Marino if (BLOCK_FOR_INSN (insn) == BLOCK_FOR_INSN (prev_nonnote)
1674e4b17023SJohn Marino && ! sched_insns_conditions_mutex_p (insn, prev_nonnote))
1675e4b17023SJohn Marino add_dependence (insn, prev_nonnote, REG_DEP_ANTI);
1676e4b17023SJohn Marino }
1677e4b17023SJohn Marino
1678e4b17023SJohn Marino /* Process an insn's memory dependencies. There are four kinds of
1679e4b17023SJohn Marino dependencies:
1680e4b17023SJohn Marino
1681e4b17023SJohn Marino (0) read dependence: read follows read
1682e4b17023SJohn Marino (1) true dependence: read follows write
1683e4b17023SJohn Marino (2) output dependence: write follows write
1684e4b17023SJohn Marino (3) anti dependence: write follows read
1685e4b17023SJohn Marino
1686e4b17023SJohn Marino We are careful to build only dependencies which actually exist, and
1687e4b17023SJohn Marino use transitivity to avoid building too many links. */
1688e4b17023SJohn Marino
1689e4b17023SJohn Marino /* Add an INSN and MEM reference pair to a pending INSN_LIST and MEM_LIST.
1690e4b17023SJohn Marino The MEM is a memory reference contained within INSN, which we are saving
1691e4b17023SJohn Marino so that we can do memory aliasing on it. */
1692e4b17023SJohn Marino
1693e4b17023SJohn Marino static void
add_insn_mem_dependence(struct deps_desc * deps,bool read_p,rtx insn,rtx mem)1694e4b17023SJohn Marino add_insn_mem_dependence (struct deps_desc *deps, bool read_p,
1695e4b17023SJohn Marino rtx insn, rtx mem)
1696e4b17023SJohn Marino {
1697e4b17023SJohn Marino rtx *insn_list;
1698e4b17023SJohn Marino rtx *mem_list;
1699e4b17023SJohn Marino rtx link;
1700e4b17023SJohn Marino
1701e4b17023SJohn Marino gcc_assert (!deps->readonly);
1702e4b17023SJohn Marino if (read_p)
1703e4b17023SJohn Marino {
1704e4b17023SJohn Marino insn_list = &deps->pending_read_insns;
1705e4b17023SJohn Marino mem_list = &deps->pending_read_mems;
1706e4b17023SJohn Marino if (!DEBUG_INSN_P (insn))
1707e4b17023SJohn Marino deps->pending_read_list_length++;
1708e4b17023SJohn Marino }
1709e4b17023SJohn Marino else
1710e4b17023SJohn Marino {
1711e4b17023SJohn Marino insn_list = &deps->pending_write_insns;
1712e4b17023SJohn Marino mem_list = &deps->pending_write_mems;
1713e4b17023SJohn Marino deps->pending_write_list_length++;
1714e4b17023SJohn Marino }
1715e4b17023SJohn Marino
1716e4b17023SJohn Marino link = alloc_INSN_LIST (insn, *insn_list);
1717e4b17023SJohn Marino *insn_list = link;
1718e4b17023SJohn Marino
1719e4b17023SJohn Marino if (sched_deps_info->use_cselib)
1720e4b17023SJohn Marino {
1721e4b17023SJohn Marino mem = shallow_copy_rtx (mem);
1722e4b17023SJohn Marino XEXP (mem, 0) = cselib_subst_to_values_from_insn (XEXP (mem, 0),
1723e4b17023SJohn Marino GET_MODE (mem), insn);
1724e4b17023SJohn Marino }
1725e4b17023SJohn Marino link = alloc_EXPR_LIST (VOIDmode, canon_rtx (mem), *mem_list);
1726e4b17023SJohn Marino *mem_list = link;
1727e4b17023SJohn Marino }
1728e4b17023SJohn Marino
1729e4b17023SJohn Marino /* Make a dependency between every memory reference on the pending lists
1730e4b17023SJohn Marino and INSN, thus flushing the pending lists. FOR_READ is true if emitting
1731e4b17023SJohn Marino dependencies for a read operation, similarly with FOR_WRITE. */
1732e4b17023SJohn Marino
1733e4b17023SJohn Marino static void
flush_pending_lists(struct deps_desc * deps,rtx insn,int for_read,int for_write)1734e4b17023SJohn Marino flush_pending_lists (struct deps_desc *deps, rtx insn, int for_read,
1735e4b17023SJohn Marino int for_write)
1736e4b17023SJohn Marino {
1737e4b17023SJohn Marino if (for_write)
1738e4b17023SJohn Marino {
1739e4b17023SJohn Marino add_dependence_list_and_free (deps, insn, &deps->pending_read_insns,
1740e4b17023SJohn Marino 1, REG_DEP_ANTI);
1741e4b17023SJohn Marino if (!deps->readonly)
1742e4b17023SJohn Marino {
1743e4b17023SJohn Marino free_EXPR_LIST_list (&deps->pending_read_mems);
1744e4b17023SJohn Marino deps->pending_read_list_length = 0;
1745e4b17023SJohn Marino }
1746e4b17023SJohn Marino }
1747e4b17023SJohn Marino
1748e4b17023SJohn Marino add_dependence_list_and_free (deps, insn, &deps->pending_write_insns, 1,
1749e4b17023SJohn Marino for_read ? REG_DEP_ANTI : REG_DEP_OUTPUT);
1750e4b17023SJohn Marino
1751e4b17023SJohn Marino add_dependence_list_and_free (deps, insn,
1752e4b17023SJohn Marino &deps->last_pending_memory_flush, 1,
1753e4b17023SJohn Marino for_read ? REG_DEP_ANTI : REG_DEP_OUTPUT);
1754e4b17023SJohn Marino
1755e4b17023SJohn Marino add_dependence_list_and_free (deps, insn, &deps->pending_jump_insns, 1,
1756e4b17023SJohn Marino REG_DEP_ANTI);
1757e4b17023SJohn Marino
1758*95d28233SJohn Marino if (DEBUG_INSN_P (insn))
1759*95d28233SJohn Marino {
1760*95d28233SJohn Marino if (for_write)
1761*95d28233SJohn Marino free_INSN_LIST_list (&deps->pending_read_insns);
1762*95d28233SJohn Marino free_INSN_LIST_list (&deps->pending_write_insns);
1763*95d28233SJohn Marino free_INSN_LIST_list (&deps->last_pending_memory_flush);
1764*95d28233SJohn Marino free_INSN_LIST_list (&deps->pending_jump_insns);
1765*95d28233SJohn Marino }
1766*95d28233SJohn Marino
1767e4b17023SJohn Marino if (!deps->readonly)
1768e4b17023SJohn Marino {
1769e4b17023SJohn Marino free_EXPR_LIST_list (&deps->pending_write_mems);
1770e4b17023SJohn Marino deps->pending_write_list_length = 0;
1771e4b17023SJohn Marino
1772e4b17023SJohn Marino deps->last_pending_memory_flush = alloc_INSN_LIST (insn, NULL_RTX);
1773e4b17023SJohn Marino deps->pending_flush_length = 1;
1774e4b17023SJohn Marino }
1775e4b17023SJohn Marino }
1776e4b17023SJohn Marino
1777e4b17023SJohn Marino /* Instruction which dependencies we are analyzing. */
1778e4b17023SJohn Marino static rtx cur_insn = NULL_RTX;
1779e4b17023SJohn Marino
1780e4b17023SJohn Marino /* Implement hooks for haifa scheduler. */
1781e4b17023SJohn Marino
1782e4b17023SJohn Marino static void
haifa_start_insn(rtx insn)1783e4b17023SJohn Marino haifa_start_insn (rtx insn)
1784e4b17023SJohn Marino {
1785e4b17023SJohn Marino gcc_assert (insn && !cur_insn);
1786e4b17023SJohn Marino
1787e4b17023SJohn Marino cur_insn = insn;
1788e4b17023SJohn Marino }
1789e4b17023SJohn Marino
1790e4b17023SJohn Marino static void
haifa_finish_insn(void)1791e4b17023SJohn Marino haifa_finish_insn (void)
1792e4b17023SJohn Marino {
1793e4b17023SJohn Marino cur_insn = NULL;
1794e4b17023SJohn Marino }
1795e4b17023SJohn Marino
1796e4b17023SJohn Marino void
haifa_note_reg_set(int regno)1797e4b17023SJohn Marino haifa_note_reg_set (int regno)
1798e4b17023SJohn Marino {
1799e4b17023SJohn Marino SET_REGNO_REG_SET (reg_pending_sets, regno);
1800e4b17023SJohn Marino }
1801e4b17023SJohn Marino
1802e4b17023SJohn Marino void
haifa_note_reg_clobber(int regno)1803e4b17023SJohn Marino haifa_note_reg_clobber (int regno)
1804e4b17023SJohn Marino {
1805e4b17023SJohn Marino SET_REGNO_REG_SET (reg_pending_clobbers, regno);
1806e4b17023SJohn Marino }
1807e4b17023SJohn Marino
1808e4b17023SJohn Marino void
haifa_note_reg_use(int regno)1809e4b17023SJohn Marino haifa_note_reg_use (int regno)
1810e4b17023SJohn Marino {
1811e4b17023SJohn Marino SET_REGNO_REG_SET (reg_pending_uses, regno);
1812e4b17023SJohn Marino }
1813e4b17023SJohn Marino
1814e4b17023SJohn Marino static void
haifa_note_mem_dep(rtx mem,rtx pending_mem,rtx pending_insn,ds_t ds)1815e4b17023SJohn Marino haifa_note_mem_dep (rtx mem, rtx pending_mem, rtx pending_insn, ds_t ds)
1816e4b17023SJohn Marino {
1817e4b17023SJohn Marino if (!(ds & SPECULATIVE))
1818e4b17023SJohn Marino {
1819e4b17023SJohn Marino mem = NULL_RTX;
1820e4b17023SJohn Marino pending_mem = NULL_RTX;
1821e4b17023SJohn Marino }
1822e4b17023SJohn Marino else
1823e4b17023SJohn Marino gcc_assert (ds & BEGIN_DATA);
1824e4b17023SJohn Marino
1825e4b17023SJohn Marino {
1826e4b17023SJohn Marino dep_def _dep, *dep = &_dep;
1827e4b17023SJohn Marino
1828e4b17023SJohn Marino init_dep_1 (dep, pending_insn, cur_insn, ds_to_dt (ds),
1829e4b17023SJohn Marino current_sched_info->flags & USE_DEPS_LIST ? ds : 0);
1830e4b17023SJohn Marino maybe_add_or_update_dep_1 (dep, false, pending_mem, mem);
1831e4b17023SJohn Marino }
1832e4b17023SJohn Marino
1833e4b17023SJohn Marino }
1834e4b17023SJohn Marino
1835e4b17023SJohn Marino static void
haifa_note_dep(rtx elem,ds_t ds)1836e4b17023SJohn Marino haifa_note_dep (rtx elem, ds_t ds)
1837e4b17023SJohn Marino {
1838e4b17023SJohn Marino dep_def _dep;
1839e4b17023SJohn Marino dep_t dep = &_dep;
1840e4b17023SJohn Marino
1841e4b17023SJohn Marino init_dep (dep, elem, cur_insn, ds_to_dt (ds));
1842e4b17023SJohn Marino maybe_add_or_update_dep_1 (dep, false, NULL_RTX, NULL_RTX);
1843e4b17023SJohn Marino }
1844e4b17023SJohn Marino
1845e4b17023SJohn Marino static void
note_reg_use(int r)1846e4b17023SJohn Marino note_reg_use (int r)
1847e4b17023SJohn Marino {
1848e4b17023SJohn Marino if (sched_deps_info->note_reg_use)
1849e4b17023SJohn Marino sched_deps_info->note_reg_use (r);
1850e4b17023SJohn Marino }
1851e4b17023SJohn Marino
1852e4b17023SJohn Marino static void
note_reg_set(int r)1853e4b17023SJohn Marino note_reg_set (int r)
1854e4b17023SJohn Marino {
1855e4b17023SJohn Marino if (sched_deps_info->note_reg_set)
1856e4b17023SJohn Marino sched_deps_info->note_reg_set (r);
1857e4b17023SJohn Marino }
1858e4b17023SJohn Marino
1859e4b17023SJohn Marino static void
note_reg_clobber(int r)1860e4b17023SJohn Marino note_reg_clobber (int r)
1861e4b17023SJohn Marino {
1862e4b17023SJohn Marino if (sched_deps_info->note_reg_clobber)
1863e4b17023SJohn Marino sched_deps_info->note_reg_clobber (r);
1864e4b17023SJohn Marino }
1865e4b17023SJohn Marino
1866e4b17023SJohn Marino static void
note_mem_dep(rtx m1,rtx m2,rtx e,ds_t ds)1867e4b17023SJohn Marino note_mem_dep (rtx m1, rtx m2, rtx e, ds_t ds)
1868e4b17023SJohn Marino {
1869e4b17023SJohn Marino if (sched_deps_info->note_mem_dep)
1870e4b17023SJohn Marino sched_deps_info->note_mem_dep (m1, m2, e, ds);
1871e4b17023SJohn Marino }
1872e4b17023SJohn Marino
1873e4b17023SJohn Marino static void
note_dep(rtx e,ds_t ds)1874e4b17023SJohn Marino note_dep (rtx e, ds_t ds)
1875e4b17023SJohn Marino {
1876e4b17023SJohn Marino if (sched_deps_info->note_dep)
1877e4b17023SJohn Marino sched_deps_info->note_dep (e, ds);
1878e4b17023SJohn Marino }
1879e4b17023SJohn Marino
1880e4b17023SJohn Marino /* Return corresponding to DS reg_note. */
1881e4b17023SJohn Marino enum reg_note
ds_to_dt(ds_t ds)1882e4b17023SJohn Marino ds_to_dt (ds_t ds)
1883e4b17023SJohn Marino {
1884e4b17023SJohn Marino if (ds & DEP_TRUE)
1885e4b17023SJohn Marino return REG_DEP_TRUE;
1886e4b17023SJohn Marino else if (ds & DEP_OUTPUT)
1887e4b17023SJohn Marino return REG_DEP_OUTPUT;
1888e4b17023SJohn Marino else if (ds & DEP_ANTI)
1889e4b17023SJohn Marino return REG_DEP_ANTI;
1890e4b17023SJohn Marino else
1891e4b17023SJohn Marino {
1892e4b17023SJohn Marino gcc_assert (ds & DEP_CONTROL);
1893e4b17023SJohn Marino return REG_DEP_CONTROL;
1894e4b17023SJohn Marino }
1895e4b17023SJohn Marino }
1896e4b17023SJohn Marino
1897e4b17023SJohn Marino
1898e4b17023SJohn Marino
1899e4b17023SJohn Marino /* Functions for computation of info needed for register pressure
1900e4b17023SJohn Marino sensitive insn scheduling. */
1901e4b17023SJohn Marino
1902e4b17023SJohn Marino
1903e4b17023SJohn Marino /* Allocate and return reg_use_data structure for REGNO and INSN. */
1904e4b17023SJohn Marino static struct reg_use_data *
create_insn_reg_use(int regno,rtx insn)1905e4b17023SJohn Marino create_insn_reg_use (int regno, rtx insn)
1906e4b17023SJohn Marino {
1907e4b17023SJohn Marino struct reg_use_data *use;
1908e4b17023SJohn Marino
1909e4b17023SJohn Marino use = (struct reg_use_data *) xmalloc (sizeof (struct reg_use_data));
1910e4b17023SJohn Marino use->regno = regno;
1911e4b17023SJohn Marino use->insn = insn;
1912e4b17023SJohn Marino use->next_insn_use = INSN_REG_USE_LIST (insn);
1913e4b17023SJohn Marino INSN_REG_USE_LIST (insn) = use;
1914e4b17023SJohn Marino return use;
1915e4b17023SJohn Marino }
1916e4b17023SJohn Marino
1917e4b17023SJohn Marino /* Allocate and return reg_set_data structure for REGNO and INSN. */
1918e4b17023SJohn Marino static struct reg_set_data *
create_insn_reg_set(int regno,rtx insn)1919e4b17023SJohn Marino create_insn_reg_set (int regno, rtx insn)
1920e4b17023SJohn Marino {
1921e4b17023SJohn Marino struct reg_set_data *set;
1922e4b17023SJohn Marino
1923e4b17023SJohn Marino set = (struct reg_set_data *) xmalloc (sizeof (struct reg_set_data));
1924e4b17023SJohn Marino set->regno = regno;
1925e4b17023SJohn Marino set->insn = insn;
1926e4b17023SJohn Marino set->next_insn_set = INSN_REG_SET_LIST (insn);
1927e4b17023SJohn Marino INSN_REG_SET_LIST (insn) = set;
1928e4b17023SJohn Marino return set;
1929e4b17023SJohn Marino }
1930e4b17023SJohn Marino
1931e4b17023SJohn Marino /* Set up insn register uses for INSN and dependency context DEPS. */
1932e4b17023SJohn Marino static void
setup_insn_reg_uses(struct deps_desc * deps,rtx insn)1933e4b17023SJohn Marino setup_insn_reg_uses (struct deps_desc *deps, rtx insn)
1934e4b17023SJohn Marino {
1935e4b17023SJohn Marino unsigned i;
1936e4b17023SJohn Marino reg_set_iterator rsi;
1937e4b17023SJohn Marino rtx list;
1938e4b17023SJohn Marino struct reg_use_data *use, *use2, *next;
1939e4b17023SJohn Marino struct deps_reg *reg_last;
1940e4b17023SJohn Marino
1941e4b17023SJohn Marino EXECUTE_IF_SET_IN_REG_SET (reg_pending_uses, 0, i, rsi)
1942e4b17023SJohn Marino {
1943e4b17023SJohn Marino if (i < FIRST_PSEUDO_REGISTER
1944e4b17023SJohn Marino && TEST_HARD_REG_BIT (ira_no_alloc_regs, i))
1945e4b17023SJohn Marino continue;
1946e4b17023SJohn Marino
1947e4b17023SJohn Marino if (find_regno_note (insn, REG_DEAD, i) == NULL_RTX
1948e4b17023SJohn Marino && ! REGNO_REG_SET_P (reg_pending_sets, i)
1949e4b17023SJohn Marino && ! REGNO_REG_SET_P (reg_pending_clobbers, i))
1950e4b17023SJohn Marino /* Ignore use which is not dying. */
1951e4b17023SJohn Marino continue;
1952e4b17023SJohn Marino
1953e4b17023SJohn Marino use = create_insn_reg_use (i, insn);
1954e4b17023SJohn Marino use->next_regno_use = use;
1955e4b17023SJohn Marino reg_last = &deps->reg_last[i];
1956e4b17023SJohn Marino
1957e4b17023SJohn Marino /* Create the cycle list of uses. */
1958e4b17023SJohn Marino for (list = reg_last->uses; list; list = XEXP (list, 1))
1959e4b17023SJohn Marino {
1960e4b17023SJohn Marino use2 = create_insn_reg_use (i, XEXP (list, 0));
1961e4b17023SJohn Marino next = use->next_regno_use;
1962e4b17023SJohn Marino use->next_regno_use = use2;
1963e4b17023SJohn Marino use2->next_regno_use = next;
1964e4b17023SJohn Marino }
1965e4b17023SJohn Marino }
1966e4b17023SJohn Marino }
1967e4b17023SJohn Marino
1968e4b17023SJohn Marino /* Register pressure info for the currently processed insn. */
1969e4b17023SJohn Marino static struct reg_pressure_data reg_pressure_info[N_REG_CLASSES];
1970e4b17023SJohn Marino
1971e4b17023SJohn Marino /* Return TRUE if INSN has the use structure for REGNO. */
1972e4b17023SJohn Marino static bool
insn_use_p(rtx insn,int regno)1973e4b17023SJohn Marino insn_use_p (rtx insn, int regno)
1974e4b17023SJohn Marino {
1975e4b17023SJohn Marino struct reg_use_data *use;
1976e4b17023SJohn Marino
1977e4b17023SJohn Marino for (use = INSN_REG_USE_LIST (insn); use != NULL; use = use->next_insn_use)
1978e4b17023SJohn Marino if (use->regno == regno)
1979e4b17023SJohn Marino return true;
1980e4b17023SJohn Marino return false;
1981e4b17023SJohn Marino }
1982e4b17023SJohn Marino
1983e4b17023SJohn Marino /* Update the register pressure info after birth of pseudo register REGNO
1984e4b17023SJohn Marino in INSN. Arguments CLOBBER_P and UNUSED_P say correspondingly that
1985e4b17023SJohn Marino the register is in clobber or unused after the insn. */
1986e4b17023SJohn Marino static void
mark_insn_pseudo_birth(rtx insn,int regno,bool clobber_p,bool unused_p)1987e4b17023SJohn Marino mark_insn_pseudo_birth (rtx insn, int regno, bool clobber_p, bool unused_p)
1988e4b17023SJohn Marino {
1989e4b17023SJohn Marino int incr, new_incr;
1990e4b17023SJohn Marino enum reg_class cl;
1991e4b17023SJohn Marino
1992e4b17023SJohn Marino gcc_assert (regno >= FIRST_PSEUDO_REGISTER);
1993e4b17023SJohn Marino cl = sched_regno_pressure_class[regno];
1994e4b17023SJohn Marino if (cl != NO_REGS)
1995e4b17023SJohn Marino {
1996e4b17023SJohn Marino incr = ira_reg_class_max_nregs[cl][PSEUDO_REGNO_MODE (regno)];
1997e4b17023SJohn Marino if (clobber_p)
1998e4b17023SJohn Marino {
1999e4b17023SJohn Marino new_incr = reg_pressure_info[cl].clobber_increase + incr;
2000e4b17023SJohn Marino reg_pressure_info[cl].clobber_increase = new_incr;
2001e4b17023SJohn Marino }
2002e4b17023SJohn Marino else if (unused_p)
2003e4b17023SJohn Marino {
2004e4b17023SJohn Marino new_incr = reg_pressure_info[cl].unused_set_increase + incr;
2005e4b17023SJohn Marino reg_pressure_info[cl].unused_set_increase = new_incr;
2006e4b17023SJohn Marino }
2007e4b17023SJohn Marino else
2008e4b17023SJohn Marino {
2009e4b17023SJohn Marino new_incr = reg_pressure_info[cl].set_increase + incr;
2010e4b17023SJohn Marino reg_pressure_info[cl].set_increase = new_incr;
2011e4b17023SJohn Marino if (! insn_use_p (insn, regno))
2012e4b17023SJohn Marino reg_pressure_info[cl].change += incr;
2013e4b17023SJohn Marino create_insn_reg_set (regno, insn);
2014e4b17023SJohn Marino }
2015e4b17023SJohn Marino gcc_assert (new_incr < (1 << INCREASE_BITS));
2016e4b17023SJohn Marino }
2017e4b17023SJohn Marino }
2018e4b17023SJohn Marino
2019e4b17023SJohn Marino /* Like mark_insn_pseudo_regno_birth except that NREGS saying how many
2020e4b17023SJohn Marino hard registers involved in the birth. */
2021e4b17023SJohn Marino static void
mark_insn_hard_regno_birth(rtx insn,int regno,int nregs,bool clobber_p,bool unused_p)2022e4b17023SJohn Marino mark_insn_hard_regno_birth (rtx insn, int regno, int nregs,
2023e4b17023SJohn Marino bool clobber_p, bool unused_p)
2024e4b17023SJohn Marino {
2025e4b17023SJohn Marino enum reg_class cl;
2026e4b17023SJohn Marino int new_incr, last = regno + nregs;
2027e4b17023SJohn Marino
2028e4b17023SJohn Marino while (regno < last)
2029e4b17023SJohn Marino {
2030e4b17023SJohn Marino gcc_assert (regno < FIRST_PSEUDO_REGISTER);
2031e4b17023SJohn Marino if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno))
2032e4b17023SJohn Marino {
2033e4b17023SJohn Marino cl = sched_regno_pressure_class[regno];
2034e4b17023SJohn Marino if (cl != NO_REGS)
2035e4b17023SJohn Marino {
2036e4b17023SJohn Marino if (clobber_p)
2037e4b17023SJohn Marino {
2038e4b17023SJohn Marino new_incr = reg_pressure_info[cl].clobber_increase + 1;
2039e4b17023SJohn Marino reg_pressure_info[cl].clobber_increase = new_incr;
2040e4b17023SJohn Marino }
2041e4b17023SJohn Marino else if (unused_p)
2042e4b17023SJohn Marino {
2043e4b17023SJohn Marino new_incr = reg_pressure_info[cl].unused_set_increase + 1;
2044e4b17023SJohn Marino reg_pressure_info[cl].unused_set_increase = new_incr;
2045e4b17023SJohn Marino }
2046e4b17023SJohn Marino else
2047e4b17023SJohn Marino {
2048e4b17023SJohn Marino new_incr = reg_pressure_info[cl].set_increase + 1;
2049e4b17023SJohn Marino reg_pressure_info[cl].set_increase = new_incr;
2050e4b17023SJohn Marino if (! insn_use_p (insn, regno))
2051e4b17023SJohn Marino reg_pressure_info[cl].change += 1;
2052e4b17023SJohn Marino create_insn_reg_set (regno, insn);
2053e4b17023SJohn Marino }
2054e4b17023SJohn Marino gcc_assert (new_incr < (1 << INCREASE_BITS));
2055e4b17023SJohn Marino }
2056e4b17023SJohn Marino }
2057e4b17023SJohn Marino regno++;
2058e4b17023SJohn Marino }
2059e4b17023SJohn Marino }
2060e4b17023SJohn Marino
2061e4b17023SJohn Marino /* Update the register pressure info after birth of pseudo or hard
2062e4b17023SJohn Marino register REG in INSN. Arguments CLOBBER_P and UNUSED_P say
2063e4b17023SJohn Marino correspondingly that the register is in clobber or unused after the
2064e4b17023SJohn Marino insn. */
2065e4b17023SJohn Marino static void
mark_insn_reg_birth(rtx insn,rtx reg,bool clobber_p,bool unused_p)2066e4b17023SJohn Marino mark_insn_reg_birth (rtx insn, rtx reg, bool clobber_p, bool unused_p)
2067e4b17023SJohn Marino {
2068e4b17023SJohn Marino int regno;
2069e4b17023SJohn Marino
2070e4b17023SJohn Marino if (GET_CODE (reg) == SUBREG)
2071e4b17023SJohn Marino reg = SUBREG_REG (reg);
2072e4b17023SJohn Marino
2073e4b17023SJohn Marino if (! REG_P (reg))
2074e4b17023SJohn Marino return;
2075e4b17023SJohn Marino
2076e4b17023SJohn Marino regno = REGNO (reg);
2077e4b17023SJohn Marino if (regno < FIRST_PSEUDO_REGISTER)
2078e4b17023SJohn Marino mark_insn_hard_regno_birth (insn, regno,
2079e4b17023SJohn Marino hard_regno_nregs[regno][GET_MODE (reg)],
2080e4b17023SJohn Marino clobber_p, unused_p);
2081e4b17023SJohn Marino else
2082e4b17023SJohn Marino mark_insn_pseudo_birth (insn, regno, clobber_p, unused_p);
2083e4b17023SJohn Marino }
2084e4b17023SJohn Marino
2085e4b17023SJohn Marino /* Update the register pressure info after death of pseudo register
2086e4b17023SJohn Marino REGNO. */
2087e4b17023SJohn Marino static void
mark_pseudo_death(int regno)2088e4b17023SJohn Marino mark_pseudo_death (int regno)
2089e4b17023SJohn Marino {
2090e4b17023SJohn Marino int incr;
2091e4b17023SJohn Marino enum reg_class cl;
2092e4b17023SJohn Marino
2093e4b17023SJohn Marino gcc_assert (regno >= FIRST_PSEUDO_REGISTER);
2094e4b17023SJohn Marino cl = sched_regno_pressure_class[regno];
2095e4b17023SJohn Marino if (cl != NO_REGS)
2096e4b17023SJohn Marino {
2097e4b17023SJohn Marino incr = ira_reg_class_max_nregs[cl][PSEUDO_REGNO_MODE (regno)];
2098e4b17023SJohn Marino reg_pressure_info[cl].change -= incr;
2099e4b17023SJohn Marino }
2100e4b17023SJohn Marino }
2101e4b17023SJohn Marino
2102e4b17023SJohn Marino /* Like mark_pseudo_death except that NREGS saying how many hard
2103e4b17023SJohn Marino registers involved in the death. */
2104e4b17023SJohn Marino static void
mark_hard_regno_death(int regno,int nregs)2105e4b17023SJohn Marino mark_hard_regno_death (int regno, int nregs)
2106e4b17023SJohn Marino {
2107e4b17023SJohn Marino enum reg_class cl;
2108e4b17023SJohn Marino int last = regno + nregs;
2109e4b17023SJohn Marino
2110e4b17023SJohn Marino while (regno < last)
2111e4b17023SJohn Marino {
2112e4b17023SJohn Marino gcc_assert (regno < FIRST_PSEUDO_REGISTER);
2113e4b17023SJohn Marino if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno))
2114e4b17023SJohn Marino {
2115e4b17023SJohn Marino cl = sched_regno_pressure_class[regno];
2116e4b17023SJohn Marino if (cl != NO_REGS)
2117e4b17023SJohn Marino reg_pressure_info[cl].change -= 1;
2118e4b17023SJohn Marino }
2119e4b17023SJohn Marino regno++;
2120e4b17023SJohn Marino }
2121e4b17023SJohn Marino }
2122e4b17023SJohn Marino
2123e4b17023SJohn Marino /* Update the register pressure info after death of pseudo or hard
2124e4b17023SJohn Marino register REG. */
2125e4b17023SJohn Marino static void
mark_reg_death(rtx reg)2126e4b17023SJohn Marino mark_reg_death (rtx reg)
2127e4b17023SJohn Marino {
2128e4b17023SJohn Marino int regno;
2129e4b17023SJohn Marino
2130e4b17023SJohn Marino if (GET_CODE (reg) == SUBREG)
2131e4b17023SJohn Marino reg = SUBREG_REG (reg);
2132e4b17023SJohn Marino
2133e4b17023SJohn Marino if (! REG_P (reg))
2134e4b17023SJohn Marino return;
2135e4b17023SJohn Marino
2136e4b17023SJohn Marino regno = REGNO (reg);
2137e4b17023SJohn Marino if (regno < FIRST_PSEUDO_REGISTER)
2138e4b17023SJohn Marino mark_hard_regno_death (regno, hard_regno_nregs[regno][GET_MODE (reg)]);
2139e4b17023SJohn Marino else
2140e4b17023SJohn Marino mark_pseudo_death (regno);
2141e4b17023SJohn Marino }
2142e4b17023SJohn Marino
2143e4b17023SJohn Marino /* Process SETTER of REG. DATA is an insn containing the setter. */
2144e4b17023SJohn Marino static void
mark_insn_reg_store(rtx reg,const_rtx setter,void * data)2145e4b17023SJohn Marino mark_insn_reg_store (rtx reg, const_rtx setter, void *data)
2146e4b17023SJohn Marino {
2147e4b17023SJohn Marino if (setter != NULL_RTX && GET_CODE (setter) != SET)
2148e4b17023SJohn Marino return;
2149e4b17023SJohn Marino mark_insn_reg_birth
2150e4b17023SJohn Marino ((rtx) data, reg, false,
2151e4b17023SJohn Marino find_reg_note ((const_rtx) data, REG_UNUSED, reg) != NULL_RTX);
2152e4b17023SJohn Marino }
2153e4b17023SJohn Marino
2154e4b17023SJohn Marino /* Like mark_insn_reg_store except notice just CLOBBERs; ignore SETs. */
2155e4b17023SJohn Marino static void
mark_insn_reg_clobber(rtx reg,const_rtx setter,void * data)2156e4b17023SJohn Marino mark_insn_reg_clobber (rtx reg, const_rtx setter, void *data)
2157e4b17023SJohn Marino {
2158e4b17023SJohn Marino if (GET_CODE (setter) == CLOBBER)
2159e4b17023SJohn Marino mark_insn_reg_birth ((rtx) data, reg, true, false);
2160e4b17023SJohn Marino }
2161e4b17023SJohn Marino
2162e4b17023SJohn Marino /* Set up reg pressure info related to INSN. */
2163e4b17023SJohn Marino void
init_insn_reg_pressure_info(rtx insn)2164e4b17023SJohn Marino init_insn_reg_pressure_info (rtx insn)
2165e4b17023SJohn Marino {
2166e4b17023SJohn Marino int i, len;
2167e4b17023SJohn Marino enum reg_class cl;
2168e4b17023SJohn Marino static struct reg_pressure_data *pressure_info;
2169e4b17023SJohn Marino rtx link;
2170e4b17023SJohn Marino
2171e4b17023SJohn Marino gcc_assert (sched_pressure_p);
2172e4b17023SJohn Marino
2173e4b17023SJohn Marino if (! INSN_P (insn))
2174e4b17023SJohn Marino return;
2175e4b17023SJohn Marino
2176e4b17023SJohn Marino for (i = 0; i < ira_pressure_classes_num; i++)
2177e4b17023SJohn Marino {
2178e4b17023SJohn Marino cl = ira_pressure_classes[i];
2179e4b17023SJohn Marino reg_pressure_info[cl].clobber_increase = 0;
2180e4b17023SJohn Marino reg_pressure_info[cl].set_increase = 0;
2181e4b17023SJohn Marino reg_pressure_info[cl].unused_set_increase = 0;
2182e4b17023SJohn Marino reg_pressure_info[cl].change = 0;
2183e4b17023SJohn Marino }
2184e4b17023SJohn Marino
2185e4b17023SJohn Marino note_stores (PATTERN (insn), mark_insn_reg_clobber, insn);
2186e4b17023SJohn Marino
2187e4b17023SJohn Marino note_stores (PATTERN (insn), mark_insn_reg_store, insn);
2188e4b17023SJohn Marino
2189e4b17023SJohn Marino #ifdef AUTO_INC_DEC
2190e4b17023SJohn Marino for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
2191e4b17023SJohn Marino if (REG_NOTE_KIND (link) == REG_INC)
2192e4b17023SJohn Marino mark_insn_reg_store (XEXP (link, 0), NULL_RTX, insn);
2193e4b17023SJohn Marino #endif
2194e4b17023SJohn Marino
2195e4b17023SJohn Marino for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
2196e4b17023SJohn Marino if (REG_NOTE_KIND (link) == REG_DEAD)
2197e4b17023SJohn Marino mark_reg_death (XEXP (link, 0));
2198e4b17023SJohn Marino
2199e4b17023SJohn Marino len = sizeof (struct reg_pressure_data) * ira_pressure_classes_num;
2200e4b17023SJohn Marino pressure_info
2201e4b17023SJohn Marino = INSN_REG_PRESSURE (insn) = (struct reg_pressure_data *) xmalloc (len);
2202e4b17023SJohn Marino INSN_MAX_REG_PRESSURE (insn) = (int *) xcalloc (ira_pressure_classes_num
2203e4b17023SJohn Marino * sizeof (int), 1);
2204e4b17023SJohn Marino for (i = 0; i < ira_pressure_classes_num; i++)
2205e4b17023SJohn Marino {
2206e4b17023SJohn Marino cl = ira_pressure_classes[i];
2207e4b17023SJohn Marino pressure_info[i].clobber_increase
2208e4b17023SJohn Marino = reg_pressure_info[cl].clobber_increase;
2209e4b17023SJohn Marino pressure_info[i].set_increase = reg_pressure_info[cl].set_increase;
2210e4b17023SJohn Marino pressure_info[i].unused_set_increase
2211e4b17023SJohn Marino = reg_pressure_info[cl].unused_set_increase;
2212e4b17023SJohn Marino pressure_info[i].change = reg_pressure_info[cl].change;
2213e4b17023SJohn Marino }
2214e4b17023SJohn Marino }
2215e4b17023SJohn Marino
2216e4b17023SJohn Marino
2217e4b17023SJohn Marino
2218e4b17023SJohn Marino
2219e4b17023SJohn Marino /* Internal variable for sched_analyze_[12] () functions.
2220e4b17023SJohn Marino If it is nonzero, this means that sched_analyze_[12] looks
2221e4b17023SJohn Marino at the most toplevel SET. */
2222e4b17023SJohn Marino static bool can_start_lhs_rhs_p;
2223e4b17023SJohn Marino
2224e4b17023SJohn Marino /* Extend reg info for the deps context DEPS given that
2225e4b17023SJohn Marino we have just generated a register numbered REGNO. */
2226e4b17023SJohn Marino static void
extend_deps_reg_info(struct deps_desc * deps,int regno)2227e4b17023SJohn Marino extend_deps_reg_info (struct deps_desc *deps, int regno)
2228e4b17023SJohn Marino {
2229e4b17023SJohn Marino int max_regno = regno + 1;
2230e4b17023SJohn Marino
2231e4b17023SJohn Marino gcc_assert (!reload_completed);
2232e4b17023SJohn Marino
2233e4b17023SJohn Marino /* In a readonly context, it would not hurt to extend info,
2234e4b17023SJohn Marino but it should not be needed. */
2235e4b17023SJohn Marino if (reload_completed && deps->readonly)
2236e4b17023SJohn Marino {
2237e4b17023SJohn Marino deps->max_reg = max_regno;
2238e4b17023SJohn Marino return;
2239e4b17023SJohn Marino }
2240e4b17023SJohn Marino
2241e4b17023SJohn Marino if (max_regno > deps->max_reg)
2242e4b17023SJohn Marino {
2243e4b17023SJohn Marino deps->reg_last = XRESIZEVEC (struct deps_reg, deps->reg_last,
2244e4b17023SJohn Marino max_regno);
2245e4b17023SJohn Marino memset (&deps->reg_last[deps->max_reg],
2246e4b17023SJohn Marino 0, (max_regno - deps->max_reg)
2247e4b17023SJohn Marino * sizeof (struct deps_reg));
2248e4b17023SJohn Marino deps->max_reg = max_regno;
2249e4b17023SJohn Marino }
2250e4b17023SJohn Marino }
2251e4b17023SJohn Marino
2252e4b17023SJohn Marino /* Extends REG_INFO_P if needed. */
2253e4b17023SJohn Marino void
maybe_extend_reg_info_p(void)2254e4b17023SJohn Marino maybe_extend_reg_info_p (void)
2255e4b17023SJohn Marino {
2256e4b17023SJohn Marino /* Extend REG_INFO_P, if needed. */
2257e4b17023SJohn Marino if ((unsigned int)max_regno - 1 >= reg_info_p_size)
2258e4b17023SJohn Marino {
2259e4b17023SJohn Marino size_t new_reg_info_p_size = max_regno + 128;
2260e4b17023SJohn Marino
2261e4b17023SJohn Marino gcc_assert (!reload_completed && sel_sched_p ());
2262e4b17023SJohn Marino
2263e4b17023SJohn Marino reg_info_p = (struct reg_info_t *) xrecalloc (reg_info_p,
2264e4b17023SJohn Marino new_reg_info_p_size,
2265e4b17023SJohn Marino reg_info_p_size,
2266e4b17023SJohn Marino sizeof (*reg_info_p));
2267e4b17023SJohn Marino reg_info_p_size = new_reg_info_p_size;
2268e4b17023SJohn Marino }
2269e4b17023SJohn Marino }
2270e4b17023SJohn Marino
2271e4b17023SJohn Marino /* Analyze a single reference to register (reg:MODE REGNO) in INSN.
2272e4b17023SJohn Marino The type of the reference is specified by REF and can be SET,
2273e4b17023SJohn Marino CLOBBER, PRE_DEC, POST_DEC, PRE_INC, POST_INC or USE. */
2274e4b17023SJohn Marino
2275e4b17023SJohn Marino static void
sched_analyze_reg(struct deps_desc * deps,int regno,enum machine_mode mode,enum rtx_code ref,rtx insn)2276e4b17023SJohn Marino sched_analyze_reg (struct deps_desc *deps, int regno, enum machine_mode mode,
2277e4b17023SJohn Marino enum rtx_code ref, rtx insn)
2278e4b17023SJohn Marino {
2279e4b17023SJohn Marino /* We could emit new pseudos in renaming. Extend the reg structures. */
2280e4b17023SJohn Marino if (!reload_completed && sel_sched_p ()
2281e4b17023SJohn Marino && (regno >= max_reg_num () - 1 || regno >= deps->max_reg))
2282e4b17023SJohn Marino extend_deps_reg_info (deps, regno);
2283e4b17023SJohn Marino
2284e4b17023SJohn Marino maybe_extend_reg_info_p ();
2285e4b17023SJohn Marino
2286e4b17023SJohn Marino /* A hard reg in a wide mode may really be multiple registers.
2287e4b17023SJohn Marino If so, mark all of them just like the first. */
2288e4b17023SJohn Marino if (regno < FIRST_PSEUDO_REGISTER)
2289e4b17023SJohn Marino {
2290e4b17023SJohn Marino int i = hard_regno_nregs[regno][mode];
2291e4b17023SJohn Marino if (ref == SET)
2292e4b17023SJohn Marino {
2293e4b17023SJohn Marino while (--i >= 0)
2294e4b17023SJohn Marino note_reg_set (regno + i);
2295e4b17023SJohn Marino }
2296e4b17023SJohn Marino else if (ref == USE)
2297e4b17023SJohn Marino {
2298e4b17023SJohn Marino while (--i >= 0)
2299e4b17023SJohn Marino note_reg_use (regno + i);
2300e4b17023SJohn Marino }
2301e4b17023SJohn Marino else
2302e4b17023SJohn Marino {
2303e4b17023SJohn Marino while (--i >= 0)
2304e4b17023SJohn Marino note_reg_clobber (regno + i);
2305e4b17023SJohn Marino }
2306e4b17023SJohn Marino }
2307e4b17023SJohn Marino
2308e4b17023SJohn Marino /* ??? Reload sometimes emits USEs and CLOBBERs of pseudos that
2309e4b17023SJohn Marino it does not reload. Ignore these as they have served their
2310e4b17023SJohn Marino purpose already. */
2311e4b17023SJohn Marino else if (regno >= deps->max_reg)
2312e4b17023SJohn Marino {
2313e4b17023SJohn Marino enum rtx_code code = GET_CODE (PATTERN (insn));
2314e4b17023SJohn Marino gcc_assert (code == USE || code == CLOBBER);
2315e4b17023SJohn Marino }
2316e4b17023SJohn Marino
2317e4b17023SJohn Marino else
2318e4b17023SJohn Marino {
2319e4b17023SJohn Marino if (ref == SET)
2320e4b17023SJohn Marino note_reg_set (regno);
2321e4b17023SJohn Marino else if (ref == USE)
2322e4b17023SJohn Marino note_reg_use (regno);
2323e4b17023SJohn Marino else
2324e4b17023SJohn Marino note_reg_clobber (regno);
2325e4b17023SJohn Marino
2326e4b17023SJohn Marino /* Pseudos that are REG_EQUIV to something may be replaced
2327e4b17023SJohn Marino by that during reloading. We need only add dependencies for
2328e4b17023SJohn Marino the address in the REG_EQUIV note. */
2329e4b17023SJohn Marino if (!reload_completed && get_reg_known_equiv_p (regno))
2330e4b17023SJohn Marino {
2331e4b17023SJohn Marino rtx t = get_reg_known_value (regno);
2332e4b17023SJohn Marino if (MEM_P (t))
2333e4b17023SJohn Marino sched_analyze_2 (deps, XEXP (t, 0), insn);
2334e4b17023SJohn Marino }
2335e4b17023SJohn Marino
2336e4b17023SJohn Marino /* Don't let it cross a call after scheduling if it doesn't
2337e4b17023SJohn Marino already cross one. */
2338e4b17023SJohn Marino if (REG_N_CALLS_CROSSED (regno) == 0)
2339e4b17023SJohn Marino {
2340e4b17023SJohn Marino if (!deps->readonly && ref == USE && !DEBUG_INSN_P (insn))
2341e4b17023SJohn Marino deps->sched_before_next_call
2342e4b17023SJohn Marino = alloc_INSN_LIST (insn, deps->sched_before_next_call);
2343e4b17023SJohn Marino else
2344e4b17023SJohn Marino add_dependence_list (insn, deps->last_function_call, 1,
2345e4b17023SJohn Marino REG_DEP_ANTI);
2346e4b17023SJohn Marino }
2347e4b17023SJohn Marino }
2348e4b17023SJohn Marino }
2349e4b17023SJohn Marino
2350e4b17023SJohn Marino /* Analyze a single SET, CLOBBER, PRE_DEC, POST_DEC, PRE_INC or POST_INC
2351e4b17023SJohn Marino rtx, X, creating all dependencies generated by the write to the
2352e4b17023SJohn Marino destination of X, and reads of everything mentioned. */
2353e4b17023SJohn Marino
2354e4b17023SJohn Marino static void
sched_analyze_1(struct deps_desc * deps,rtx x,rtx insn)2355e4b17023SJohn Marino sched_analyze_1 (struct deps_desc *deps, rtx x, rtx insn)
2356e4b17023SJohn Marino {
2357e4b17023SJohn Marino rtx dest = XEXP (x, 0);
2358e4b17023SJohn Marino enum rtx_code code = GET_CODE (x);
2359e4b17023SJohn Marino bool cslr_p = can_start_lhs_rhs_p;
2360e4b17023SJohn Marino
2361e4b17023SJohn Marino can_start_lhs_rhs_p = false;
2362e4b17023SJohn Marino
2363e4b17023SJohn Marino gcc_assert (dest);
2364e4b17023SJohn Marino if (dest == 0)
2365e4b17023SJohn Marino return;
2366e4b17023SJohn Marino
2367e4b17023SJohn Marino if (cslr_p && sched_deps_info->start_lhs)
2368e4b17023SJohn Marino sched_deps_info->start_lhs (dest);
2369e4b17023SJohn Marino
2370e4b17023SJohn Marino if (GET_CODE (dest) == PARALLEL)
2371e4b17023SJohn Marino {
2372e4b17023SJohn Marino int i;
2373e4b17023SJohn Marino
2374e4b17023SJohn Marino for (i = XVECLEN (dest, 0) - 1; i >= 0; i--)
2375e4b17023SJohn Marino if (XEXP (XVECEXP (dest, 0, i), 0) != 0)
2376e4b17023SJohn Marino sched_analyze_1 (deps,
2377e4b17023SJohn Marino gen_rtx_CLOBBER (VOIDmode,
2378e4b17023SJohn Marino XEXP (XVECEXP (dest, 0, i), 0)),
2379e4b17023SJohn Marino insn);
2380e4b17023SJohn Marino
2381e4b17023SJohn Marino if (cslr_p && sched_deps_info->finish_lhs)
2382e4b17023SJohn Marino sched_deps_info->finish_lhs ();
2383e4b17023SJohn Marino
2384e4b17023SJohn Marino if (code == SET)
2385e4b17023SJohn Marino {
2386e4b17023SJohn Marino can_start_lhs_rhs_p = cslr_p;
2387e4b17023SJohn Marino
2388e4b17023SJohn Marino sched_analyze_2 (deps, SET_SRC (x), insn);
2389e4b17023SJohn Marino
2390e4b17023SJohn Marino can_start_lhs_rhs_p = false;
2391e4b17023SJohn Marino }
2392e4b17023SJohn Marino
2393e4b17023SJohn Marino return;
2394e4b17023SJohn Marino }
2395e4b17023SJohn Marino
2396e4b17023SJohn Marino while (GET_CODE (dest) == STRICT_LOW_PART || GET_CODE (dest) == SUBREG
2397e4b17023SJohn Marino || GET_CODE (dest) == ZERO_EXTRACT)
2398e4b17023SJohn Marino {
2399e4b17023SJohn Marino if (GET_CODE (dest) == STRICT_LOW_PART
2400e4b17023SJohn Marino || GET_CODE (dest) == ZERO_EXTRACT
2401e4b17023SJohn Marino || df_read_modify_subreg_p (dest))
2402e4b17023SJohn Marino {
2403e4b17023SJohn Marino /* These both read and modify the result. We must handle
2404e4b17023SJohn Marino them as writes to get proper dependencies for following
2405e4b17023SJohn Marino instructions. We must handle them as reads to get proper
2406e4b17023SJohn Marino dependencies from this to previous instructions.
2407e4b17023SJohn Marino Thus we need to call sched_analyze_2. */
2408e4b17023SJohn Marino
2409e4b17023SJohn Marino sched_analyze_2 (deps, XEXP (dest, 0), insn);
2410e4b17023SJohn Marino }
2411e4b17023SJohn Marino if (GET_CODE (dest) == ZERO_EXTRACT)
2412e4b17023SJohn Marino {
2413e4b17023SJohn Marino /* The second and third arguments are values read by this insn. */
2414e4b17023SJohn Marino sched_analyze_2 (deps, XEXP (dest, 1), insn);
2415e4b17023SJohn Marino sched_analyze_2 (deps, XEXP (dest, 2), insn);
2416e4b17023SJohn Marino }
2417e4b17023SJohn Marino dest = XEXP (dest, 0);
2418e4b17023SJohn Marino }
2419e4b17023SJohn Marino
2420e4b17023SJohn Marino if (REG_P (dest))
2421e4b17023SJohn Marino {
2422e4b17023SJohn Marino int regno = REGNO (dest);
2423e4b17023SJohn Marino enum machine_mode mode = GET_MODE (dest);
2424e4b17023SJohn Marino
2425e4b17023SJohn Marino sched_analyze_reg (deps, regno, mode, code, insn);
2426e4b17023SJohn Marino
2427e4b17023SJohn Marino #ifdef STACK_REGS
2428e4b17023SJohn Marino /* Treat all writes to a stack register as modifying the TOS. */
2429e4b17023SJohn Marino if (regno >= FIRST_STACK_REG && regno <= LAST_STACK_REG)
2430e4b17023SJohn Marino {
2431e4b17023SJohn Marino /* Avoid analyzing the same register twice. */
2432e4b17023SJohn Marino if (regno != FIRST_STACK_REG)
2433e4b17023SJohn Marino sched_analyze_reg (deps, FIRST_STACK_REG, mode, code, insn);
2434e4b17023SJohn Marino
2435e4b17023SJohn Marino add_to_hard_reg_set (&implicit_reg_pending_uses, mode,
2436e4b17023SJohn Marino FIRST_STACK_REG);
2437e4b17023SJohn Marino }
2438e4b17023SJohn Marino #endif
2439e4b17023SJohn Marino }
2440e4b17023SJohn Marino else if (MEM_P (dest))
2441e4b17023SJohn Marino {
2442e4b17023SJohn Marino /* Writing memory. */
2443e4b17023SJohn Marino rtx t = dest;
2444e4b17023SJohn Marino
2445e4b17023SJohn Marino if (sched_deps_info->use_cselib)
2446e4b17023SJohn Marino {
2447e4b17023SJohn Marino enum machine_mode address_mode
2448e4b17023SJohn Marino = targetm.addr_space.address_mode (MEM_ADDR_SPACE (dest));
2449e4b17023SJohn Marino
2450e4b17023SJohn Marino t = shallow_copy_rtx (dest);
2451e4b17023SJohn Marino cselib_lookup_from_insn (XEXP (t, 0), address_mode, 1,
2452e4b17023SJohn Marino GET_MODE (t), insn);
2453e4b17023SJohn Marino XEXP (t, 0)
2454e4b17023SJohn Marino = cselib_subst_to_values_from_insn (XEXP (t, 0), GET_MODE (t),
2455e4b17023SJohn Marino insn);
2456e4b17023SJohn Marino }
2457e4b17023SJohn Marino t = canon_rtx (t);
2458e4b17023SJohn Marino
2459e4b17023SJohn Marino /* Pending lists can't get larger with a readonly context. */
2460e4b17023SJohn Marino if (!deps->readonly
2461e4b17023SJohn Marino && ((deps->pending_read_list_length + deps->pending_write_list_length)
2462e4b17023SJohn Marino > MAX_PENDING_LIST_LENGTH))
2463e4b17023SJohn Marino {
2464e4b17023SJohn Marino /* Flush all pending reads and writes to prevent the pending lists
2465e4b17023SJohn Marino from getting any larger. Insn scheduling runs too slowly when
2466e4b17023SJohn Marino these lists get long. When compiling GCC with itself,
2467e4b17023SJohn Marino this flush occurs 8 times for sparc, and 10 times for m88k using
2468e4b17023SJohn Marino the default value of 32. */
2469e4b17023SJohn Marino flush_pending_lists (deps, insn, false, true);
2470e4b17023SJohn Marino }
2471e4b17023SJohn Marino else
2472e4b17023SJohn Marino {
2473e4b17023SJohn Marino rtx pending, pending_mem;
2474e4b17023SJohn Marino
2475e4b17023SJohn Marino pending = deps->pending_read_insns;
2476e4b17023SJohn Marino pending_mem = deps->pending_read_mems;
2477e4b17023SJohn Marino while (pending)
2478e4b17023SJohn Marino {
2479e4b17023SJohn Marino if (anti_dependence (XEXP (pending_mem, 0), t)
2480e4b17023SJohn Marino && ! sched_insns_conditions_mutex_p (insn, XEXP (pending, 0)))
2481e4b17023SJohn Marino note_mem_dep (t, XEXP (pending_mem, 0), XEXP (pending, 0),
2482e4b17023SJohn Marino DEP_ANTI);
2483e4b17023SJohn Marino
2484e4b17023SJohn Marino pending = XEXP (pending, 1);
2485e4b17023SJohn Marino pending_mem = XEXP (pending_mem, 1);
2486e4b17023SJohn Marino }
2487e4b17023SJohn Marino
2488e4b17023SJohn Marino pending = deps->pending_write_insns;
2489e4b17023SJohn Marino pending_mem = deps->pending_write_mems;
2490e4b17023SJohn Marino while (pending)
2491e4b17023SJohn Marino {
2492e4b17023SJohn Marino if (output_dependence (XEXP (pending_mem, 0), t)
2493e4b17023SJohn Marino && ! sched_insns_conditions_mutex_p (insn, XEXP (pending, 0)))
2494e4b17023SJohn Marino note_mem_dep (t, XEXP (pending_mem, 0), XEXP (pending, 0),
2495e4b17023SJohn Marino DEP_OUTPUT);
2496e4b17023SJohn Marino
2497e4b17023SJohn Marino pending = XEXP (pending, 1);
2498e4b17023SJohn Marino pending_mem = XEXP (pending_mem, 1);
2499e4b17023SJohn Marino }
2500e4b17023SJohn Marino
2501e4b17023SJohn Marino add_dependence_list (insn, deps->last_pending_memory_flush, 1,
2502e4b17023SJohn Marino REG_DEP_ANTI);
2503e4b17023SJohn Marino add_dependence_list (insn, deps->pending_jump_insns, 1,
2504e4b17023SJohn Marino REG_DEP_CONTROL);
2505e4b17023SJohn Marino
2506e4b17023SJohn Marino if (!deps->readonly)
2507e4b17023SJohn Marino add_insn_mem_dependence (deps, false, insn, dest);
2508e4b17023SJohn Marino }
2509e4b17023SJohn Marino sched_analyze_2 (deps, XEXP (dest, 0), insn);
2510e4b17023SJohn Marino }
2511e4b17023SJohn Marino
2512e4b17023SJohn Marino if (cslr_p && sched_deps_info->finish_lhs)
2513e4b17023SJohn Marino sched_deps_info->finish_lhs ();
2514e4b17023SJohn Marino
2515e4b17023SJohn Marino /* Analyze reads. */
2516e4b17023SJohn Marino if (GET_CODE (x) == SET)
2517e4b17023SJohn Marino {
2518e4b17023SJohn Marino can_start_lhs_rhs_p = cslr_p;
2519e4b17023SJohn Marino
2520e4b17023SJohn Marino sched_analyze_2 (deps, SET_SRC (x), insn);
2521e4b17023SJohn Marino
2522e4b17023SJohn Marino can_start_lhs_rhs_p = false;
2523e4b17023SJohn Marino }
2524e4b17023SJohn Marino }
2525e4b17023SJohn Marino
2526e4b17023SJohn Marino /* Analyze the uses of memory and registers in rtx X in INSN. */
2527e4b17023SJohn Marino static void
sched_analyze_2(struct deps_desc * deps,rtx x,rtx insn)2528e4b17023SJohn Marino sched_analyze_2 (struct deps_desc *deps, rtx x, rtx insn)
2529e4b17023SJohn Marino {
2530e4b17023SJohn Marino int i;
2531e4b17023SJohn Marino int j;
2532e4b17023SJohn Marino enum rtx_code code;
2533e4b17023SJohn Marino const char *fmt;
2534e4b17023SJohn Marino bool cslr_p = can_start_lhs_rhs_p;
2535e4b17023SJohn Marino
2536e4b17023SJohn Marino can_start_lhs_rhs_p = false;
2537e4b17023SJohn Marino
2538e4b17023SJohn Marino gcc_assert (x);
2539e4b17023SJohn Marino if (x == 0)
2540e4b17023SJohn Marino return;
2541e4b17023SJohn Marino
2542e4b17023SJohn Marino if (cslr_p && sched_deps_info->start_rhs)
2543e4b17023SJohn Marino sched_deps_info->start_rhs (x);
2544e4b17023SJohn Marino
2545e4b17023SJohn Marino code = GET_CODE (x);
2546e4b17023SJohn Marino
2547e4b17023SJohn Marino switch (code)
2548e4b17023SJohn Marino {
2549e4b17023SJohn Marino case CONST_INT:
2550e4b17023SJohn Marino case CONST_DOUBLE:
2551e4b17023SJohn Marino case CONST_FIXED:
2552e4b17023SJohn Marino case CONST_VECTOR:
2553e4b17023SJohn Marino case SYMBOL_REF:
2554e4b17023SJohn Marino case CONST:
2555e4b17023SJohn Marino case LABEL_REF:
2556e4b17023SJohn Marino /* Ignore constants. */
2557e4b17023SJohn Marino if (cslr_p && sched_deps_info->finish_rhs)
2558e4b17023SJohn Marino sched_deps_info->finish_rhs ();
2559e4b17023SJohn Marino
2560e4b17023SJohn Marino return;
2561e4b17023SJohn Marino
2562e4b17023SJohn Marino #ifdef HAVE_cc0
2563e4b17023SJohn Marino case CC0:
2564e4b17023SJohn Marino /* User of CC0 depends on immediately preceding insn. */
2565e4b17023SJohn Marino SCHED_GROUP_P (insn) = 1;
2566e4b17023SJohn Marino /* Don't move CC0 setter to another block (it can set up the
2567e4b17023SJohn Marino same flag for previous CC0 users which is safe). */
2568e4b17023SJohn Marino CANT_MOVE (prev_nonnote_insn (insn)) = 1;
2569e4b17023SJohn Marino
2570e4b17023SJohn Marino if (cslr_p && sched_deps_info->finish_rhs)
2571e4b17023SJohn Marino sched_deps_info->finish_rhs ();
2572e4b17023SJohn Marino
2573e4b17023SJohn Marino return;
2574e4b17023SJohn Marino #endif
2575e4b17023SJohn Marino
2576e4b17023SJohn Marino case REG:
2577e4b17023SJohn Marino {
2578e4b17023SJohn Marino int regno = REGNO (x);
2579e4b17023SJohn Marino enum machine_mode mode = GET_MODE (x);
2580e4b17023SJohn Marino
2581e4b17023SJohn Marino sched_analyze_reg (deps, regno, mode, USE, insn);
2582e4b17023SJohn Marino
2583e4b17023SJohn Marino #ifdef STACK_REGS
2584e4b17023SJohn Marino /* Treat all reads of a stack register as modifying the TOS. */
2585e4b17023SJohn Marino if (regno >= FIRST_STACK_REG && regno <= LAST_STACK_REG)
2586e4b17023SJohn Marino {
2587e4b17023SJohn Marino /* Avoid analyzing the same register twice. */
2588e4b17023SJohn Marino if (regno != FIRST_STACK_REG)
2589e4b17023SJohn Marino sched_analyze_reg (deps, FIRST_STACK_REG, mode, USE, insn);
2590e4b17023SJohn Marino sched_analyze_reg (deps, FIRST_STACK_REG, mode, SET, insn);
2591e4b17023SJohn Marino }
2592e4b17023SJohn Marino #endif
2593e4b17023SJohn Marino
2594e4b17023SJohn Marino if (cslr_p && sched_deps_info->finish_rhs)
2595e4b17023SJohn Marino sched_deps_info->finish_rhs ();
2596e4b17023SJohn Marino
2597e4b17023SJohn Marino return;
2598e4b17023SJohn Marino }
2599e4b17023SJohn Marino
2600e4b17023SJohn Marino case MEM:
2601e4b17023SJohn Marino {
2602e4b17023SJohn Marino /* Reading memory. */
2603e4b17023SJohn Marino rtx u;
2604e4b17023SJohn Marino rtx pending, pending_mem;
2605e4b17023SJohn Marino rtx t = x;
2606e4b17023SJohn Marino
2607e4b17023SJohn Marino if (sched_deps_info->use_cselib)
2608e4b17023SJohn Marino {
2609e4b17023SJohn Marino enum machine_mode address_mode
2610e4b17023SJohn Marino = targetm.addr_space.address_mode (MEM_ADDR_SPACE (t));
2611e4b17023SJohn Marino
2612e4b17023SJohn Marino t = shallow_copy_rtx (t);
2613e4b17023SJohn Marino cselib_lookup_from_insn (XEXP (t, 0), address_mode, 1,
2614e4b17023SJohn Marino GET_MODE (t), insn);
2615e4b17023SJohn Marino XEXP (t, 0)
2616e4b17023SJohn Marino = cselib_subst_to_values_from_insn (XEXP (t, 0), GET_MODE (t),
2617e4b17023SJohn Marino insn);
2618e4b17023SJohn Marino }
2619e4b17023SJohn Marino
2620e4b17023SJohn Marino if (!DEBUG_INSN_P (insn))
2621e4b17023SJohn Marino {
2622e4b17023SJohn Marino t = canon_rtx (t);
2623e4b17023SJohn Marino pending = deps->pending_read_insns;
2624e4b17023SJohn Marino pending_mem = deps->pending_read_mems;
2625e4b17023SJohn Marino while (pending)
2626e4b17023SJohn Marino {
2627e4b17023SJohn Marino if (read_dependence (XEXP (pending_mem, 0), t)
2628e4b17023SJohn Marino && ! sched_insns_conditions_mutex_p (insn,
2629e4b17023SJohn Marino XEXP (pending, 0)))
2630e4b17023SJohn Marino note_mem_dep (t, XEXP (pending_mem, 0), XEXP (pending, 0),
2631e4b17023SJohn Marino DEP_ANTI);
2632e4b17023SJohn Marino
2633e4b17023SJohn Marino pending = XEXP (pending, 1);
2634e4b17023SJohn Marino pending_mem = XEXP (pending_mem, 1);
2635e4b17023SJohn Marino }
2636e4b17023SJohn Marino
2637e4b17023SJohn Marino pending = deps->pending_write_insns;
2638e4b17023SJohn Marino pending_mem = deps->pending_write_mems;
2639e4b17023SJohn Marino while (pending)
2640e4b17023SJohn Marino {
2641e4b17023SJohn Marino if (true_dependence (XEXP (pending_mem, 0), VOIDmode, t)
2642e4b17023SJohn Marino && ! sched_insns_conditions_mutex_p (insn,
2643e4b17023SJohn Marino XEXP (pending, 0)))
2644e4b17023SJohn Marino note_mem_dep (t, XEXP (pending_mem, 0), XEXP (pending, 0),
2645e4b17023SJohn Marino sched_deps_info->generate_spec_deps
2646e4b17023SJohn Marino ? BEGIN_DATA | DEP_TRUE : DEP_TRUE);
2647e4b17023SJohn Marino
2648e4b17023SJohn Marino pending = XEXP (pending, 1);
2649e4b17023SJohn Marino pending_mem = XEXP (pending_mem, 1);
2650e4b17023SJohn Marino }
2651e4b17023SJohn Marino
2652e4b17023SJohn Marino for (u = deps->last_pending_memory_flush; u; u = XEXP (u, 1))
2653e4b17023SJohn Marino add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
2654e4b17023SJohn Marino
2655e4b17023SJohn Marino for (u = deps->pending_jump_insns; u; u = XEXP (u, 1))
2656e4b17023SJohn Marino if (deps_may_trap_p (x))
2657e4b17023SJohn Marino {
2658e4b17023SJohn Marino if ((sched_deps_info->generate_spec_deps)
2659e4b17023SJohn Marino && sel_sched_p () && (spec_info->mask & BEGIN_CONTROL))
2660e4b17023SJohn Marino {
2661e4b17023SJohn Marino ds_t ds = set_dep_weak (DEP_ANTI, BEGIN_CONTROL,
2662e4b17023SJohn Marino MAX_DEP_WEAK);
2663e4b17023SJohn Marino
2664e4b17023SJohn Marino note_dep (XEXP (u, 0), ds);
2665e4b17023SJohn Marino }
2666e4b17023SJohn Marino else
2667e4b17023SJohn Marino add_dependence (insn, XEXP (u, 0), REG_DEP_CONTROL);
2668e4b17023SJohn Marino }
2669e4b17023SJohn Marino }
2670e4b17023SJohn Marino
2671e4b17023SJohn Marino /* Always add these dependencies to pending_reads, since
2672e4b17023SJohn Marino this insn may be followed by a write. */
2673e4b17023SJohn Marino if (!deps->readonly)
2674e4b17023SJohn Marino add_insn_mem_dependence (deps, true, insn, x);
2675e4b17023SJohn Marino
2676e4b17023SJohn Marino sched_analyze_2 (deps, XEXP (x, 0), insn);
2677e4b17023SJohn Marino
2678e4b17023SJohn Marino if (cslr_p && sched_deps_info->finish_rhs)
2679e4b17023SJohn Marino sched_deps_info->finish_rhs ();
2680e4b17023SJohn Marino
2681e4b17023SJohn Marino return;
2682e4b17023SJohn Marino }
2683e4b17023SJohn Marino
2684e4b17023SJohn Marino /* Force pending stores to memory in case a trap handler needs them. */
2685e4b17023SJohn Marino case TRAP_IF:
2686e4b17023SJohn Marino flush_pending_lists (deps, insn, true, false);
2687e4b17023SJohn Marino break;
2688e4b17023SJohn Marino
2689e4b17023SJohn Marino case PREFETCH:
2690e4b17023SJohn Marino if (PREFETCH_SCHEDULE_BARRIER_P (x))
2691e4b17023SJohn Marino reg_pending_barrier = TRUE_BARRIER;
2692e4b17023SJohn Marino break;
2693e4b17023SJohn Marino
2694e4b17023SJohn Marino case UNSPEC_VOLATILE:
2695e4b17023SJohn Marino flush_pending_lists (deps, insn, true, true);
2696e4b17023SJohn Marino /* FALLTHRU */
2697e4b17023SJohn Marino
2698e4b17023SJohn Marino case ASM_OPERANDS:
2699e4b17023SJohn Marino case ASM_INPUT:
2700e4b17023SJohn Marino {
2701e4b17023SJohn Marino /* Traditional and volatile asm instructions must be considered to use
2702e4b17023SJohn Marino and clobber all hard registers, all pseudo-registers and all of
2703e4b17023SJohn Marino memory. So must TRAP_IF and UNSPEC_VOLATILE operations.
2704e4b17023SJohn Marino
2705e4b17023SJohn Marino Consider for instance a volatile asm that changes the fpu rounding
2706e4b17023SJohn Marino mode. An insn should not be moved across this even if it only uses
2707e4b17023SJohn Marino pseudo-regs because it might give an incorrectly rounded result. */
2708e4b17023SJohn Marino if (code != ASM_OPERANDS || MEM_VOLATILE_P (x))
2709e4b17023SJohn Marino reg_pending_barrier = TRUE_BARRIER;
2710e4b17023SJohn Marino
2711e4b17023SJohn Marino /* For all ASM_OPERANDS, we must traverse the vector of input operands.
2712e4b17023SJohn Marino We can not just fall through here since then we would be confused
2713e4b17023SJohn Marino by the ASM_INPUT rtx inside ASM_OPERANDS, which do not indicate
2714e4b17023SJohn Marino traditional asms unlike their normal usage. */
2715e4b17023SJohn Marino
2716e4b17023SJohn Marino if (code == ASM_OPERANDS)
2717e4b17023SJohn Marino {
2718e4b17023SJohn Marino for (j = 0; j < ASM_OPERANDS_INPUT_LENGTH (x); j++)
2719e4b17023SJohn Marino sched_analyze_2 (deps, ASM_OPERANDS_INPUT (x, j), insn);
2720e4b17023SJohn Marino
2721e4b17023SJohn Marino if (cslr_p && sched_deps_info->finish_rhs)
2722e4b17023SJohn Marino sched_deps_info->finish_rhs ();
2723e4b17023SJohn Marino
2724e4b17023SJohn Marino return;
2725e4b17023SJohn Marino }
2726e4b17023SJohn Marino break;
2727e4b17023SJohn Marino }
2728e4b17023SJohn Marino
2729e4b17023SJohn Marino case PRE_DEC:
2730e4b17023SJohn Marino case POST_DEC:
2731e4b17023SJohn Marino case PRE_INC:
2732e4b17023SJohn Marino case POST_INC:
2733e4b17023SJohn Marino /* These both read and modify the result. We must handle them as writes
2734e4b17023SJohn Marino to get proper dependencies for following instructions. We must handle
2735e4b17023SJohn Marino them as reads to get proper dependencies from this to previous
2736e4b17023SJohn Marino instructions. Thus we need to pass them to both sched_analyze_1
2737e4b17023SJohn Marino and sched_analyze_2. We must call sched_analyze_2 first in order
2738e4b17023SJohn Marino to get the proper antecedent for the read. */
2739e4b17023SJohn Marino sched_analyze_2 (deps, XEXP (x, 0), insn);
2740e4b17023SJohn Marino sched_analyze_1 (deps, x, insn);
2741e4b17023SJohn Marino
2742e4b17023SJohn Marino if (cslr_p && sched_deps_info->finish_rhs)
2743e4b17023SJohn Marino sched_deps_info->finish_rhs ();
2744e4b17023SJohn Marino
2745e4b17023SJohn Marino return;
2746e4b17023SJohn Marino
2747e4b17023SJohn Marino case POST_MODIFY:
2748e4b17023SJohn Marino case PRE_MODIFY:
2749e4b17023SJohn Marino /* op0 = op0 + op1 */
2750e4b17023SJohn Marino sched_analyze_2 (deps, XEXP (x, 0), insn);
2751e4b17023SJohn Marino sched_analyze_2 (deps, XEXP (x, 1), insn);
2752e4b17023SJohn Marino sched_analyze_1 (deps, x, insn);
2753e4b17023SJohn Marino
2754e4b17023SJohn Marino if (cslr_p && sched_deps_info->finish_rhs)
2755e4b17023SJohn Marino sched_deps_info->finish_rhs ();
2756e4b17023SJohn Marino
2757e4b17023SJohn Marino return;
2758e4b17023SJohn Marino
2759e4b17023SJohn Marino default:
2760e4b17023SJohn Marino break;
2761e4b17023SJohn Marino }
2762e4b17023SJohn Marino
2763e4b17023SJohn Marino /* Other cases: walk the insn. */
2764e4b17023SJohn Marino fmt = GET_RTX_FORMAT (code);
2765e4b17023SJohn Marino for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
2766e4b17023SJohn Marino {
2767e4b17023SJohn Marino if (fmt[i] == 'e')
2768e4b17023SJohn Marino sched_analyze_2 (deps, XEXP (x, i), insn);
2769e4b17023SJohn Marino else if (fmt[i] == 'E')
2770e4b17023SJohn Marino for (j = 0; j < XVECLEN (x, i); j++)
2771e4b17023SJohn Marino sched_analyze_2 (deps, XVECEXP (x, i, j), insn);
2772e4b17023SJohn Marino }
2773e4b17023SJohn Marino
2774e4b17023SJohn Marino if (cslr_p && sched_deps_info->finish_rhs)
2775e4b17023SJohn Marino sched_deps_info->finish_rhs ();
2776e4b17023SJohn Marino }
2777e4b17023SJohn Marino
2778e4b17023SJohn Marino /* Analyze an INSN with pattern X to find all dependencies. */
2779e4b17023SJohn Marino static void
sched_analyze_insn(struct deps_desc * deps,rtx x,rtx insn)2780e4b17023SJohn Marino sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
2781e4b17023SJohn Marino {
2782e4b17023SJohn Marino RTX_CODE code = GET_CODE (x);
2783e4b17023SJohn Marino rtx link;
2784e4b17023SJohn Marino unsigned i;
2785e4b17023SJohn Marino reg_set_iterator rsi;
2786e4b17023SJohn Marino
2787e4b17023SJohn Marino if (! reload_completed)
2788e4b17023SJohn Marino {
2789e4b17023SJohn Marino HARD_REG_SET temp;
2790e4b17023SJohn Marino
2791e4b17023SJohn Marino extract_insn (insn);
2792e4b17023SJohn Marino preprocess_constraints ();
2793e4b17023SJohn Marino ira_implicitly_set_insn_hard_regs (&temp);
2794e4b17023SJohn Marino AND_COMPL_HARD_REG_SET (temp, ira_no_alloc_regs);
2795e4b17023SJohn Marino IOR_HARD_REG_SET (implicit_reg_pending_clobbers, temp);
2796e4b17023SJohn Marino }
2797e4b17023SJohn Marino
2798e4b17023SJohn Marino can_start_lhs_rhs_p = (NONJUMP_INSN_P (insn)
2799e4b17023SJohn Marino && code == SET);
2800e4b17023SJohn Marino
2801e4b17023SJohn Marino if (may_trap_p (x))
2802e4b17023SJohn Marino /* Avoid moving trapping instructions accross function calls that might
2803e4b17023SJohn Marino not always return. */
2804e4b17023SJohn Marino add_dependence_list (insn, deps->last_function_call_may_noreturn,
2805e4b17023SJohn Marino 1, REG_DEP_ANTI);
2806e4b17023SJohn Marino
2807e4b17023SJohn Marino /* We must avoid creating a situation in which two successors of the
2808e4b17023SJohn Marino current block have different unwind info after scheduling. If at any
2809e4b17023SJohn Marino point the two paths re-join this leads to incorrect unwind info. */
2810e4b17023SJohn Marino /* ??? There are certain situations involving a forced frame pointer in
2811e4b17023SJohn Marino which, with extra effort, we could fix up the unwind info at a later
2812e4b17023SJohn Marino CFG join. However, it seems better to notice these cases earlier
2813e4b17023SJohn Marino during prologue generation and avoid marking the frame pointer setup
2814e4b17023SJohn Marino as frame-related at all. */
2815e4b17023SJohn Marino if (RTX_FRAME_RELATED_P (insn))
2816e4b17023SJohn Marino {
2817e4b17023SJohn Marino /* Make sure prologue insn is scheduled before next jump. */
2818e4b17023SJohn Marino deps->sched_before_next_jump
2819e4b17023SJohn Marino = alloc_INSN_LIST (insn, deps->sched_before_next_jump);
2820e4b17023SJohn Marino
2821e4b17023SJohn Marino /* Make sure epilogue insn is scheduled after preceding jumps. */
2822e4b17023SJohn Marino add_dependence_list (insn, deps->pending_jump_insns, 1, REG_DEP_ANTI);
2823e4b17023SJohn Marino }
2824e4b17023SJohn Marino
2825e4b17023SJohn Marino if (code == COND_EXEC)
2826e4b17023SJohn Marino {
2827e4b17023SJohn Marino sched_analyze_2 (deps, COND_EXEC_TEST (x), insn);
2828e4b17023SJohn Marino
2829e4b17023SJohn Marino /* ??? Should be recording conditions so we reduce the number of
2830e4b17023SJohn Marino false dependencies. */
2831e4b17023SJohn Marino x = COND_EXEC_CODE (x);
2832e4b17023SJohn Marino code = GET_CODE (x);
2833e4b17023SJohn Marino }
2834e4b17023SJohn Marino if (code == SET || code == CLOBBER)
2835e4b17023SJohn Marino {
2836e4b17023SJohn Marino sched_analyze_1 (deps, x, insn);
2837e4b17023SJohn Marino
2838e4b17023SJohn Marino /* Bare clobber insns are used for letting life analysis, reg-stack
2839e4b17023SJohn Marino and others know that a value is dead. Depend on the last call
2840e4b17023SJohn Marino instruction so that reg-stack won't get confused. */
2841e4b17023SJohn Marino if (code == CLOBBER)
2842e4b17023SJohn Marino add_dependence_list (insn, deps->last_function_call, 1,
2843e4b17023SJohn Marino REG_DEP_OUTPUT);
2844e4b17023SJohn Marino }
2845e4b17023SJohn Marino else if (code == PARALLEL)
2846e4b17023SJohn Marino {
2847e4b17023SJohn Marino for (i = XVECLEN (x, 0); i--;)
2848e4b17023SJohn Marino {
2849e4b17023SJohn Marino rtx sub = XVECEXP (x, 0, i);
2850e4b17023SJohn Marino code = GET_CODE (sub);
2851e4b17023SJohn Marino
2852e4b17023SJohn Marino if (code == COND_EXEC)
2853e4b17023SJohn Marino {
2854e4b17023SJohn Marino sched_analyze_2 (deps, COND_EXEC_TEST (sub), insn);
2855e4b17023SJohn Marino sub = COND_EXEC_CODE (sub);
2856e4b17023SJohn Marino code = GET_CODE (sub);
2857e4b17023SJohn Marino }
2858e4b17023SJohn Marino if (code == SET || code == CLOBBER)
2859e4b17023SJohn Marino sched_analyze_1 (deps, sub, insn);
2860e4b17023SJohn Marino else
2861e4b17023SJohn Marino sched_analyze_2 (deps, sub, insn);
2862e4b17023SJohn Marino }
2863e4b17023SJohn Marino }
2864e4b17023SJohn Marino else
2865e4b17023SJohn Marino sched_analyze_2 (deps, x, insn);
2866e4b17023SJohn Marino
2867e4b17023SJohn Marino /* Mark registers CLOBBERED or used by called function. */
2868e4b17023SJohn Marino if (CALL_P (insn))
2869e4b17023SJohn Marino {
2870e4b17023SJohn Marino for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
2871e4b17023SJohn Marino {
2872e4b17023SJohn Marino if (GET_CODE (XEXP (link, 0)) == CLOBBER)
2873e4b17023SJohn Marino sched_analyze_1 (deps, XEXP (link, 0), insn);
2874e4b17023SJohn Marino else
2875e4b17023SJohn Marino sched_analyze_2 (deps, XEXP (link, 0), insn);
2876e4b17023SJohn Marino }
2877e4b17023SJohn Marino /* Don't schedule anything after a tail call, tail call needs
2878e4b17023SJohn Marino to use at least all call-saved registers. */
2879e4b17023SJohn Marino if (SIBLING_CALL_P (insn))
2880e4b17023SJohn Marino reg_pending_barrier = TRUE_BARRIER;
2881e4b17023SJohn Marino else if (find_reg_note (insn, REG_SETJMP, NULL))
2882e4b17023SJohn Marino reg_pending_barrier = MOVE_BARRIER;
2883e4b17023SJohn Marino }
2884e4b17023SJohn Marino
2885e4b17023SJohn Marino if (JUMP_P (insn))
2886e4b17023SJohn Marino {
2887e4b17023SJohn Marino rtx next;
2888e4b17023SJohn Marino next = next_nonnote_nondebug_insn (insn);
2889e4b17023SJohn Marino if (next && BARRIER_P (next))
2890e4b17023SJohn Marino reg_pending_barrier = MOVE_BARRIER;
2891e4b17023SJohn Marino else
2892e4b17023SJohn Marino {
2893e4b17023SJohn Marino rtx pending, pending_mem;
2894e4b17023SJohn Marino
2895e4b17023SJohn Marino if (sched_deps_info->compute_jump_reg_dependencies)
2896e4b17023SJohn Marino {
2897e4b17023SJohn Marino (*sched_deps_info->compute_jump_reg_dependencies)
2898e4b17023SJohn Marino (insn, reg_pending_control_uses);
2899e4b17023SJohn Marino
2900e4b17023SJohn Marino /* Make latency of jump equal to 0 by using anti-dependence. */
2901e4b17023SJohn Marino EXECUTE_IF_SET_IN_REG_SET (reg_pending_control_uses, 0, i, rsi)
2902e4b17023SJohn Marino {
2903e4b17023SJohn Marino struct deps_reg *reg_last = &deps->reg_last[i];
2904e4b17023SJohn Marino add_dependence_list (insn, reg_last->sets, 0, REG_DEP_ANTI);
2905e4b17023SJohn Marino add_dependence_list (insn, reg_last->implicit_sets,
2906e4b17023SJohn Marino 0, REG_DEP_ANTI);
2907e4b17023SJohn Marino add_dependence_list (insn, reg_last->clobbers, 0,
2908e4b17023SJohn Marino REG_DEP_ANTI);
2909e4b17023SJohn Marino }
2910e4b17023SJohn Marino }
2911e4b17023SJohn Marino
2912e4b17023SJohn Marino /* All memory writes and volatile reads must happen before the
2913e4b17023SJohn Marino jump. Non-volatile reads must happen before the jump iff
2914e4b17023SJohn Marino the result is needed by the above register used mask. */
2915e4b17023SJohn Marino
2916e4b17023SJohn Marino pending = deps->pending_write_insns;
2917e4b17023SJohn Marino pending_mem = deps->pending_write_mems;
2918e4b17023SJohn Marino while (pending)
2919e4b17023SJohn Marino {
2920e4b17023SJohn Marino if (! sched_insns_conditions_mutex_p (insn, XEXP (pending, 0)))
2921e4b17023SJohn Marino add_dependence (insn, XEXP (pending, 0), REG_DEP_OUTPUT);
2922e4b17023SJohn Marino pending = XEXP (pending, 1);
2923e4b17023SJohn Marino pending_mem = XEXP (pending_mem, 1);
2924e4b17023SJohn Marino }
2925e4b17023SJohn Marino
2926e4b17023SJohn Marino pending = deps->pending_read_insns;
2927e4b17023SJohn Marino pending_mem = deps->pending_read_mems;
2928e4b17023SJohn Marino while (pending)
2929e4b17023SJohn Marino {
2930e4b17023SJohn Marino if (MEM_VOLATILE_P (XEXP (pending_mem, 0))
2931e4b17023SJohn Marino && ! sched_insns_conditions_mutex_p (insn, XEXP (pending, 0)))
2932e4b17023SJohn Marino add_dependence (insn, XEXP (pending, 0), REG_DEP_OUTPUT);
2933e4b17023SJohn Marino pending = XEXP (pending, 1);
2934e4b17023SJohn Marino pending_mem = XEXP (pending_mem, 1);
2935e4b17023SJohn Marino }
2936e4b17023SJohn Marino
2937e4b17023SJohn Marino add_dependence_list (insn, deps->last_pending_memory_flush, 1,
2938e4b17023SJohn Marino REG_DEP_ANTI);
2939e4b17023SJohn Marino add_dependence_list (insn, deps->pending_jump_insns, 1,
2940e4b17023SJohn Marino REG_DEP_ANTI);
2941e4b17023SJohn Marino }
2942e4b17023SJohn Marino }
2943e4b17023SJohn Marino
2944e4b17023SJohn Marino /* If this instruction can throw an exception, then moving it changes
2945e4b17023SJohn Marino where block boundaries fall. This is mighty confusing elsewhere.
2946e4b17023SJohn Marino Therefore, prevent such an instruction from being moved. Same for
2947e4b17023SJohn Marino non-jump instructions that define block boundaries.
2948e4b17023SJohn Marino ??? Unclear whether this is still necessary in EBB mode. If not,
2949e4b17023SJohn Marino add_branch_dependences should be adjusted for RGN mode instead. */
2950e4b17023SJohn Marino if (((CALL_P (insn) || JUMP_P (insn)) && can_throw_internal (insn))
2951e4b17023SJohn Marino || (NONJUMP_INSN_P (insn) && control_flow_insn_p (insn)))
2952e4b17023SJohn Marino reg_pending_barrier = MOVE_BARRIER;
2953e4b17023SJohn Marino
2954e4b17023SJohn Marino if (sched_pressure_p)
2955e4b17023SJohn Marino {
2956e4b17023SJohn Marino setup_insn_reg_uses (deps, insn);
2957e4b17023SJohn Marino init_insn_reg_pressure_info (insn);
2958e4b17023SJohn Marino }
2959e4b17023SJohn Marino
2960e4b17023SJohn Marino /* Add register dependencies for insn. */
2961e4b17023SJohn Marino if (DEBUG_INSN_P (insn))
2962e4b17023SJohn Marino {
2963e4b17023SJohn Marino rtx prev = deps->last_debug_insn;
2964e4b17023SJohn Marino rtx u;
2965e4b17023SJohn Marino
2966e4b17023SJohn Marino if (!deps->readonly)
2967e4b17023SJohn Marino deps->last_debug_insn = insn;
2968e4b17023SJohn Marino
2969e4b17023SJohn Marino if (prev)
2970e4b17023SJohn Marino add_dependence (insn, prev, REG_DEP_ANTI);
2971e4b17023SJohn Marino
2972e4b17023SJohn Marino add_dependence_list (insn, deps->last_function_call, 1,
2973e4b17023SJohn Marino REG_DEP_ANTI);
2974e4b17023SJohn Marino
2975e4b17023SJohn Marino for (u = deps->last_pending_memory_flush; u; u = XEXP (u, 1))
2976e4b17023SJohn Marino if (!sel_sched_p ())
2977e4b17023SJohn Marino add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
2978e4b17023SJohn Marino
2979e4b17023SJohn Marino EXECUTE_IF_SET_IN_REG_SET (reg_pending_uses, 0, i, rsi)
2980e4b17023SJohn Marino {
2981e4b17023SJohn Marino struct deps_reg *reg_last = &deps->reg_last[i];
2982e4b17023SJohn Marino add_dependence_list (insn, reg_last->sets, 1, REG_DEP_ANTI);
2983e4b17023SJohn Marino /* There's no point in making REG_DEP_CONTROL dependencies for
2984e4b17023SJohn Marino debug insns. */
2985e4b17023SJohn Marino add_dependence_list (insn, reg_last->clobbers, 1, REG_DEP_ANTI);
2986e4b17023SJohn Marino
2987e4b17023SJohn Marino if (!deps->readonly)
2988e4b17023SJohn Marino reg_last->uses = alloc_INSN_LIST (insn, reg_last->uses);
2989e4b17023SJohn Marino }
2990e4b17023SJohn Marino CLEAR_REG_SET (reg_pending_uses);
2991e4b17023SJohn Marino
2992e4b17023SJohn Marino /* Quite often, a debug insn will refer to stuff in the
2993e4b17023SJohn Marino previous instruction, but the reason we want this
2994e4b17023SJohn Marino dependency here is to make sure the scheduler doesn't
2995e4b17023SJohn Marino gratuitously move a debug insn ahead. This could dirty
2996e4b17023SJohn Marino DF flags and cause additional analysis that wouldn't have
2997e4b17023SJohn Marino occurred in compilation without debug insns, and such
2998e4b17023SJohn Marino additional analysis can modify the generated code. */
2999e4b17023SJohn Marino prev = PREV_INSN (insn);
3000e4b17023SJohn Marino
3001e4b17023SJohn Marino if (prev && NONDEBUG_INSN_P (prev))
3002e4b17023SJohn Marino add_dependence (insn, prev, REG_DEP_ANTI);
3003e4b17023SJohn Marino }
3004e4b17023SJohn Marino else
3005e4b17023SJohn Marino {
3006e4b17023SJohn Marino regset_head set_or_clobbered;
3007e4b17023SJohn Marino
3008e4b17023SJohn Marino EXECUTE_IF_SET_IN_REG_SET (reg_pending_uses, 0, i, rsi)
3009e4b17023SJohn Marino {
3010e4b17023SJohn Marino struct deps_reg *reg_last = &deps->reg_last[i];
3011e4b17023SJohn Marino add_dependence_list (insn, reg_last->sets, 0, REG_DEP_TRUE);
3012e4b17023SJohn Marino add_dependence_list (insn, reg_last->implicit_sets, 0, REG_DEP_ANTI);
3013e4b17023SJohn Marino add_dependence_list (insn, reg_last->clobbers, 0, REG_DEP_TRUE);
3014e4b17023SJohn Marino
3015e4b17023SJohn Marino if (!deps->readonly)
3016e4b17023SJohn Marino {
3017e4b17023SJohn Marino reg_last->uses = alloc_INSN_LIST (insn, reg_last->uses);
3018e4b17023SJohn Marino reg_last->uses_length++;
3019e4b17023SJohn Marino }
3020e4b17023SJohn Marino }
3021e4b17023SJohn Marino
3022e4b17023SJohn Marino for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3023e4b17023SJohn Marino if (TEST_HARD_REG_BIT (implicit_reg_pending_uses, i))
3024e4b17023SJohn Marino {
3025e4b17023SJohn Marino struct deps_reg *reg_last = &deps->reg_last[i];
3026e4b17023SJohn Marino add_dependence_list (insn, reg_last->sets, 0, REG_DEP_TRUE);
3027e4b17023SJohn Marino add_dependence_list (insn, reg_last->implicit_sets, 0,
3028e4b17023SJohn Marino REG_DEP_ANTI);
3029e4b17023SJohn Marino add_dependence_list (insn, reg_last->clobbers, 0, REG_DEP_TRUE);
3030e4b17023SJohn Marino
3031e4b17023SJohn Marino if (!deps->readonly)
3032e4b17023SJohn Marino {
3033e4b17023SJohn Marino reg_last->uses = alloc_INSN_LIST (insn, reg_last->uses);
3034e4b17023SJohn Marino reg_last->uses_length++;
3035e4b17023SJohn Marino }
3036e4b17023SJohn Marino }
3037e4b17023SJohn Marino
3038e4b17023SJohn Marino if (targetm.sched.exposed_pipeline)
3039e4b17023SJohn Marino {
3040e4b17023SJohn Marino INIT_REG_SET (&set_or_clobbered);
3041e4b17023SJohn Marino bitmap_ior (&set_or_clobbered, reg_pending_clobbers,
3042e4b17023SJohn Marino reg_pending_sets);
3043e4b17023SJohn Marino EXECUTE_IF_SET_IN_REG_SET (&set_or_clobbered, 0, i, rsi)
3044e4b17023SJohn Marino {
3045e4b17023SJohn Marino struct deps_reg *reg_last = &deps->reg_last[i];
3046e4b17023SJohn Marino rtx list;
3047e4b17023SJohn Marino for (list = reg_last->uses; list; list = XEXP (list, 1))
3048e4b17023SJohn Marino {
3049e4b17023SJohn Marino rtx other = XEXP (list, 0);
3050e4b17023SJohn Marino if (INSN_CACHED_COND (other) != const_true_rtx
3051e4b17023SJohn Marino && refers_to_regno_p (i, i + 1, INSN_CACHED_COND (other), NULL))
3052e4b17023SJohn Marino INSN_CACHED_COND (other) = const_true_rtx;
3053e4b17023SJohn Marino }
3054e4b17023SJohn Marino }
3055e4b17023SJohn Marino }
3056e4b17023SJohn Marino
3057e4b17023SJohn Marino /* If the current insn is conditional, we can't free any
3058e4b17023SJohn Marino of the lists. */
3059e4b17023SJohn Marino if (sched_has_condition_p (insn))
3060e4b17023SJohn Marino {
3061e4b17023SJohn Marino EXECUTE_IF_SET_IN_REG_SET (reg_pending_clobbers, 0, i, rsi)
3062e4b17023SJohn Marino {
3063e4b17023SJohn Marino struct deps_reg *reg_last = &deps->reg_last[i];
3064e4b17023SJohn Marino add_dependence_list (insn, reg_last->sets, 0, REG_DEP_OUTPUT);
3065e4b17023SJohn Marino add_dependence_list (insn, reg_last->implicit_sets, 0,
3066e4b17023SJohn Marino REG_DEP_ANTI);
3067e4b17023SJohn Marino add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI);
3068e4b17023SJohn Marino add_dependence_list (insn, reg_last->control_uses, 0,
3069e4b17023SJohn Marino REG_DEP_CONTROL);
3070e4b17023SJohn Marino
3071e4b17023SJohn Marino if (!deps->readonly)
3072e4b17023SJohn Marino {
3073e4b17023SJohn Marino reg_last->clobbers
3074e4b17023SJohn Marino = alloc_INSN_LIST (insn, reg_last->clobbers);
3075e4b17023SJohn Marino reg_last->clobbers_length++;
3076e4b17023SJohn Marino }
3077e4b17023SJohn Marino }
3078e4b17023SJohn Marino EXECUTE_IF_SET_IN_REG_SET (reg_pending_sets, 0, i, rsi)
3079e4b17023SJohn Marino {
3080e4b17023SJohn Marino struct deps_reg *reg_last = &deps->reg_last[i];
3081e4b17023SJohn Marino add_dependence_list (insn, reg_last->sets, 0, REG_DEP_OUTPUT);
3082e4b17023SJohn Marino add_dependence_list (insn, reg_last->implicit_sets, 0,
3083e4b17023SJohn Marino REG_DEP_ANTI);
3084e4b17023SJohn Marino add_dependence_list (insn, reg_last->clobbers, 0, REG_DEP_OUTPUT);
3085e4b17023SJohn Marino add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI);
3086e4b17023SJohn Marino add_dependence_list (insn, reg_last->control_uses, 0,
3087e4b17023SJohn Marino REG_DEP_CONTROL);
3088e4b17023SJohn Marino
3089e4b17023SJohn Marino if (!deps->readonly)
3090e4b17023SJohn Marino reg_last->sets = alloc_INSN_LIST (insn, reg_last->sets);
3091e4b17023SJohn Marino }
3092e4b17023SJohn Marino }
3093e4b17023SJohn Marino else
3094e4b17023SJohn Marino {
3095e4b17023SJohn Marino EXECUTE_IF_SET_IN_REG_SET (reg_pending_clobbers, 0, i, rsi)
3096e4b17023SJohn Marino {
3097e4b17023SJohn Marino struct deps_reg *reg_last = &deps->reg_last[i];
3098e4b17023SJohn Marino if (reg_last->uses_length > MAX_PENDING_LIST_LENGTH
3099e4b17023SJohn Marino || reg_last->clobbers_length > MAX_PENDING_LIST_LENGTH)
3100e4b17023SJohn Marino {
3101e4b17023SJohn Marino add_dependence_list_and_free (deps, insn, ®_last->sets, 0,
3102e4b17023SJohn Marino REG_DEP_OUTPUT);
3103e4b17023SJohn Marino add_dependence_list_and_free (deps, insn,
3104e4b17023SJohn Marino ®_last->implicit_sets, 0,
3105e4b17023SJohn Marino REG_DEP_ANTI);
3106e4b17023SJohn Marino add_dependence_list_and_free (deps, insn, ®_last->uses, 0,
3107e4b17023SJohn Marino REG_DEP_ANTI);
3108e4b17023SJohn Marino add_dependence_list_and_free (deps, insn,
3109e4b17023SJohn Marino ®_last->control_uses, 0,
3110e4b17023SJohn Marino REG_DEP_ANTI);
3111e4b17023SJohn Marino add_dependence_list_and_free
3112e4b17023SJohn Marino (deps, insn, ®_last->clobbers, 0, REG_DEP_OUTPUT);
3113e4b17023SJohn Marino
3114e4b17023SJohn Marino if (!deps->readonly)
3115e4b17023SJohn Marino {
3116e4b17023SJohn Marino reg_last->sets = alloc_INSN_LIST (insn, reg_last->sets);
3117e4b17023SJohn Marino reg_last->clobbers_length = 0;
3118e4b17023SJohn Marino reg_last->uses_length = 0;
3119e4b17023SJohn Marino }
3120e4b17023SJohn Marino }
3121e4b17023SJohn Marino else
3122e4b17023SJohn Marino {
3123e4b17023SJohn Marino add_dependence_list (insn, reg_last->sets, 0, REG_DEP_OUTPUT);
3124e4b17023SJohn Marino add_dependence_list (insn, reg_last->implicit_sets, 0,
3125e4b17023SJohn Marino REG_DEP_ANTI);
3126e4b17023SJohn Marino add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI);
3127e4b17023SJohn Marino add_dependence_list (insn, reg_last->control_uses, 0,
3128e4b17023SJohn Marino REG_DEP_CONTROL);
3129e4b17023SJohn Marino }
3130e4b17023SJohn Marino
3131e4b17023SJohn Marino if (!deps->readonly)
3132e4b17023SJohn Marino {
3133e4b17023SJohn Marino reg_last->clobbers_length++;
3134e4b17023SJohn Marino reg_last->clobbers
3135e4b17023SJohn Marino = alloc_INSN_LIST (insn, reg_last->clobbers);
3136e4b17023SJohn Marino }
3137e4b17023SJohn Marino }
3138e4b17023SJohn Marino EXECUTE_IF_SET_IN_REG_SET (reg_pending_sets, 0, i, rsi)
3139e4b17023SJohn Marino {
3140e4b17023SJohn Marino struct deps_reg *reg_last = &deps->reg_last[i];
3141e4b17023SJohn Marino
3142e4b17023SJohn Marino add_dependence_list_and_free (deps, insn, ®_last->sets, 0,
3143e4b17023SJohn Marino REG_DEP_OUTPUT);
3144e4b17023SJohn Marino add_dependence_list_and_free (deps, insn,
3145e4b17023SJohn Marino ®_last->implicit_sets,
3146e4b17023SJohn Marino 0, REG_DEP_ANTI);
3147e4b17023SJohn Marino add_dependence_list_and_free (deps, insn, ®_last->clobbers, 0,
3148e4b17023SJohn Marino REG_DEP_OUTPUT);
3149e4b17023SJohn Marino add_dependence_list_and_free (deps, insn, ®_last->uses, 0,
3150e4b17023SJohn Marino REG_DEP_ANTI);
3151e4b17023SJohn Marino add_dependence_list (insn, reg_last->control_uses, 0,
3152e4b17023SJohn Marino REG_DEP_CONTROL);
3153e4b17023SJohn Marino
3154e4b17023SJohn Marino if (!deps->readonly)
3155e4b17023SJohn Marino {
3156e4b17023SJohn Marino reg_last->sets = alloc_INSN_LIST (insn, reg_last->sets);
3157e4b17023SJohn Marino reg_last->uses_length = 0;
3158e4b17023SJohn Marino reg_last->clobbers_length = 0;
3159e4b17023SJohn Marino }
3160e4b17023SJohn Marino }
3161e4b17023SJohn Marino }
3162e4b17023SJohn Marino if (!deps->readonly)
3163e4b17023SJohn Marino {
3164e4b17023SJohn Marino EXECUTE_IF_SET_IN_REG_SET (reg_pending_control_uses, 0, i, rsi)
3165e4b17023SJohn Marino {
3166e4b17023SJohn Marino struct deps_reg *reg_last = &deps->reg_last[i];
3167e4b17023SJohn Marino reg_last->control_uses
3168e4b17023SJohn Marino = alloc_INSN_LIST (insn, reg_last->control_uses);
3169e4b17023SJohn Marino }
3170e4b17023SJohn Marino }
3171e4b17023SJohn Marino }
3172e4b17023SJohn Marino
3173e4b17023SJohn Marino for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3174e4b17023SJohn Marino if (TEST_HARD_REG_BIT (implicit_reg_pending_clobbers, i))
3175e4b17023SJohn Marino {
3176e4b17023SJohn Marino struct deps_reg *reg_last = &deps->reg_last[i];
3177e4b17023SJohn Marino add_dependence_list (insn, reg_last->sets, 0, REG_DEP_ANTI);
3178e4b17023SJohn Marino add_dependence_list (insn, reg_last->clobbers, 0, REG_DEP_ANTI);
3179e4b17023SJohn Marino add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI);
3180e4b17023SJohn Marino add_dependence_list (insn, reg_last->control_uses, 0, REG_DEP_ANTI);
3181e4b17023SJohn Marino
3182e4b17023SJohn Marino if (!deps->readonly)
3183e4b17023SJohn Marino reg_last->implicit_sets
3184e4b17023SJohn Marino = alloc_INSN_LIST (insn, reg_last->implicit_sets);
3185e4b17023SJohn Marino }
3186e4b17023SJohn Marino
3187e4b17023SJohn Marino if (!deps->readonly)
3188e4b17023SJohn Marino {
3189e4b17023SJohn Marino IOR_REG_SET (&deps->reg_last_in_use, reg_pending_uses);
3190e4b17023SJohn Marino IOR_REG_SET (&deps->reg_last_in_use, reg_pending_clobbers);
3191e4b17023SJohn Marino IOR_REG_SET (&deps->reg_last_in_use, reg_pending_sets);
3192e4b17023SJohn Marino for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3193e4b17023SJohn Marino if (TEST_HARD_REG_BIT (implicit_reg_pending_uses, i)
3194e4b17023SJohn Marino || TEST_HARD_REG_BIT (implicit_reg_pending_clobbers, i))
3195e4b17023SJohn Marino SET_REGNO_REG_SET (&deps->reg_last_in_use, i);
3196e4b17023SJohn Marino
3197e4b17023SJohn Marino /* Set up the pending barrier found. */
3198e4b17023SJohn Marino deps->last_reg_pending_barrier = reg_pending_barrier;
3199e4b17023SJohn Marino }
3200e4b17023SJohn Marino
3201e4b17023SJohn Marino CLEAR_REG_SET (reg_pending_uses);
3202e4b17023SJohn Marino CLEAR_REG_SET (reg_pending_clobbers);
3203e4b17023SJohn Marino CLEAR_REG_SET (reg_pending_sets);
3204e4b17023SJohn Marino CLEAR_REG_SET (reg_pending_control_uses);
3205e4b17023SJohn Marino CLEAR_HARD_REG_SET (implicit_reg_pending_clobbers);
3206e4b17023SJohn Marino CLEAR_HARD_REG_SET (implicit_reg_pending_uses);
3207e4b17023SJohn Marino
3208e4b17023SJohn Marino /* Add dependencies if a scheduling barrier was found. */
3209e4b17023SJohn Marino if (reg_pending_barrier)
3210e4b17023SJohn Marino {
3211e4b17023SJohn Marino /* In the case of barrier the most added dependencies are not
3212e4b17023SJohn Marino real, so we use anti-dependence here. */
3213e4b17023SJohn Marino if (sched_has_condition_p (insn))
3214e4b17023SJohn Marino {
3215e4b17023SJohn Marino EXECUTE_IF_SET_IN_REG_SET (&deps->reg_last_in_use, 0, i, rsi)
3216e4b17023SJohn Marino {
3217e4b17023SJohn Marino struct deps_reg *reg_last = &deps->reg_last[i];
3218e4b17023SJohn Marino add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI);
3219e4b17023SJohn Marino add_dependence_list (insn, reg_last->sets, 0,
3220e4b17023SJohn Marino reg_pending_barrier == TRUE_BARRIER
3221e4b17023SJohn Marino ? REG_DEP_TRUE : REG_DEP_ANTI);
3222e4b17023SJohn Marino add_dependence_list (insn, reg_last->implicit_sets, 0,
3223e4b17023SJohn Marino REG_DEP_ANTI);
3224e4b17023SJohn Marino add_dependence_list (insn, reg_last->clobbers, 0,
3225e4b17023SJohn Marino reg_pending_barrier == TRUE_BARRIER
3226e4b17023SJohn Marino ? REG_DEP_TRUE : REG_DEP_ANTI);
3227e4b17023SJohn Marino }
3228e4b17023SJohn Marino }
3229e4b17023SJohn Marino else
3230e4b17023SJohn Marino {
3231e4b17023SJohn Marino EXECUTE_IF_SET_IN_REG_SET (&deps->reg_last_in_use, 0, i, rsi)
3232e4b17023SJohn Marino {
3233e4b17023SJohn Marino struct deps_reg *reg_last = &deps->reg_last[i];
3234e4b17023SJohn Marino add_dependence_list_and_free (deps, insn, ®_last->uses, 0,
3235e4b17023SJohn Marino REG_DEP_ANTI);
3236e4b17023SJohn Marino add_dependence_list_and_free (deps, insn,
3237e4b17023SJohn Marino ®_last->control_uses, 0,
3238e4b17023SJohn Marino REG_DEP_CONTROL);
3239e4b17023SJohn Marino add_dependence_list_and_free (deps, insn, ®_last->sets, 0,
3240e4b17023SJohn Marino reg_pending_barrier == TRUE_BARRIER
3241e4b17023SJohn Marino ? REG_DEP_TRUE : REG_DEP_ANTI);
3242e4b17023SJohn Marino add_dependence_list_and_free (deps, insn,
3243e4b17023SJohn Marino ®_last->implicit_sets, 0,
3244e4b17023SJohn Marino REG_DEP_ANTI);
3245e4b17023SJohn Marino add_dependence_list_and_free (deps, insn, ®_last->clobbers, 0,
3246e4b17023SJohn Marino reg_pending_barrier == TRUE_BARRIER
3247e4b17023SJohn Marino ? REG_DEP_TRUE : REG_DEP_ANTI);
3248e4b17023SJohn Marino
3249e4b17023SJohn Marino if (!deps->readonly)
3250e4b17023SJohn Marino {
3251e4b17023SJohn Marino reg_last->uses_length = 0;
3252e4b17023SJohn Marino reg_last->clobbers_length = 0;
3253e4b17023SJohn Marino }
3254e4b17023SJohn Marino }
3255e4b17023SJohn Marino }
3256e4b17023SJohn Marino
3257e4b17023SJohn Marino if (!deps->readonly)
3258e4b17023SJohn Marino for (i = 0; i < (unsigned)deps->max_reg; i++)
3259e4b17023SJohn Marino {
3260e4b17023SJohn Marino struct deps_reg *reg_last = &deps->reg_last[i];
3261e4b17023SJohn Marino reg_last->sets = alloc_INSN_LIST (insn, reg_last->sets);
3262e4b17023SJohn Marino SET_REGNO_REG_SET (&deps->reg_last_in_use, i);
3263e4b17023SJohn Marino }
3264e4b17023SJohn Marino
3265*95d28233SJohn Marino /* Don't flush pending lists on speculative checks for
3266*95d28233SJohn Marino selective scheduling. */
3267*95d28233SJohn Marino if (!sel_sched_p () || !sel_insn_is_speculation_check (insn))
3268e4b17023SJohn Marino flush_pending_lists (deps, insn, true, true);
3269e4b17023SJohn Marino
3270e4b17023SJohn Marino reg_pending_barrier = NOT_A_BARRIER;
3271e4b17023SJohn Marino }
3272e4b17023SJohn Marino
3273e4b17023SJohn Marino /* If a post-call group is still open, see if it should remain so.
3274e4b17023SJohn Marino This insn must be a simple move of a hard reg to a pseudo or
3275e4b17023SJohn Marino vice-versa.
3276e4b17023SJohn Marino
3277e4b17023SJohn Marino We must avoid moving these insns for correctness on targets
3278e4b17023SJohn Marino with small register classes, and for special registers like
3279e4b17023SJohn Marino PIC_OFFSET_TABLE_REGNUM. For simplicity, extend this to all
3280e4b17023SJohn Marino hard regs for all targets. */
3281e4b17023SJohn Marino
3282e4b17023SJohn Marino if (deps->in_post_call_group_p)
3283e4b17023SJohn Marino {
3284e4b17023SJohn Marino rtx tmp, set = single_set (insn);
3285e4b17023SJohn Marino int src_regno, dest_regno;
3286e4b17023SJohn Marino
3287e4b17023SJohn Marino if (set == NULL)
3288e4b17023SJohn Marino {
3289e4b17023SJohn Marino if (DEBUG_INSN_P (insn))
3290e4b17023SJohn Marino /* We don't want to mark debug insns as part of the same
3291e4b17023SJohn Marino sched group. We know they really aren't, but if we use
3292e4b17023SJohn Marino debug insns to tell that a call group is over, we'll
3293e4b17023SJohn Marino get different code if debug insns are not there and
3294e4b17023SJohn Marino instructions that follow seem like they should be part
3295e4b17023SJohn Marino of the call group.
3296e4b17023SJohn Marino
3297e4b17023SJohn Marino Also, if we did, fixup_sched_groups() would move the
3298e4b17023SJohn Marino deps of the debug insn to the call insn, modifying
3299e4b17023SJohn Marino non-debug post-dependency counts of the debug insn
3300e4b17023SJohn Marino dependencies and otherwise messing with the scheduling
3301e4b17023SJohn Marino order.
3302e4b17023SJohn Marino
3303e4b17023SJohn Marino Instead, let such debug insns be scheduled freely, but
3304e4b17023SJohn Marino keep the call group open in case there are insns that
3305e4b17023SJohn Marino should be part of it afterwards. Since we grant debug
3306e4b17023SJohn Marino insns higher priority than even sched group insns, it
3307e4b17023SJohn Marino will all turn out all right. */
3308e4b17023SJohn Marino goto debug_dont_end_call_group;
3309e4b17023SJohn Marino else
3310e4b17023SJohn Marino goto end_call_group;
3311e4b17023SJohn Marino }
3312e4b17023SJohn Marino
3313e4b17023SJohn Marino tmp = SET_DEST (set);
3314e4b17023SJohn Marino if (GET_CODE (tmp) == SUBREG)
3315e4b17023SJohn Marino tmp = SUBREG_REG (tmp);
3316e4b17023SJohn Marino if (REG_P (tmp))
3317e4b17023SJohn Marino dest_regno = REGNO (tmp);
3318e4b17023SJohn Marino else
3319e4b17023SJohn Marino goto end_call_group;
3320e4b17023SJohn Marino
3321e4b17023SJohn Marino tmp = SET_SRC (set);
3322e4b17023SJohn Marino if (GET_CODE (tmp) == SUBREG)
3323e4b17023SJohn Marino tmp = SUBREG_REG (tmp);
3324e4b17023SJohn Marino if ((GET_CODE (tmp) == PLUS
3325e4b17023SJohn Marino || GET_CODE (tmp) == MINUS)
3326e4b17023SJohn Marino && REG_P (XEXP (tmp, 0))
3327e4b17023SJohn Marino && REGNO (XEXP (tmp, 0)) == STACK_POINTER_REGNUM
3328e4b17023SJohn Marino && dest_regno == STACK_POINTER_REGNUM)
3329e4b17023SJohn Marino src_regno = STACK_POINTER_REGNUM;
3330e4b17023SJohn Marino else if (REG_P (tmp))
3331e4b17023SJohn Marino src_regno = REGNO (tmp);
3332e4b17023SJohn Marino else
3333e4b17023SJohn Marino goto end_call_group;
3334e4b17023SJohn Marino
3335e4b17023SJohn Marino if (src_regno < FIRST_PSEUDO_REGISTER
3336e4b17023SJohn Marino || dest_regno < FIRST_PSEUDO_REGISTER)
3337e4b17023SJohn Marino {
3338e4b17023SJohn Marino if (!deps->readonly
3339e4b17023SJohn Marino && deps->in_post_call_group_p == post_call_initial)
3340e4b17023SJohn Marino deps->in_post_call_group_p = post_call;
3341e4b17023SJohn Marino
3342e4b17023SJohn Marino if (!sel_sched_p () || sched_emulate_haifa_p)
3343e4b17023SJohn Marino {
3344e4b17023SJohn Marino SCHED_GROUP_P (insn) = 1;
3345e4b17023SJohn Marino CANT_MOVE (insn) = 1;
3346e4b17023SJohn Marino }
3347e4b17023SJohn Marino }
3348e4b17023SJohn Marino else
3349e4b17023SJohn Marino {
3350e4b17023SJohn Marino end_call_group:
3351e4b17023SJohn Marino if (!deps->readonly)
3352e4b17023SJohn Marino deps->in_post_call_group_p = not_post_call;
3353e4b17023SJohn Marino }
3354e4b17023SJohn Marino }
3355e4b17023SJohn Marino
3356e4b17023SJohn Marino debug_dont_end_call_group:
3357e4b17023SJohn Marino if ((current_sched_info->flags & DO_SPECULATION)
3358e4b17023SJohn Marino && !sched_insn_is_legitimate_for_speculation_p (insn, 0))
3359e4b17023SJohn Marino /* INSN has an internal dependency (e.g. r14 = [r14]) and thus cannot
3360e4b17023SJohn Marino be speculated. */
3361e4b17023SJohn Marino {
3362e4b17023SJohn Marino if (sel_sched_p ())
3363e4b17023SJohn Marino sel_mark_hard_insn (insn);
3364e4b17023SJohn Marino else
3365e4b17023SJohn Marino {
3366e4b17023SJohn Marino sd_iterator_def sd_it;
3367e4b17023SJohn Marino dep_t dep;
3368e4b17023SJohn Marino
3369e4b17023SJohn Marino for (sd_it = sd_iterator_start (insn, SD_LIST_SPEC_BACK);
3370e4b17023SJohn Marino sd_iterator_cond (&sd_it, &dep);)
3371e4b17023SJohn Marino change_spec_dep_to_hard (sd_it);
3372e4b17023SJohn Marino }
3373e4b17023SJohn Marino }
3374e4b17023SJohn Marino }
3375e4b17023SJohn Marino
3376e4b17023SJohn Marino /* Return TRUE if INSN might not always return normally (e.g. call exit,
3377e4b17023SJohn Marino longjmp, loop forever, ...). */
3378e4b17023SJohn Marino static bool
call_may_noreturn_p(rtx insn)3379e4b17023SJohn Marino call_may_noreturn_p (rtx insn)
3380e4b17023SJohn Marino {
3381e4b17023SJohn Marino rtx call;
3382e4b17023SJohn Marino
3383e4b17023SJohn Marino /* const or pure calls that aren't looping will always return. */
3384e4b17023SJohn Marino if (RTL_CONST_OR_PURE_CALL_P (insn)
3385e4b17023SJohn Marino && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn))
3386e4b17023SJohn Marino return false;
3387e4b17023SJohn Marino
3388e4b17023SJohn Marino call = PATTERN (insn);
3389e4b17023SJohn Marino if (GET_CODE (call) == PARALLEL)
3390e4b17023SJohn Marino call = XVECEXP (call, 0, 0);
3391e4b17023SJohn Marino if (GET_CODE (call) == SET)
3392e4b17023SJohn Marino call = SET_SRC (call);
3393e4b17023SJohn Marino if (GET_CODE (call) == CALL
3394e4b17023SJohn Marino && MEM_P (XEXP (call, 0))
3395e4b17023SJohn Marino && GET_CODE (XEXP (XEXP (call, 0), 0)) == SYMBOL_REF)
3396e4b17023SJohn Marino {
3397e4b17023SJohn Marino rtx symbol = XEXP (XEXP (call, 0), 0);
3398e4b17023SJohn Marino if (SYMBOL_REF_DECL (symbol)
3399e4b17023SJohn Marino && TREE_CODE (SYMBOL_REF_DECL (symbol)) == FUNCTION_DECL)
3400e4b17023SJohn Marino {
3401e4b17023SJohn Marino if (DECL_BUILT_IN_CLASS (SYMBOL_REF_DECL (symbol))
3402e4b17023SJohn Marino == BUILT_IN_NORMAL)
3403e4b17023SJohn Marino switch (DECL_FUNCTION_CODE (SYMBOL_REF_DECL (symbol)))
3404e4b17023SJohn Marino {
3405e4b17023SJohn Marino case BUILT_IN_BCMP:
3406e4b17023SJohn Marino case BUILT_IN_BCOPY:
3407e4b17023SJohn Marino case BUILT_IN_BZERO:
3408e4b17023SJohn Marino case BUILT_IN_INDEX:
3409e4b17023SJohn Marino case BUILT_IN_MEMCHR:
3410e4b17023SJohn Marino case BUILT_IN_MEMCMP:
3411e4b17023SJohn Marino case BUILT_IN_MEMCPY:
3412e4b17023SJohn Marino case BUILT_IN_MEMMOVE:
3413e4b17023SJohn Marino case BUILT_IN_MEMPCPY:
3414e4b17023SJohn Marino case BUILT_IN_MEMSET:
3415e4b17023SJohn Marino case BUILT_IN_RINDEX:
3416e4b17023SJohn Marino case BUILT_IN_STPCPY:
3417e4b17023SJohn Marino case BUILT_IN_STPNCPY:
3418e4b17023SJohn Marino case BUILT_IN_STRCAT:
3419e4b17023SJohn Marino case BUILT_IN_STRCHR:
3420e4b17023SJohn Marino case BUILT_IN_STRCMP:
3421e4b17023SJohn Marino case BUILT_IN_STRCPY:
3422e4b17023SJohn Marino case BUILT_IN_STRCSPN:
3423e4b17023SJohn Marino case BUILT_IN_STRLEN:
3424e4b17023SJohn Marino case BUILT_IN_STRNCAT:
3425e4b17023SJohn Marino case BUILT_IN_STRNCMP:
3426e4b17023SJohn Marino case BUILT_IN_STRNCPY:
3427e4b17023SJohn Marino case BUILT_IN_STRPBRK:
3428e4b17023SJohn Marino case BUILT_IN_STRRCHR:
3429e4b17023SJohn Marino case BUILT_IN_STRSPN:
3430e4b17023SJohn Marino case BUILT_IN_STRSTR:
3431e4b17023SJohn Marino /* Assume certain string/memory builtins always return. */
3432e4b17023SJohn Marino return false;
3433e4b17023SJohn Marino default:
3434e4b17023SJohn Marino break;
3435e4b17023SJohn Marino }
3436e4b17023SJohn Marino }
3437e4b17023SJohn Marino }
3438e4b17023SJohn Marino
3439e4b17023SJohn Marino /* For all other calls assume that they might not always return. */
3440e4b17023SJohn Marino return true;
3441e4b17023SJohn Marino }
3442e4b17023SJohn Marino
3443e4b17023SJohn Marino /* Analyze INSN with DEPS as a context. */
3444e4b17023SJohn Marino void
deps_analyze_insn(struct deps_desc * deps,rtx insn)3445e4b17023SJohn Marino deps_analyze_insn (struct deps_desc *deps, rtx insn)
3446e4b17023SJohn Marino {
3447e4b17023SJohn Marino if (sched_deps_info->start_insn)
3448e4b17023SJohn Marino sched_deps_info->start_insn (insn);
3449e4b17023SJohn Marino
3450e4b17023SJohn Marino /* Record the condition for this insn. */
3451e4b17023SJohn Marino if (NONDEBUG_INSN_P (insn))
3452e4b17023SJohn Marino {
3453e4b17023SJohn Marino rtx t;
3454e4b17023SJohn Marino sched_get_condition_with_rev (insn, NULL);
3455e4b17023SJohn Marino t = INSN_CACHED_COND (insn);
3456e4b17023SJohn Marino INSN_COND_DEPS (insn) = NULL_RTX;
3457e4b17023SJohn Marino if (reload_completed
3458e4b17023SJohn Marino && (current_sched_info->flags & DO_PREDICATION)
3459e4b17023SJohn Marino && COMPARISON_P (t)
3460e4b17023SJohn Marino && REG_P (XEXP (t, 0))
3461e4b17023SJohn Marino && CONSTANT_P (XEXP (t, 1)))
3462e4b17023SJohn Marino {
3463e4b17023SJohn Marino unsigned int regno;
3464e4b17023SJohn Marino int nregs;
3465e4b17023SJohn Marino t = XEXP (t, 0);
3466e4b17023SJohn Marino regno = REGNO (t);
3467e4b17023SJohn Marino nregs = hard_regno_nregs[regno][GET_MODE (t)];
3468e4b17023SJohn Marino t = NULL_RTX;
3469e4b17023SJohn Marino while (nregs-- > 0)
3470e4b17023SJohn Marino {
3471e4b17023SJohn Marino struct deps_reg *reg_last = &deps->reg_last[regno + nregs];
3472e4b17023SJohn Marino t = concat_INSN_LIST (reg_last->sets, t);
3473e4b17023SJohn Marino t = concat_INSN_LIST (reg_last->clobbers, t);
3474e4b17023SJohn Marino t = concat_INSN_LIST (reg_last->implicit_sets, t);
3475e4b17023SJohn Marino }
3476e4b17023SJohn Marino INSN_COND_DEPS (insn) = t;
3477e4b17023SJohn Marino }
3478e4b17023SJohn Marino }
3479e4b17023SJohn Marino
3480e4b17023SJohn Marino if (JUMP_P (insn))
3481e4b17023SJohn Marino {
3482e4b17023SJohn Marino /* Make each JUMP_INSN (but not a speculative check)
3483e4b17023SJohn Marino a scheduling barrier for memory references. */
3484e4b17023SJohn Marino if (!deps->readonly
3485e4b17023SJohn Marino && !(sel_sched_p ()
3486e4b17023SJohn Marino && sel_insn_is_speculation_check (insn)))
3487e4b17023SJohn Marino {
3488e4b17023SJohn Marino /* Keep the list a reasonable size. */
3489e4b17023SJohn Marino if (deps->pending_flush_length++ > MAX_PENDING_LIST_LENGTH)
3490e4b17023SJohn Marino flush_pending_lists (deps, insn, true, true);
3491e4b17023SJohn Marino else
3492e4b17023SJohn Marino deps->pending_jump_insns
3493e4b17023SJohn Marino = alloc_INSN_LIST (insn, deps->pending_jump_insns);
3494e4b17023SJohn Marino }
3495e4b17023SJohn Marino
3496e4b17023SJohn Marino /* For each insn which shouldn't cross a jump, add a dependence. */
3497e4b17023SJohn Marino add_dependence_list_and_free (deps, insn,
3498e4b17023SJohn Marino &deps->sched_before_next_jump, 1,
3499e4b17023SJohn Marino REG_DEP_ANTI);
3500e4b17023SJohn Marino
3501e4b17023SJohn Marino sched_analyze_insn (deps, PATTERN (insn), insn);
3502e4b17023SJohn Marino }
3503e4b17023SJohn Marino else if (NONJUMP_INSN_P (insn) || DEBUG_INSN_P (insn))
3504e4b17023SJohn Marino {
3505e4b17023SJohn Marino sched_analyze_insn (deps, PATTERN (insn), insn);
3506e4b17023SJohn Marino }
3507e4b17023SJohn Marino else if (CALL_P (insn))
3508e4b17023SJohn Marino {
3509e4b17023SJohn Marino int i;
3510e4b17023SJohn Marino
3511e4b17023SJohn Marino CANT_MOVE (insn) = 1;
3512e4b17023SJohn Marino
3513e4b17023SJohn Marino if (find_reg_note (insn, REG_SETJMP, NULL))
3514e4b17023SJohn Marino {
3515e4b17023SJohn Marino /* This is setjmp. Assume that all registers, not just
3516e4b17023SJohn Marino hard registers, may be clobbered by this call. */
3517e4b17023SJohn Marino reg_pending_barrier = MOVE_BARRIER;
3518e4b17023SJohn Marino }
3519e4b17023SJohn Marino else
3520e4b17023SJohn Marino {
3521e4b17023SJohn Marino for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3522e4b17023SJohn Marino /* A call may read and modify global register variables. */
3523e4b17023SJohn Marino if (global_regs[i])
3524e4b17023SJohn Marino {
3525e4b17023SJohn Marino SET_REGNO_REG_SET (reg_pending_sets, i);
3526e4b17023SJohn Marino SET_HARD_REG_BIT (implicit_reg_pending_uses, i);
3527e4b17023SJohn Marino }
3528e4b17023SJohn Marino /* Other call-clobbered hard regs may be clobbered.
3529e4b17023SJohn Marino Since we only have a choice between 'might be clobbered'
3530e4b17023SJohn Marino and 'definitely not clobbered', we must include all
3531e4b17023SJohn Marino partly call-clobbered registers here. */
3532e4b17023SJohn Marino else if (HARD_REGNO_CALL_PART_CLOBBERED (i, reg_raw_mode[i])
3533e4b17023SJohn Marino || TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
3534e4b17023SJohn Marino SET_REGNO_REG_SET (reg_pending_clobbers, i);
3535e4b17023SJohn Marino /* We don't know what set of fixed registers might be used
3536e4b17023SJohn Marino by the function, but it is certain that the stack pointer
3537e4b17023SJohn Marino is among them, but be conservative. */
3538e4b17023SJohn Marino else if (fixed_regs[i])
3539e4b17023SJohn Marino SET_HARD_REG_BIT (implicit_reg_pending_uses, i);
3540e4b17023SJohn Marino /* The frame pointer is normally not used by the function
3541e4b17023SJohn Marino itself, but by the debugger. */
3542e4b17023SJohn Marino /* ??? MIPS o32 is an exception. It uses the frame pointer
3543e4b17023SJohn Marino in the macro expansion of jal but does not represent this
3544e4b17023SJohn Marino fact in the call_insn rtl. */
3545e4b17023SJohn Marino else if (i == FRAME_POINTER_REGNUM
3546e4b17023SJohn Marino || (i == HARD_FRAME_POINTER_REGNUM
3547e4b17023SJohn Marino && (! reload_completed || frame_pointer_needed)))
3548e4b17023SJohn Marino SET_HARD_REG_BIT (implicit_reg_pending_uses, i);
3549e4b17023SJohn Marino }
3550e4b17023SJohn Marino
3551e4b17023SJohn Marino /* For each insn which shouldn't cross a call, add a dependence
3552e4b17023SJohn Marino between that insn and this call insn. */
3553e4b17023SJohn Marino add_dependence_list_and_free (deps, insn,
3554e4b17023SJohn Marino &deps->sched_before_next_call, 1,
3555e4b17023SJohn Marino REG_DEP_ANTI);
3556e4b17023SJohn Marino
3557e4b17023SJohn Marino sched_analyze_insn (deps, PATTERN (insn), insn);
3558e4b17023SJohn Marino
3559e4b17023SJohn Marino /* If CALL would be in a sched group, then this will violate
3560e4b17023SJohn Marino convention that sched group insns have dependencies only on the
3561e4b17023SJohn Marino previous instruction.
3562e4b17023SJohn Marino
3563e4b17023SJohn Marino Of course one can say: "Hey! What about head of the sched group?"
3564e4b17023SJohn Marino And I will answer: "Basic principles (one dep per insn) are always
3565e4b17023SJohn Marino the same." */
3566e4b17023SJohn Marino gcc_assert (!SCHED_GROUP_P (insn));
3567e4b17023SJohn Marino
3568e4b17023SJohn Marino /* In the absence of interprocedural alias analysis, we must flush
3569e4b17023SJohn Marino all pending reads and writes, and start new dependencies starting
3570e4b17023SJohn Marino from here. But only flush writes for constant calls (which may
3571e4b17023SJohn Marino be passed a pointer to something we haven't written yet). */
3572e4b17023SJohn Marino flush_pending_lists (deps, insn, true, ! RTL_CONST_OR_PURE_CALL_P (insn));
3573e4b17023SJohn Marino
3574e4b17023SJohn Marino if (!deps->readonly)
3575e4b17023SJohn Marino {
3576e4b17023SJohn Marino /* Remember the last function call for limiting lifetimes. */
3577e4b17023SJohn Marino free_INSN_LIST_list (&deps->last_function_call);
3578e4b17023SJohn Marino deps->last_function_call = alloc_INSN_LIST (insn, NULL_RTX);
3579e4b17023SJohn Marino
3580e4b17023SJohn Marino if (call_may_noreturn_p (insn))
3581e4b17023SJohn Marino {
3582e4b17023SJohn Marino /* Remember the last function call that might not always return
3583e4b17023SJohn Marino normally for limiting moves of trapping insns. */
3584e4b17023SJohn Marino free_INSN_LIST_list (&deps->last_function_call_may_noreturn);
3585e4b17023SJohn Marino deps->last_function_call_may_noreturn
3586e4b17023SJohn Marino = alloc_INSN_LIST (insn, NULL_RTX);
3587e4b17023SJohn Marino }
3588e4b17023SJohn Marino
3589e4b17023SJohn Marino /* Before reload, begin a post-call group, so as to keep the
3590e4b17023SJohn Marino lifetimes of hard registers correct. */
3591e4b17023SJohn Marino if (! reload_completed)
3592e4b17023SJohn Marino deps->in_post_call_group_p = post_call;
3593e4b17023SJohn Marino }
3594e4b17023SJohn Marino }
3595e4b17023SJohn Marino
3596e4b17023SJohn Marino if (sched_deps_info->use_cselib)
3597e4b17023SJohn Marino cselib_process_insn (insn);
3598e4b17023SJohn Marino
3599e4b17023SJohn Marino /* EH_REGION insn notes can not appear until well after we complete
3600e4b17023SJohn Marino scheduling. */
3601e4b17023SJohn Marino if (NOTE_P (insn))
3602e4b17023SJohn Marino gcc_assert (NOTE_KIND (insn) != NOTE_INSN_EH_REGION_BEG
3603e4b17023SJohn Marino && NOTE_KIND (insn) != NOTE_INSN_EH_REGION_END);
3604e4b17023SJohn Marino
3605e4b17023SJohn Marino if (sched_deps_info->finish_insn)
3606e4b17023SJohn Marino sched_deps_info->finish_insn ();
3607e4b17023SJohn Marino
3608e4b17023SJohn Marino /* Fixup the dependencies in the sched group. */
3609e4b17023SJohn Marino if ((NONJUMP_INSN_P (insn) || JUMP_P (insn))
3610e4b17023SJohn Marino && SCHED_GROUP_P (insn) && !sel_sched_p ())
3611e4b17023SJohn Marino fixup_sched_groups (insn);
3612e4b17023SJohn Marino }
3613e4b17023SJohn Marino
3614e4b17023SJohn Marino /* Initialize DEPS for the new block beginning with HEAD. */
3615e4b17023SJohn Marino void
deps_start_bb(struct deps_desc * deps,rtx head)3616e4b17023SJohn Marino deps_start_bb (struct deps_desc *deps, rtx head)
3617e4b17023SJohn Marino {
3618e4b17023SJohn Marino gcc_assert (!deps->readonly);
3619e4b17023SJohn Marino
3620e4b17023SJohn Marino /* Before reload, if the previous block ended in a call, show that
3621e4b17023SJohn Marino we are inside a post-call group, so as to keep the lifetimes of
3622e4b17023SJohn Marino hard registers correct. */
3623e4b17023SJohn Marino if (! reload_completed && !LABEL_P (head))
3624e4b17023SJohn Marino {
3625e4b17023SJohn Marino rtx insn = prev_nonnote_nondebug_insn (head);
3626e4b17023SJohn Marino
3627e4b17023SJohn Marino if (insn && CALL_P (insn))
3628e4b17023SJohn Marino deps->in_post_call_group_p = post_call_initial;
3629e4b17023SJohn Marino }
3630e4b17023SJohn Marino }
3631e4b17023SJohn Marino
3632e4b17023SJohn Marino /* Analyze every insn between HEAD and TAIL inclusive, creating backward
3633e4b17023SJohn Marino dependencies for each insn. */
3634e4b17023SJohn Marino void
sched_analyze(struct deps_desc * deps,rtx head,rtx tail)3635e4b17023SJohn Marino sched_analyze (struct deps_desc *deps, rtx head, rtx tail)
3636e4b17023SJohn Marino {
3637e4b17023SJohn Marino rtx insn;
3638e4b17023SJohn Marino
3639e4b17023SJohn Marino if (sched_deps_info->use_cselib)
3640e4b17023SJohn Marino cselib_init (CSELIB_RECORD_MEMORY);
3641e4b17023SJohn Marino
3642e4b17023SJohn Marino deps_start_bb (deps, head);
3643e4b17023SJohn Marino
3644e4b17023SJohn Marino for (insn = head;; insn = NEXT_INSN (insn))
3645e4b17023SJohn Marino {
3646e4b17023SJohn Marino
3647e4b17023SJohn Marino if (INSN_P (insn))
3648e4b17023SJohn Marino {
3649e4b17023SJohn Marino /* And initialize deps_lists. */
3650e4b17023SJohn Marino sd_init_insn (insn);
3651e4b17023SJohn Marino }
3652e4b17023SJohn Marino
3653e4b17023SJohn Marino deps_analyze_insn (deps, insn);
3654e4b17023SJohn Marino
3655e4b17023SJohn Marino if (insn == tail)
3656e4b17023SJohn Marino {
3657e4b17023SJohn Marino if (sched_deps_info->use_cselib)
3658e4b17023SJohn Marino cselib_finish ();
3659e4b17023SJohn Marino return;
3660e4b17023SJohn Marino }
3661e4b17023SJohn Marino }
3662e4b17023SJohn Marino gcc_unreachable ();
3663e4b17023SJohn Marino }
3664e4b17023SJohn Marino
3665e4b17023SJohn Marino /* Helper for sched_free_deps ().
3666e4b17023SJohn Marino Delete INSN's (RESOLVED_P) backward dependencies. */
3667e4b17023SJohn Marino static void
delete_dep_nodes_in_back_deps(rtx insn,bool resolved_p)3668e4b17023SJohn Marino delete_dep_nodes_in_back_deps (rtx insn, bool resolved_p)
3669e4b17023SJohn Marino {
3670e4b17023SJohn Marino sd_iterator_def sd_it;
3671e4b17023SJohn Marino dep_t dep;
3672e4b17023SJohn Marino sd_list_types_def types;
3673e4b17023SJohn Marino
3674e4b17023SJohn Marino if (resolved_p)
3675e4b17023SJohn Marino types = SD_LIST_RES_BACK;
3676e4b17023SJohn Marino else
3677e4b17023SJohn Marino types = SD_LIST_BACK;
3678e4b17023SJohn Marino
3679e4b17023SJohn Marino for (sd_it = sd_iterator_start (insn, types);
3680e4b17023SJohn Marino sd_iterator_cond (&sd_it, &dep);)
3681e4b17023SJohn Marino {
3682e4b17023SJohn Marino dep_link_t link = *sd_it.linkp;
3683e4b17023SJohn Marino dep_node_t node = DEP_LINK_NODE (link);
3684e4b17023SJohn Marino deps_list_t back_list;
3685e4b17023SJohn Marino deps_list_t forw_list;
3686e4b17023SJohn Marino
3687e4b17023SJohn Marino get_back_and_forw_lists (dep, resolved_p, &back_list, &forw_list);
3688e4b17023SJohn Marino remove_from_deps_list (link, back_list);
3689e4b17023SJohn Marino delete_dep_node (node);
3690e4b17023SJohn Marino }
3691e4b17023SJohn Marino }
3692e4b17023SJohn Marino
3693e4b17023SJohn Marino /* Delete (RESOLVED_P) dependencies between HEAD and TAIL together with
3694e4b17023SJohn Marino deps_lists. */
3695e4b17023SJohn Marino void
sched_free_deps(rtx head,rtx tail,bool resolved_p)3696e4b17023SJohn Marino sched_free_deps (rtx head, rtx tail, bool resolved_p)
3697e4b17023SJohn Marino {
3698e4b17023SJohn Marino rtx insn;
3699e4b17023SJohn Marino rtx next_tail = NEXT_INSN (tail);
3700e4b17023SJohn Marino
3701e4b17023SJohn Marino /* We make two passes since some insns may be scheduled before their
3702e4b17023SJohn Marino dependencies are resolved. */
3703e4b17023SJohn Marino for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
3704e4b17023SJohn Marino if (INSN_P (insn) && INSN_LUID (insn) > 0)
3705e4b17023SJohn Marino {
3706e4b17023SJohn Marino /* Clear forward deps and leave the dep_nodes to the
3707e4b17023SJohn Marino corresponding back_deps list. */
3708e4b17023SJohn Marino if (resolved_p)
3709e4b17023SJohn Marino clear_deps_list (INSN_RESOLVED_FORW_DEPS (insn));
3710e4b17023SJohn Marino else
3711e4b17023SJohn Marino clear_deps_list (INSN_FORW_DEPS (insn));
3712e4b17023SJohn Marino }
3713e4b17023SJohn Marino for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
3714e4b17023SJohn Marino if (INSN_P (insn) && INSN_LUID (insn) > 0)
3715e4b17023SJohn Marino {
3716e4b17023SJohn Marino /* Clear resolved back deps together with its dep_nodes. */
3717e4b17023SJohn Marino delete_dep_nodes_in_back_deps (insn, resolved_p);
3718e4b17023SJohn Marino
3719e4b17023SJohn Marino sd_finish_insn (insn);
3720e4b17023SJohn Marino }
3721e4b17023SJohn Marino }
3722e4b17023SJohn Marino
3723e4b17023SJohn Marino /* Initialize variables for region data dependence analysis.
3724e4b17023SJohn Marino When LAZY_REG_LAST is true, do not allocate reg_last array
3725e4b17023SJohn Marino of struct deps_desc immediately. */
3726e4b17023SJohn Marino
3727e4b17023SJohn Marino void
init_deps(struct deps_desc * deps,bool lazy_reg_last)3728e4b17023SJohn Marino init_deps (struct deps_desc *deps, bool lazy_reg_last)
3729e4b17023SJohn Marino {
3730e4b17023SJohn Marino int max_reg = (reload_completed ? FIRST_PSEUDO_REGISTER : max_reg_num ());
3731e4b17023SJohn Marino
3732e4b17023SJohn Marino deps->max_reg = max_reg;
3733e4b17023SJohn Marino if (lazy_reg_last)
3734e4b17023SJohn Marino deps->reg_last = NULL;
3735e4b17023SJohn Marino else
3736e4b17023SJohn Marino deps->reg_last = XCNEWVEC (struct deps_reg, max_reg);
3737e4b17023SJohn Marino INIT_REG_SET (&deps->reg_last_in_use);
3738e4b17023SJohn Marino
3739e4b17023SJohn Marino deps->pending_read_insns = 0;
3740e4b17023SJohn Marino deps->pending_read_mems = 0;
3741e4b17023SJohn Marino deps->pending_write_insns = 0;
3742e4b17023SJohn Marino deps->pending_write_mems = 0;
3743e4b17023SJohn Marino deps->pending_jump_insns = 0;
3744e4b17023SJohn Marino deps->pending_read_list_length = 0;
3745e4b17023SJohn Marino deps->pending_write_list_length = 0;
3746e4b17023SJohn Marino deps->pending_flush_length = 0;
3747e4b17023SJohn Marino deps->last_pending_memory_flush = 0;
3748e4b17023SJohn Marino deps->last_function_call = 0;
3749e4b17023SJohn Marino deps->last_function_call_may_noreturn = 0;
3750e4b17023SJohn Marino deps->sched_before_next_call = 0;
3751e4b17023SJohn Marino deps->sched_before_next_jump = 0;
3752e4b17023SJohn Marino deps->in_post_call_group_p = not_post_call;
3753e4b17023SJohn Marino deps->last_debug_insn = 0;
3754e4b17023SJohn Marino deps->last_reg_pending_barrier = NOT_A_BARRIER;
3755e4b17023SJohn Marino deps->readonly = 0;
3756e4b17023SJohn Marino }
3757e4b17023SJohn Marino
3758e4b17023SJohn Marino /* Init only reg_last field of DEPS, which was not allocated before as
3759e4b17023SJohn Marino we inited DEPS lazily. */
3760e4b17023SJohn Marino void
init_deps_reg_last(struct deps_desc * deps)3761e4b17023SJohn Marino init_deps_reg_last (struct deps_desc *deps)
3762e4b17023SJohn Marino {
3763e4b17023SJohn Marino gcc_assert (deps && deps->max_reg > 0);
3764e4b17023SJohn Marino gcc_assert (deps->reg_last == NULL);
3765e4b17023SJohn Marino
3766e4b17023SJohn Marino deps->reg_last = XCNEWVEC (struct deps_reg, deps->max_reg);
3767e4b17023SJohn Marino }
3768e4b17023SJohn Marino
3769e4b17023SJohn Marino
3770e4b17023SJohn Marino /* Free insn lists found in DEPS. */
3771e4b17023SJohn Marino
3772e4b17023SJohn Marino void
free_deps(struct deps_desc * deps)3773e4b17023SJohn Marino free_deps (struct deps_desc *deps)
3774e4b17023SJohn Marino {
3775e4b17023SJohn Marino unsigned i;
3776e4b17023SJohn Marino reg_set_iterator rsi;
3777e4b17023SJohn Marino
3778e4b17023SJohn Marino /* We set max_reg to 0 when this context was already freed. */
3779e4b17023SJohn Marino if (deps->max_reg == 0)
3780e4b17023SJohn Marino {
3781e4b17023SJohn Marino gcc_assert (deps->reg_last == NULL);
3782e4b17023SJohn Marino return;
3783e4b17023SJohn Marino }
3784e4b17023SJohn Marino deps->max_reg = 0;
3785e4b17023SJohn Marino
3786e4b17023SJohn Marino free_INSN_LIST_list (&deps->pending_read_insns);
3787e4b17023SJohn Marino free_EXPR_LIST_list (&deps->pending_read_mems);
3788e4b17023SJohn Marino free_INSN_LIST_list (&deps->pending_write_insns);
3789e4b17023SJohn Marino free_EXPR_LIST_list (&deps->pending_write_mems);
3790e4b17023SJohn Marino free_INSN_LIST_list (&deps->last_pending_memory_flush);
3791e4b17023SJohn Marino
3792e4b17023SJohn Marino /* Without the EXECUTE_IF_SET, this loop is executed max_reg * nr_regions
3793e4b17023SJohn Marino times. For a testcase with 42000 regs and 8000 small basic blocks,
3794e4b17023SJohn Marino this loop accounted for nearly 60% (84 sec) of the total -O2 runtime. */
3795e4b17023SJohn Marino EXECUTE_IF_SET_IN_REG_SET (&deps->reg_last_in_use, 0, i, rsi)
3796e4b17023SJohn Marino {
3797e4b17023SJohn Marino struct deps_reg *reg_last = &deps->reg_last[i];
3798e4b17023SJohn Marino if (reg_last->uses)
3799e4b17023SJohn Marino free_INSN_LIST_list (®_last->uses);
3800e4b17023SJohn Marino if (reg_last->sets)
3801e4b17023SJohn Marino free_INSN_LIST_list (®_last->sets);
3802e4b17023SJohn Marino if (reg_last->implicit_sets)
3803e4b17023SJohn Marino free_INSN_LIST_list (®_last->implicit_sets);
3804e4b17023SJohn Marino if (reg_last->control_uses)
3805e4b17023SJohn Marino free_INSN_LIST_list (®_last->control_uses);
3806e4b17023SJohn Marino if (reg_last->clobbers)
3807e4b17023SJohn Marino free_INSN_LIST_list (®_last->clobbers);
3808e4b17023SJohn Marino }
3809e4b17023SJohn Marino CLEAR_REG_SET (&deps->reg_last_in_use);
3810e4b17023SJohn Marino
3811e4b17023SJohn Marino /* As we initialize reg_last lazily, it is possible that we didn't allocate
3812e4b17023SJohn Marino it at all. */
3813e4b17023SJohn Marino free (deps->reg_last);
3814e4b17023SJohn Marino deps->reg_last = NULL;
3815e4b17023SJohn Marino
3816e4b17023SJohn Marino deps = NULL;
3817e4b17023SJohn Marino }
3818e4b17023SJohn Marino
3819e4b17023SJohn Marino /* Remove INSN from dependence contexts DEPS. */
3820e4b17023SJohn Marino void
remove_from_deps(struct deps_desc * deps,rtx insn)3821e4b17023SJohn Marino remove_from_deps (struct deps_desc *deps, rtx insn)
3822e4b17023SJohn Marino {
3823e4b17023SJohn Marino int removed;
3824e4b17023SJohn Marino unsigned i;
3825e4b17023SJohn Marino reg_set_iterator rsi;
3826e4b17023SJohn Marino
3827e4b17023SJohn Marino removed = remove_from_both_dependence_lists (insn, &deps->pending_read_insns,
3828e4b17023SJohn Marino &deps->pending_read_mems);
3829e4b17023SJohn Marino if (!DEBUG_INSN_P (insn))
3830e4b17023SJohn Marino deps->pending_read_list_length -= removed;
3831e4b17023SJohn Marino removed = remove_from_both_dependence_lists (insn, &deps->pending_write_insns,
3832e4b17023SJohn Marino &deps->pending_write_mems);
3833e4b17023SJohn Marino deps->pending_write_list_length -= removed;
3834e4b17023SJohn Marino
3835e4b17023SJohn Marino removed = remove_from_dependence_list (insn, &deps->pending_jump_insns);
3836e4b17023SJohn Marino deps->pending_flush_length -= removed;
3837e4b17023SJohn Marino removed = remove_from_dependence_list (insn, &deps->last_pending_memory_flush);
3838e4b17023SJohn Marino deps->pending_flush_length -= removed;
3839e4b17023SJohn Marino
3840e4b17023SJohn Marino EXECUTE_IF_SET_IN_REG_SET (&deps->reg_last_in_use, 0, i, rsi)
3841e4b17023SJohn Marino {
3842e4b17023SJohn Marino struct deps_reg *reg_last = &deps->reg_last[i];
3843e4b17023SJohn Marino if (reg_last->uses)
3844e4b17023SJohn Marino remove_from_dependence_list (insn, ®_last->uses);
3845e4b17023SJohn Marino if (reg_last->sets)
3846e4b17023SJohn Marino remove_from_dependence_list (insn, ®_last->sets);
3847e4b17023SJohn Marino if (reg_last->implicit_sets)
3848e4b17023SJohn Marino remove_from_dependence_list (insn, ®_last->implicit_sets);
3849e4b17023SJohn Marino if (reg_last->clobbers)
3850e4b17023SJohn Marino remove_from_dependence_list (insn, ®_last->clobbers);
3851e4b17023SJohn Marino if (!reg_last->uses && !reg_last->sets && !reg_last->implicit_sets
3852e4b17023SJohn Marino && !reg_last->clobbers)
3853e4b17023SJohn Marino CLEAR_REGNO_REG_SET (&deps->reg_last_in_use, i);
3854e4b17023SJohn Marino }
3855e4b17023SJohn Marino
3856e4b17023SJohn Marino if (CALL_P (insn))
3857e4b17023SJohn Marino {
3858e4b17023SJohn Marino remove_from_dependence_list (insn, &deps->last_function_call);
3859e4b17023SJohn Marino remove_from_dependence_list (insn,
3860e4b17023SJohn Marino &deps->last_function_call_may_noreturn);
3861e4b17023SJohn Marino }
3862e4b17023SJohn Marino remove_from_dependence_list (insn, &deps->sched_before_next_call);
3863e4b17023SJohn Marino }
3864e4b17023SJohn Marino
3865e4b17023SJohn Marino /* Init deps data vector. */
3866e4b17023SJohn Marino static void
init_deps_data_vector(void)3867e4b17023SJohn Marino init_deps_data_vector (void)
3868e4b17023SJohn Marino {
3869e4b17023SJohn Marino int reserve = (sched_max_luid + 1
3870e4b17023SJohn Marino - VEC_length (haifa_deps_insn_data_def, h_d_i_d));
3871e4b17023SJohn Marino if (reserve > 0
3872e4b17023SJohn Marino && ! VEC_space (haifa_deps_insn_data_def, h_d_i_d, reserve))
3873e4b17023SJohn Marino VEC_safe_grow_cleared (haifa_deps_insn_data_def, heap, h_d_i_d,
3874e4b17023SJohn Marino 3 * sched_max_luid / 2);
3875e4b17023SJohn Marino }
3876e4b17023SJohn Marino
3877e4b17023SJohn Marino /* If it is profitable to use them, initialize or extend (depending on
3878e4b17023SJohn Marino GLOBAL_P) dependency data. */
3879e4b17023SJohn Marino void
sched_deps_init(bool global_p)3880e4b17023SJohn Marino sched_deps_init (bool global_p)
3881e4b17023SJohn Marino {
3882e4b17023SJohn Marino /* Average number of insns in the basic block.
3883e4b17023SJohn Marino '+ 1' is used to make it nonzero. */
3884e4b17023SJohn Marino int insns_in_block = sched_max_luid / n_basic_blocks + 1;
3885e4b17023SJohn Marino
3886e4b17023SJohn Marino init_deps_data_vector ();
3887e4b17023SJohn Marino
3888e4b17023SJohn Marino /* We use another caching mechanism for selective scheduling, so
3889e4b17023SJohn Marino we don't use this one. */
3890e4b17023SJohn Marino if (!sel_sched_p () && global_p && insns_in_block > 100 * 5)
3891e4b17023SJohn Marino {
3892e4b17023SJohn Marino /* ?!? We could save some memory by computing a per-region luid mapping
3893e4b17023SJohn Marino which could reduce both the number of vectors in the cache and the
3894e4b17023SJohn Marino size of each vector. Instead we just avoid the cache entirely unless
3895e4b17023SJohn Marino the average number of instructions in a basic block is very high. See
3896e4b17023SJohn Marino the comment before the declaration of true_dependency_cache for
3897e4b17023SJohn Marino what we consider "very high". */
3898e4b17023SJohn Marino cache_size = 0;
3899e4b17023SJohn Marino extend_dependency_caches (sched_max_luid, true);
3900e4b17023SJohn Marino }
3901e4b17023SJohn Marino
3902e4b17023SJohn Marino if (global_p)
3903e4b17023SJohn Marino {
3904e4b17023SJohn Marino dl_pool = create_alloc_pool ("deps_list", sizeof (struct _deps_list),
3905e4b17023SJohn Marino /* Allocate lists for one block at a time. */
3906e4b17023SJohn Marino insns_in_block);
3907e4b17023SJohn Marino dn_pool = create_alloc_pool ("dep_node", sizeof (struct _dep_node),
3908e4b17023SJohn Marino /* Allocate nodes for one block at a time.
3909e4b17023SJohn Marino We assume that average insn has
3910e4b17023SJohn Marino 5 producers. */
3911e4b17023SJohn Marino 5 * insns_in_block);
3912e4b17023SJohn Marino }
3913e4b17023SJohn Marino }
3914e4b17023SJohn Marino
3915e4b17023SJohn Marino
3916e4b17023SJohn Marino /* Create or extend (depending on CREATE_P) dependency caches to
3917e4b17023SJohn Marino size N. */
3918e4b17023SJohn Marino void
extend_dependency_caches(int n,bool create_p)3919e4b17023SJohn Marino extend_dependency_caches (int n, bool create_p)
3920e4b17023SJohn Marino {
3921e4b17023SJohn Marino if (create_p || true_dependency_cache)
3922e4b17023SJohn Marino {
3923e4b17023SJohn Marino int i, luid = cache_size + n;
3924e4b17023SJohn Marino
3925e4b17023SJohn Marino true_dependency_cache = XRESIZEVEC (bitmap_head, true_dependency_cache,
3926e4b17023SJohn Marino luid);
3927e4b17023SJohn Marino output_dependency_cache = XRESIZEVEC (bitmap_head,
3928e4b17023SJohn Marino output_dependency_cache, luid);
3929e4b17023SJohn Marino anti_dependency_cache = XRESIZEVEC (bitmap_head, anti_dependency_cache,
3930e4b17023SJohn Marino luid);
3931e4b17023SJohn Marino control_dependency_cache = XRESIZEVEC (bitmap_head, control_dependency_cache,
3932e4b17023SJohn Marino luid);
3933e4b17023SJohn Marino
3934e4b17023SJohn Marino if (current_sched_info->flags & DO_SPECULATION)
3935e4b17023SJohn Marino spec_dependency_cache = XRESIZEVEC (bitmap_head, spec_dependency_cache,
3936e4b17023SJohn Marino luid);
3937e4b17023SJohn Marino
3938e4b17023SJohn Marino for (i = cache_size; i < luid; i++)
3939e4b17023SJohn Marino {
3940e4b17023SJohn Marino bitmap_initialize (&true_dependency_cache[i], 0);
3941e4b17023SJohn Marino bitmap_initialize (&output_dependency_cache[i], 0);
3942e4b17023SJohn Marino bitmap_initialize (&anti_dependency_cache[i], 0);
3943e4b17023SJohn Marino bitmap_initialize (&control_dependency_cache[i], 0);
3944e4b17023SJohn Marino
3945e4b17023SJohn Marino if (current_sched_info->flags & DO_SPECULATION)
3946e4b17023SJohn Marino bitmap_initialize (&spec_dependency_cache[i], 0);
3947e4b17023SJohn Marino }
3948e4b17023SJohn Marino cache_size = luid;
3949e4b17023SJohn Marino }
3950e4b17023SJohn Marino }
3951e4b17023SJohn Marino
3952e4b17023SJohn Marino /* Finalize dependency information for the whole function. */
3953e4b17023SJohn Marino void
sched_deps_finish(void)3954e4b17023SJohn Marino sched_deps_finish (void)
3955e4b17023SJohn Marino {
3956e4b17023SJohn Marino gcc_assert (deps_pools_are_empty_p ());
3957e4b17023SJohn Marino free_alloc_pool_if_empty (&dn_pool);
3958e4b17023SJohn Marino free_alloc_pool_if_empty (&dl_pool);
3959e4b17023SJohn Marino gcc_assert (dn_pool == NULL && dl_pool == NULL);
3960e4b17023SJohn Marino
3961e4b17023SJohn Marino VEC_free (haifa_deps_insn_data_def, heap, h_d_i_d);
3962e4b17023SJohn Marino cache_size = 0;
3963e4b17023SJohn Marino
3964e4b17023SJohn Marino if (true_dependency_cache)
3965e4b17023SJohn Marino {
3966e4b17023SJohn Marino int i;
3967e4b17023SJohn Marino
3968e4b17023SJohn Marino for (i = 0; i < cache_size; i++)
3969e4b17023SJohn Marino {
3970e4b17023SJohn Marino bitmap_clear (&true_dependency_cache[i]);
3971e4b17023SJohn Marino bitmap_clear (&output_dependency_cache[i]);
3972e4b17023SJohn Marino bitmap_clear (&anti_dependency_cache[i]);
3973e4b17023SJohn Marino bitmap_clear (&control_dependency_cache[i]);
3974e4b17023SJohn Marino
3975e4b17023SJohn Marino if (sched_deps_info->generate_spec_deps)
3976e4b17023SJohn Marino bitmap_clear (&spec_dependency_cache[i]);
3977e4b17023SJohn Marino }
3978e4b17023SJohn Marino free (true_dependency_cache);
3979e4b17023SJohn Marino true_dependency_cache = NULL;
3980e4b17023SJohn Marino free (output_dependency_cache);
3981e4b17023SJohn Marino output_dependency_cache = NULL;
3982e4b17023SJohn Marino free (anti_dependency_cache);
3983e4b17023SJohn Marino anti_dependency_cache = NULL;
3984e4b17023SJohn Marino free (control_dependency_cache);
3985e4b17023SJohn Marino control_dependency_cache = NULL;
3986e4b17023SJohn Marino
3987e4b17023SJohn Marino if (sched_deps_info->generate_spec_deps)
3988e4b17023SJohn Marino {
3989e4b17023SJohn Marino free (spec_dependency_cache);
3990e4b17023SJohn Marino spec_dependency_cache = NULL;
3991e4b17023SJohn Marino }
3992e4b17023SJohn Marino
3993e4b17023SJohn Marino }
3994e4b17023SJohn Marino }
3995e4b17023SJohn Marino
3996e4b17023SJohn Marino /* Initialize some global variables needed by the dependency analysis
3997e4b17023SJohn Marino code. */
3998e4b17023SJohn Marino
3999e4b17023SJohn Marino void
init_deps_global(void)4000e4b17023SJohn Marino init_deps_global (void)
4001e4b17023SJohn Marino {
4002e4b17023SJohn Marino CLEAR_HARD_REG_SET (implicit_reg_pending_clobbers);
4003e4b17023SJohn Marino CLEAR_HARD_REG_SET (implicit_reg_pending_uses);
4004e4b17023SJohn Marino reg_pending_sets = ALLOC_REG_SET (®_obstack);
4005e4b17023SJohn Marino reg_pending_clobbers = ALLOC_REG_SET (®_obstack);
4006e4b17023SJohn Marino reg_pending_uses = ALLOC_REG_SET (®_obstack);
4007e4b17023SJohn Marino reg_pending_control_uses = ALLOC_REG_SET (®_obstack);
4008e4b17023SJohn Marino reg_pending_barrier = NOT_A_BARRIER;
4009e4b17023SJohn Marino
4010e4b17023SJohn Marino if (!sel_sched_p () || sched_emulate_haifa_p)
4011e4b17023SJohn Marino {
4012e4b17023SJohn Marino sched_deps_info->start_insn = haifa_start_insn;
4013e4b17023SJohn Marino sched_deps_info->finish_insn = haifa_finish_insn;
4014e4b17023SJohn Marino
4015e4b17023SJohn Marino sched_deps_info->note_reg_set = haifa_note_reg_set;
4016e4b17023SJohn Marino sched_deps_info->note_reg_clobber = haifa_note_reg_clobber;
4017e4b17023SJohn Marino sched_deps_info->note_reg_use = haifa_note_reg_use;
4018e4b17023SJohn Marino
4019e4b17023SJohn Marino sched_deps_info->note_mem_dep = haifa_note_mem_dep;
4020e4b17023SJohn Marino sched_deps_info->note_dep = haifa_note_dep;
4021e4b17023SJohn Marino }
4022e4b17023SJohn Marino }
4023e4b17023SJohn Marino
4024e4b17023SJohn Marino /* Free everything used by the dependency analysis code. */
4025e4b17023SJohn Marino
4026e4b17023SJohn Marino void
finish_deps_global(void)4027e4b17023SJohn Marino finish_deps_global (void)
4028e4b17023SJohn Marino {
4029e4b17023SJohn Marino FREE_REG_SET (reg_pending_sets);
4030e4b17023SJohn Marino FREE_REG_SET (reg_pending_clobbers);
4031e4b17023SJohn Marino FREE_REG_SET (reg_pending_uses);
4032e4b17023SJohn Marino FREE_REG_SET (reg_pending_control_uses);
4033e4b17023SJohn Marino }
4034e4b17023SJohn Marino
4035e4b17023SJohn Marino /* Estimate the weakness of dependence between MEM1 and MEM2. */
4036e4b17023SJohn Marino dw_t
estimate_dep_weak(rtx mem1,rtx mem2)4037e4b17023SJohn Marino estimate_dep_weak (rtx mem1, rtx mem2)
4038e4b17023SJohn Marino {
4039e4b17023SJohn Marino rtx r1, r2;
4040e4b17023SJohn Marino
4041e4b17023SJohn Marino if (mem1 == mem2)
4042e4b17023SJohn Marino /* MEMs are the same - don't speculate. */
4043e4b17023SJohn Marino return MIN_DEP_WEAK;
4044e4b17023SJohn Marino
4045e4b17023SJohn Marino r1 = XEXP (mem1, 0);
4046e4b17023SJohn Marino r2 = XEXP (mem2, 0);
4047e4b17023SJohn Marino
4048e4b17023SJohn Marino if (r1 == r2
4049e4b17023SJohn Marino || (REG_P (r1) && REG_P (r2)
4050e4b17023SJohn Marino && REGNO (r1) == REGNO (r2)))
4051e4b17023SJohn Marino /* Again, MEMs are the same. */
4052e4b17023SJohn Marino return MIN_DEP_WEAK;
4053e4b17023SJohn Marino else if ((REG_P (r1) && !REG_P (r2))
4054e4b17023SJohn Marino || (!REG_P (r1) && REG_P (r2)))
4055e4b17023SJohn Marino /* Different addressing modes - reason to be more speculative,
4056e4b17023SJohn Marino than usual. */
4057e4b17023SJohn Marino return NO_DEP_WEAK - (NO_DEP_WEAK - UNCERTAIN_DEP_WEAK) / 2;
4058e4b17023SJohn Marino else
4059e4b17023SJohn Marino /* We can't say anything about the dependence. */
4060e4b17023SJohn Marino return UNCERTAIN_DEP_WEAK;
4061e4b17023SJohn Marino }
4062e4b17023SJohn Marino
4063e4b17023SJohn Marino /* Add or update backward dependence between INSN and ELEM with type DEP_TYPE.
4064e4b17023SJohn Marino This function can handle same INSN and ELEM (INSN == ELEM).
4065e4b17023SJohn Marino It is a convenience wrapper. */
4066e4b17023SJohn Marino static void
add_dependence_1(rtx insn,rtx elem,enum reg_note dep_type)4067e4b17023SJohn Marino add_dependence_1 (rtx insn, rtx elem, enum reg_note dep_type)
4068e4b17023SJohn Marino {
4069e4b17023SJohn Marino ds_t ds;
4070e4b17023SJohn Marino bool internal;
4071e4b17023SJohn Marino
4072e4b17023SJohn Marino if (dep_type == REG_DEP_TRUE)
4073e4b17023SJohn Marino ds = DEP_TRUE;
4074e4b17023SJohn Marino else if (dep_type == REG_DEP_OUTPUT)
4075e4b17023SJohn Marino ds = DEP_OUTPUT;
4076e4b17023SJohn Marino else if (dep_type == REG_DEP_CONTROL)
4077e4b17023SJohn Marino ds = DEP_CONTROL;
4078e4b17023SJohn Marino else
4079e4b17023SJohn Marino {
4080e4b17023SJohn Marino gcc_assert (dep_type == REG_DEP_ANTI);
4081e4b17023SJohn Marino ds = DEP_ANTI;
4082e4b17023SJohn Marino }
4083e4b17023SJohn Marino
4084e4b17023SJohn Marino /* When add_dependence is called from inside sched-deps.c, we expect
4085e4b17023SJohn Marino cur_insn to be non-null. */
4086e4b17023SJohn Marino internal = cur_insn != NULL;
4087e4b17023SJohn Marino if (internal)
4088e4b17023SJohn Marino gcc_assert (insn == cur_insn);
4089e4b17023SJohn Marino else
4090e4b17023SJohn Marino cur_insn = insn;
4091e4b17023SJohn Marino
4092e4b17023SJohn Marino note_dep (elem, ds);
4093e4b17023SJohn Marino if (!internal)
4094e4b17023SJohn Marino cur_insn = NULL;
4095e4b17023SJohn Marino }
4096e4b17023SJohn Marino
4097e4b17023SJohn Marino /* Return weakness of speculative type TYPE in the dep_status DS. */
4098e4b17023SJohn Marino dw_t
get_dep_weak_1(ds_t ds,ds_t type)4099e4b17023SJohn Marino get_dep_weak_1 (ds_t ds, ds_t type)
4100e4b17023SJohn Marino {
4101e4b17023SJohn Marino ds = ds & type;
4102e4b17023SJohn Marino
4103e4b17023SJohn Marino switch (type)
4104e4b17023SJohn Marino {
4105e4b17023SJohn Marino case BEGIN_DATA: ds >>= BEGIN_DATA_BITS_OFFSET; break;
4106e4b17023SJohn Marino case BE_IN_DATA: ds >>= BE_IN_DATA_BITS_OFFSET; break;
4107e4b17023SJohn Marino case BEGIN_CONTROL: ds >>= BEGIN_CONTROL_BITS_OFFSET; break;
4108e4b17023SJohn Marino case BE_IN_CONTROL: ds >>= BE_IN_CONTROL_BITS_OFFSET; break;
4109e4b17023SJohn Marino default: gcc_unreachable ();
4110e4b17023SJohn Marino }
4111e4b17023SJohn Marino
4112e4b17023SJohn Marino return (dw_t) ds;
4113e4b17023SJohn Marino }
4114e4b17023SJohn Marino
4115e4b17023SJohn Marino dw_t
get_dep_weak(ds_t ds,ds_t type)4116e4b17023SJohn Marino get_dep_weak (ds_t ds, ds_t type)
4117e4b17023SJohn Marino {
4118e4b17023SJohn Marino dw_t dw = get_dep_weak_1 (ds, type);
4119e4b17023SJohn Marino
4120e4b17023SJohn Marino gcc_assert (MIN_DEP_WEAK <= dw && dw <= MAX_DEP_WEAK);
4121e4b17023SJohn Marino return dw;
4122e4b17023SJohn Marino }
4123e4b17023SJohn Marino
4124e4b17023SJohn Marino /* Return the dep_status, which has the same parameters as DS, except for
4125e4b17023SJohn Marino speculative type TYPE, that will have weakness DW. */
4126e4b17023SJohn Marino ds_t
set_dep_weak(ds_t ds,ds_t type,dw_t dw)4127e4b17023SJohn Marino set_dep_weak (ds_t ds, ds_t type, dw_t dw)
4128e4b17023SJohn Marino {
4129e4b17023SJohn Marino gcc_assert (MIN_DEP_WEAK <= dw && dw <= MAX_DEP_WEAK);
4130e4b17023SJohn Marino
4131e4b17023SJohn Marino ds &= ~type;
4132e4b17023SJohn Marino switch (type)
4133e4b17023SJohn Marino {
4134e4b17023SJohn Marino case BEGIN_DATA: ds |= ((ds_t) dw) << BEGIN_DATA_BITS_OFFSET; break;
4135e4b17023SJohn Marino case BE_IN_DATA: ds |= ((ds_t) dw) << BE_IN_DATA_BITS_OFFSET; break;
4136e4b17023SJohn Marino case BEGIN_CONTROL: ds |= ((ds_t) dw) << BEGIN_CONTROL_BITS_OFFSET; break;
4137e4b17023SJohn Marino case BE_IN_CONTROL: ds |= ((ds_t) dw) << BE_IN_CONTROL_BITS_OFFSET; break;
4138e4b17023SJohn Marino default: gcc_unreachable ();
4139e4b17023SJohn Marino }
4140e4b17023SJohn Marino return ds;
4141e4b17023SJohn Marino }
4142e4b17023SJohn Marino
4143e4b17023SJohn Marino /* Return the join of two dep_statuses DS1 and DS2.
4144e4b17023SJohn Marino If MAX_P is true then choose the greater probability,
4145e4b17023SJohn Marino otherwise multiply probabilities.
4146e4b17023SJohn Marino This function assumes that both DS1 and DS2 contain speculative bits. */
4147e4b17023SJohn Marino static ds_t
ds_merge_1(ds_t ds1,ds_t ds2,bool max_p)4148e4b17023SJohn Marino ds_merge_1 (ds_t ds1, ds_t ds2, bool max_p)
4149e4b17023SJohn Marino {
4150e4b17023SJohn Marino ds_t ds, t;
4151e4b17023SJohn Marino
4152e4b17023SJohn Marino gcc_assert ((ds1 & SPECULATIVE) && (ds2 & SPECULATIVE));
4153e4b17023SJohn Marino
4154e4b17023SJohn Marino ds = (ds1 & DEP_TYPES) | (ds2 & DEP_TYPES);
4155e4b17023SJohn Marino
4156e4b17023SJohn Marino t = FIRST_SPEC_TYPE;
4157e4b17023SJohn Marino do
4158e4b17023SJohn Marino {
4159e4b17023SJohn Marino if ((ds1 & t) && !(ds2 & t))
4160e4b17023SJohn Marino ds |= ds1 & t;
4161e4b17023SJohn Marino else if (!(ds1 & t) && (ds2 & t))
4162e4b17023SJohn Marino ds |= ds2 & t;
4163e4b17023SJohn Marino else if ((ds1 & t) && (ds2 & t))
4164e4b17023SJohn Marino {
4165e4b17023SJohn Marino dw_t dw1 = get_dep_weak (ds1, t);
4166e4b17023SJohn Marino dw_t dw2 = get_dep_weak (ds2, t);
4167e4b17023SJohn Marino ds_t dw;
4168e4b17023SJohn Marino
4169e4b17023SJohn Marino if (!max_p)
4170e4b17023SJohn Marino {
4171e4b17023SJohn Marino dw = ((ds_t) dw1) * ((ds_t) dw2);
4172e4b17023SJohn Marino dw /= MAX_DEP_WEAK;
4173e4b17023SJohn Marino if (dw < MIN_DEP_WEAK)
4174e4b17023SJohn Marino dw = MIN_DEP_WEAK;
4175e4b17023SJohn Marino }
4176e4b17023SJohn Marino else
4177e4b17023SJohn Marino {
4178e4b17023SJohn Marino if (dw1 >= dw2)
4179e4b17023SJohn Marino dw = dw1;
4180e4b17023SJohn Marino else
4181e4b17023SJohn Marino dw = dw2;
4182e4b17023SJohn Marino }
4183e4b17023SJohn Marino
4184e4b17023SJohn Marino ds = set_dep_weak (ds, t, (dw_t) dw);
4185e4b17023SJohn Marino }
4186e4b17023SJohn Marino
4187e4b17023SJohn Marino if (t == LAST_SPEC_TYPE)
4188e4b17023SJohn Marino break;
4189e4b17023SJohn Marino t <<= SPEC_TYPE_SHIFT;
4190e4b17023SJohn Marino }
4191e4b17023SJohn Marino while (1);
4192e4b17023SJohn Marino
4193e4b17023SJohn Marino return ds;
4194e4b17023SJohn Marino }
4195e4b17023SJohn Marino
4196e4b17023SJohn Marino /* Return the join of two dep_statuses DS1 and DS2.
4197e4b17023SJohn Marino This function assumes that both DS1 and DS2 contain speculative bits. */
4198e4b17023SJohn Marino ds_t
ds_merge(ds_t ds1,ds_t ds2)4199e4b17023SJohn Marino ds_merge (ds_t ds1, ds_t ds2)
4200e4b17023SJohn Marino {
4201e4b17023SJohn Marino return ds_merge_1 (ds1, ds2, false);
4202e4b17023SJohn Marino }
4203e4b17023SJohn Marino
4204e4b17023SJohn Marino /* Return the join of two dep_statuses DS1 and DS2. */
4205e4b17023SJohn Marino ds_t
ds_full_merge(ds_t ds,ds_t ds2,rtx mem1,rtx mem2)4206e4b17023SJohn Marino ds_full_merge (ds_t ds, ds_t ds2, rtx mem1, rtx mem2)
4207e4b17023SJohn Marino {
4208e4b17023SJohn Marino ds_t new_status = ds | ds2;
4209e4b17023SJohn Marino
4210e4b17023SJohn Marino if (new_status & SPECULATIVE)
4211e4b17023SJohn Marino {
4212e4b17023SJohn Marino if ((ds && !(ds & SPECULATIVE))
4213e4b17023SJohn Marino || (ds2 && !(ds2 & SPECULATIVE)))
4214e4b17023SJohn Marino /* Then this dep can't be speculative. */
4215e4b17023SJohn Marino new_status &= ~SPECULATIVE;
4216e4b17023SJohn Marino else
4217e4b17023SJohn Marino {
4218e4b17023SJohn Marino /* Both are speculative. Merging probabilities. */
4219e4b17023SJohn Marino if (mem1)
4220e4b17023SJohn Marino {
4221e4b17023SJohn Marino dw_t dw;
4222e4b17023SJohn Marino
4223e4b17023SJohn Marino dw = estimate_dep_weak (mem1, mem2);
4224e4b17023SJohn Marino ds = set_dep_weak (ds, BEGIN_DATA, dw);
4225e4b17023SJohn Marino }
4226e4b17023SJohn Marino
4227e4b17023SJohn Marino if (!ds)
4228e4b17023SJohn Marino new_status = ds2;
4229e4b17023SJohn Marino else if (!ds2)
4230e4b17023SJohn Marino new_status = ds;
4231e4b17023SJohn Marino else
4232e4b17023SJohn Marino new_status = ds_merge (ds2, ds);
4233e4b17023SJohn Marino }
4234e4b17023SJohn Marino }
4235e4b17023SJohn Marino
4236e4b17023SJohn Marino return new_status;
4237e4b17023SJohn Marino }
4238e4b17023SJohn Marino
4239e4b17023SJohn Marino /* Return the join of DS1 and DS2. Use maximum instead of multiplying
4240e4b17023SJohn Marino probabilities. */
4241e4b17023SJohn Marino ds_t
ds_max_merge(ds_t ds1,ds_t ds2)4242e4b17023SJohn Marino ds_max_merge (ds_t ds1, ds_t ds2)
4243e4b17023SJohn Marino {
4244e4b17023SJohn Marino if (ds1 == 0 && ds2 == 0)
4245e4b17023SJohn Marino return 0;
4246e4b17023SJohn Marino
4247e4b17023SJohn Marino if (ds1 == 0 && ds2 != 0)
4248e4b17023SJohn Marino return ds2;
4249e4b17023SJohn Marino
4250e4b17023SJohn Marino if (ds1 != 0 && ds2 == 0)
4251e4b17023SJohn Marino return ds1;
4252e4b17023SJohn Marino
4253e4b17023SJohn Marino return ds_merge_1 (ds1, ds2, true);
4254e4b17023SJohn Marino }
4255e4b17023SJohn Marino
4256e4b17023SJohn Marino /* Return the probability of speculation success for the speculation
4257e4b17023SJohn Marino status DS. */
4258e4b17023SJohn Marino dw_t
ds_weak(ds_t ds)4259e4b17023SJohn Marino ds_weak (ds_t ds)
4260e4b17023SJohn Marino {
4261e4b17023SJohn Marino ds_t res = 1, dt;
4262e4b17023SJohn Marino int n = 0;
4263e4b17023SJohn Marino
4264e4b17023SJohn Marino dt = FIRST_SPEC_TYPE;
4265e4b17023SJohn Marino do
4266e4b17023SJohn Marino {
4267e4b17023SJohn Marino if (ds & dt)
4268e4b17023SJohn Marino {
4269e4b17023SJohn Marino res *= (ds_t) get_dep_weak (ds, dt);
4270e4b17023SJohn Marino n++;
4271e4b17023SJohn Marino }
4272e4b17023SJohn Marino
4273e4b17023SJohn Marino if (dt == LAST_SPEC_TYPE)
4274e4b17023SJohn Marino break;
4275e4b17023SJohn Marino dt <<= SPEC_TYPE_SHIFT;
4276e4b17023SJohn Marino }
4277e4b17023SJohn Marino while (1);
4278e4b17023SJohn Marino
4279e4b17023SJohn Marino gcc_assert (n);
4280e4b17023SJohn Marino while (--n)
4281e4b17023SJohn Marino res /= MAX_DEP_WEAK;
4282e4b17023SJohn Marino
4283e4b17023SJohn Marino if (res < MIN_DEP_WEAK)
4284e4b17023SJohn Marino res = MIN_DEP_WEAK;
4285e4b17023SJohn Marino
4286e4b17023SJohn Marino gcc_assert (res <= MAX_DEP_WEAK);
4287e4b17023SJohn Marino
4288e4b17023SJohn Marino return (dw_t) res;
4289e4b17023SJohn Marino }
4290e4b17023SJohn Marino
4291e4b17023SJohn Marino /* Return a dep status that contains all speculation types of DS. */
4292e4b17023SJohn Marino ds_t
ds_get_speculation_types(ds_t ds)4293e4b17023SJohn Marino ds_get_speculation_types (ds_t ds)
4294e4b17023SJohn Marino {
4295e4b17023SJohn Marino if (ds & BEGIN_DATA)
4296e4b17023SJohn Marino ds |= BEGIN_DATA;
4297e4b17023SJohn Marino if (ds & BE_IN_DATA)
4298e4b17023SJohn Marino ds |= BE_IN_DATA;
4299e4b17023SJohn Marino if (ds & BEGIN_CONTROL)
4300e4b17023SJohn Marino ds |= BEGIN_CONTROL;
4301e4b17023SJohn Marino if (ds & BE_IN_CONTROL)
4302e4b17023SJohn Marino ds |= BE_IN_CONTROL;
4303e4b17023SJohn Marino
4304e4b17023SJohn Marino return ds & SPECULATIVE;
4305e4b17023SJohn Marino }
4306e4b17023SJohn Marino
4307e4b17023SJohn Marino /* Return a dep status that contains maximal weakness for each speculation
4308e4b17023SJohn Marino type present in DS. */
4309e4b17023SJohn Marino ds_t
ds_get_max_dep_weak(ds_t ds)4310e4b17023SJohn Marino ds_get_max_dep_weak (ds_t ds)
4311e4b17023SJohn Marino {
4312e4b17023SJohn Marino if (ds & BEGIN_DATA)
4313e4b17023SJohn Marino ds = set_dep_weak (ds, BEGIN_DATA, MAX_DEP_WEAK);
4314e4b17023SJohn Marino if (ds & BE_IN_DATA)
4315e4b17023SJohn Marino ds = set_dep_weak (ds, BE_IN_DATA, MAX_DEP_WEAK);
4316e4b17023SJohn Marino if (ds & BEGIN_CONTROL)
4317e4b17023SJohn Marino ds = set_dep_weak (ds, BEGIN_CONTROL, MAX_DEP_WEAK);
4318e4b17023SJohn Marino if (ds & BE_IN_CONTROL)
4319e4b17023SJohn Marino ds = set_dep_weak (ds, BE_IN_CONTROL, MAX_DEP_WEAK);
4320e4b17023SJohn Marino
4321e4b17023SJohn Marino return ds;
4322e4b17023SJohn Marino }
4323e4b17023SJohn Marino
4324e4b17023SJohn Marino /* Dump information about the dependence status S. */
4325e4b17023SJohn Marino static void
dump_ds(FILE * f,ds_t s)4326e4b17023SJohn Marino dump_ds (FILE *f, ds_t s)
4327e4b17023SJohn Marino {
4328e4b17023SJohn Marino fprintf (f, "{");
4329e4b17023SJohn Marino
4330e4b17023SJohn Marino if (s & BEGIN_DATA)
4331e4b17023SJohn Marino fprintf (f, "BEGIN_DATA: %d; ", get_dep_weak_1 (s, BEGIN_DATA));
4332e4b17023SJohn Marino if (s & BE_IN_DATA)
4333e4b17023SJohn Marino fprintf (f, "BE_IN_DATA: %d; ", get_dep_weak_1 (s, BE_IN_DATA));
4334e4b17023SJohn Marino if (s & BEGIN_CONTROL)
4335e4b17023SJohn Marino fprintf (f, "BEGIN_CONTROL: %d; ", get_dep_weak_1 (s, BEGIN_CONTROL));
4336e4b17023SJohn Marino if (s & BE_IN_CONTROL)
4337e4b17023SJohn Marino fprintf (f, "BE_IN_CONTROL: %d; ", get_dep_weak_1 (s, BE_IN_CONTROL));
4338e4b17023SJohn Marino
4339e4b17023SJohn Marino if (s & HARD_DEP)
4340e4b17023SJohn Marino fprintf (f, "HARD_DEP; ");
4341e4b17023SJohn Marino
4342e4b17023SJohn Marino if (s & DEP_TRUE)
4343e4b17023SJohn Marino fprintf (f, "DEP_TRUE; ");
4344e4b17023SJohn Marino if (s & DEP_OUTPUT)
4345e4b17023SJohn Marino fprintf (f, "DEP_OUTPUT; ");
4346e4b17023SJohn Marino if (s & DEP_ANTI)
4347e4b17023SJohn Marino fprintf (f, "DEP_ANTI; ");
4348e4b17023SJohn Marino if (s & DEP_CONTROL)
4349e4b17023SJohn Marino fprintf (f, "DEP_CONTROL; ");
4350e4b17023SJohn Marino
4351e4b17023SJohn Marino fprintf (f, "}");
4352e4b17023SJohn Marino }
4353e4b17023SJohn Marino
4354e4b17023SJohn Marino DEBUG_FUNCTION void
debug_ds(ds_t s)4355e4b17023SJohn Marino debug_ds (ds_t s)
4356e4b17023SJohn Marino {
4357e4b17023SJohn Marino dump_ds (stderr, s);
4358e4b17023SJohn Marino fprintf (stderr, "\n");
4359e4b17023SJohn Marino }
4360e4b17023SJohn Marino
4361e4b17023SJohn Marino #ifdef ENABLE_CHECKING
4362e4b17023SJohn Marino /* Verify that dependence type and status are consistent.
4363e4b17023SJohn Marino If RELAXED_P is true, then skip dep_weakness checks. */
4364e4b17023SJohn Marino static void
check_dep(dep_t dep,bool relaxed_p)4365e4b17023SJohn Marino check_dep (dep_t dep, bool relaxed_p)
4366e4b17023SJohn Marino {
4367e4b17023SJohn Marino enum reg_note dt = DEP_TYPE (dep);
4368e4b17023SJohn Marino ds_t ds = DEP_STATUS (dep);
4369e4b17023SJohn Marino
4370e4b17023SJohn Marino gcc_assert (DEP_PRO (dep) != DEP_CON (dep));
4371e4b17023SJohn Marino
4372e4b17023SJohn Marino if (!(current_sched_info->flags & USE_DEPS_LIST))
4373e4b17023SJohn Marino {
4374e4b17023SJohn Marino gcc_assert (ds == 0);
4375e4b17023SJohn Marino return;
4376e4b17023SJohn Marino }
4377e4b17023SJohn Marino
4378e4b17023SJohn Marino /* Check that dependence type contains the same bits as the status. */
4379e4b17023SJohn Marino if (dt == REG_DEP_TRUE)
4380e4b17023SJohn Marino gcc_assert (ds & DEP_TRUE);
4381e4b17023SJohn Marino else if (dt == REG_DEP_OUTPUT)
4382e4b17023SJohn Marino gcc_assert ((ds & DEP_OUTPUT)
4383e4b17023SJohn Marino && !(ds & DEP_TRUE));
4384e4b17023SJohn Marino else if (dt == REG_DEP_ANTI)
4385e4b17023SJohn Marino gcc_assert ((ds & DEP_ANTI)
4386e4b17023SJohn Marino && !(ds & (DEP_OUTPUT | DEP_TRUE)));
4387e4b17023SJohn Marino else
4388e4b17023SJohn Marino gcc_assert (dt == REG_DEP_CONTROL
4389e4b17023SJohn Marino && (ds & DEP_CONTROL)
4390e4b17023SJohn Marino && !(ds & (DEP_OUTPUT | DEP_ANTI | DEP_TRUE)));
4391e4b17023SJohn Marino
4392e4b17023SJohn Marino /* HARD_DEP can not appear in dep_status of a link. */
4393e4b17023SJohn Marino gcc_assert (!(ds & HARD_DEP));
4394e4b17023SJohn Marino
4395e4b17023SJohn Marino /* Check that dependence status is set correctly when speculation is not
4396e4b17023SJohn Marino supported. */
4397e4b17023SJohn Marino if (!sched_deps_info->generate_spec_deps)
4398e4b17023SJohn Marino gcc_assert (!(ds & SPECULATIVE));
4399e4b17023SJohn Marino else if (ds & SPECULATIVE)
4400e4b17023SJohn Marino {
4401e4b17023SJohn Marino if (!relaxed_p)
4402e4b17023SJohn Marino {
4403e4b17023SJohn Marino ds_t type = FIRST_SPEC_TYPE;
4404e4b17023SJohn Marino
4405e4b17023SJohn Marino /* Check that dependence weakness is in proper range. */
4406e4b17023SJohn Marino do
4407e4b17023SJohn Marino {
4408e4b17023SJohn Marino if (ds & type)
4409e4b17023SJohn Marino get_dep_weak (ds, type);
4410e4b17023SJohn Marino
4411e4b17023SJohn Marino if (type == LAST_SPEC_TYPE)
4412e4b17023SJohn Marino break;
4413e4b17023SJohn Marino type <<= SPEC_TYPE_SHIFT;
4414e4b17023SJohn Marino }
4415e4b17023SJohn Marino while (1);
4416e4b17023SJohn Marino }
4417e4b17023SJohn Marino
4418e4b17023SJohn Marino if (ds & BEGIN_SPEC)
4419e4b17023SJohn Marino {
4420e4b17023SJohn Marino /* Only true dependence can be data speculative. */
4421e4b17023SJohn Marino if (ds & BEGIN_DATA)
4422e4b17023SJohn Marino gcc_assert (ds & DEP_TRUE);
4423e4b17023SJohn Marino
4424e4b17023SJohn Marino /* Control dependencies in the insn scheduler are represented by
4425e4b17023SJohn Marino anti-dependencies, therefore only anti dependence can be
4426e4b17023SJohn Marino control speculative. */
4427e4b17023SJohn Marino if (ds & BEGIN_CONTROL)
4428e4b17023SJohn Marino gcc_assert (ds & DEP_ANTI);
4429e4b17023SJohn Marino }
4430e4b17023SJohn Marino else
4431e4b17023SJohn Marino {
4432e4b17023SJohn Marino /* Subsequent speculations should resolve true dependencies. */
4433e4b17023SJohn Marino gcc_assert ((ds & DEP_TYPES) == DEP_TRUE);
4434e4b17023SJohn Marino }
4435e4b17023SJohn Marino
4436e4b17023SJohn Marino /* Check that true and anti dependencies can't have other speculative
4437e4b17023SJohn Marino statuses. */
4438e4b17023SJohn Marino if (ds & DEP_TRUE)
4439e4b17023SJohn Marino gcc_assert (ds & (BEGIN_DATA | BE_IN_SPEC));
4440e4b17023SJohn Marino /* An output dependence can't be speculative at all. */
4441e4b17023SJohn Marino gcc_assert (!(ds & DEP_OUTPUT));
4442e4b17023SJohn Marino if (ds & DEP_ANTI)
4443e4b17023SJohn Marino gcc_assert (ds & BEGIN_CONTROL);
4444e4b17023SJohn Marino }
4445e4b17023SJohn Marino }
4446e4b17023SJohn Marino #endif /* ENABLE_CHECKING */
4447e4b17023SJohn Marino
4448e4b17023SJohn Marino #endif /* INSN_SCHEDULING */
4449