Commit 9a8819b8 by Pat Haugen Committed by Pat Haugen

rs6000.c (move_to_end_of_ready): New, factored out from common code.

	* config/rs6000/rs6000.c (move_to_end_of_ready): New, factored out
	from common code.
	(power6_sched_reorder2): Factored out from rs6000_sched_reorder2,
	call new function.
	(power9_sched_reorder2): Call new function.
	(rs6000_sched_reorder2): Likewise.

From-SVN: r278463
parent dd46a542
2019-11-19 Pat Haugen <pthaugen@us.ibm.com>
* config/rs6000/rs6000.c (move_to_end_of_ready): New, factored out
from common code.
(power6_sched_reorder2): Factored out from rs6000_sched_reorder2,
call new function.
(power9_sched_reorder2): Call new function.
(rs6000_sched_reorder2): Likewise.
2019-11-18 Jan Hubicka <jh@suse.cz> 2019-11-18 Jan Hubicka <jh@suse.cz>
* ipa-fnsummary.c (estimate_edge_size_and_time): Drop parameter PROB. * ipa-fnsummary.c (estimate_edge_size_and_time): Drop parameter PROB.
...@@ -17711,14 +17711,216 @@ get_next_active_insn (rtx_insn *insn, rtx_insn *tail) ...@@ -17711,14 +17711,216 @@ get_next_active_insn (rtx_insn *insn, rtx_insn *tail)
return insn; return insn;
} }
/* Move instruction at POS to the end of the READY list. */
static void
move_to_end_of_ready (rtx_insn **ready, int pos, int lastpos)
{
rtx_insn *tmp;
int i;
tmp = ready[pos];
for (i = pos; i < lastpos; i++)
ready[i] = ready[i + 1];
ready[lastpos] = tmp;
}
/* Do Power6 specific sched_reorder2 reordering of ready list. */
static int
power6_sched_reorder2 (rtx_insn **ready, int lastpos)
{
/* For Power6, we need to handle some special cases to try and keep the
store queue from overflowing and triggering expensive flushes.
This code monitors how load and store instructions are being issued
and skews the ready list one way or the other to increase the likelihood
that a desired instruction is issued at the proper time.
A couple of things are done. First, we maintain a "load_store_pendulum"
to track the current state of load/store issue.
- If the pendulum is at zero, then no loads or stores have been
issued in the current cycle so we do nothing.
- If the pendulum is 1, then a single load has been issued in this
cycle and we attempt to locate another load in the ready list to
issue with it.
- If the pendulum is -2, then two stores have already been
issued in this cycle, so we increase the priority of the first load
in the ready list to increase it's likelihood of being chosen first
in the next cycle.
- If the pendulum is -1, then a single store has been issued in this
cycle and we attempt to locate another store in the ready list to
issue with it, preferring a store to an adjacent memory location to
facilitate store pairing in the store queue.
- If the pendulum is 2, then two loads have already been
issued in this cycle, so we increase the priority of the first store
in the ready list to increase it's likelihood of being chosen first
in the next cycle.
- If the pendulum < -2 or > 2, then do nothing.
Note: This code covers the most common scenarios. There exist non
load/store instructions which make use of the LSU and which
would need to be accounted for to strictly model the behavior
of the machine. Those instructions are currently unaccounted
for to help minimize compile time overhead of this code.
*/
int pos;
rtx load_mem, str_mem;
if (is_store_insn (last_scheduled_insn, &str_mem))
/* Issuing a store, swing the load_store_pendulum to the left */
load_store_pendulum--;
else if (is_load_insn (last_scheduled_insn, &load_mem))
/* Issuing a load, swing the load_store_pendulum to the right */
load_store_pendulum++;
else
return cached_can_issue_more;
/* If the pendulum is balanced, or there is only one instruction on
the ready list, then all is well, so return. */
if ((load_store_pendulum == 0) || (lastpos <= 0))
return cached_can_issue_more;
if (load_store_pendulum == 1)
{
/* A load has been issued in this cycle. Scan the ready list
for another load to issue with it */
pos = lastpos;
while (pos >= 0)
{
if (is_load_insn (ready[pos], &load_mem))
{
/* Found a load. Move it to the head of the ready list,
and adjust it's priority so that it is more likely to
stay there */
move_to_end_of_ready (ready, pos, lastpos);
if (!sel_sched_p ()
&& INSN_PRIORITY_KNOWN (ready[lastpos]))
INSN_PRIORITY (ready[lastpos])++;
break;
}
pos--;
}
}
else if (load_store_pendulum == -2)
{
/* Two stores have been issued in this cycle. Increase the
priority of the first load in the ready list to favor it for
issuing in the next cycle. */
pos = lastpos;
while (pos >= 0)
{
if (is_load_insn (ready[pos], &load_mem)
&& !sel_sched_p ()
&& INSN_PRIORITY_KNOWN (ready[pos]))
{
INSN_PRIORITY (ready[pos])++;
/* Adjust the pendulum to account for the fact that a load
was found and increased in priority. This is to prevent
increasing the priority of multiple loads */
load_store_pendulum--;
break;
}
pos--;
}
}
else if (load_store_pendulum == -1)
{
/* A store has been issued in this cycle. Scan the ready list for
another store to issue with it, preferring a store to an adjacent
memory location */
int first_store_pos = -1;
pos = lastpos;
while (pos >= 0)
{
if (is_store_insn (ready[pos], &str_mem))
{
rtx str_mem2;
/* Maintain the index of the first store found on the
list */
if (first_store_pos == -1)
first_store_pos = pos;
if (is_store_insn (last_scheduled_insn, &str_mem2)
&& adjacent_mem_locations (str_mem, str_mem2))
{
/* Found an adjacent store. Move it to the head of the
ready list, and adjust it's priority so that it is
more likely to stay there */
move_to_end_of_ready (ready, pos, lastpos);
if (!sel_sched_p ()
&& INSN_PRIORITY_KNOWN (ready[lastpos]))
INSN_PRIORITY (ready[lastpos])++;
first_store_pos = -1;
break;
};
}
pos--;
}
if (first_store_pos >= 0)
{
/* An adjacent store wasn't found, but a non-adjacent store was,
so move the non-adjacent store to the front of the ready
list, and adjust its priority so that it is more likely to
stay there. */
move_to_end_of_ready (ready, first_store_pos, lastpos);
if (!sel_sched_p ()
&& INSN_PRIORITY_KNOWN (ready[lastpos]))
INSN_PRIORITY (ready[lastpos])++;
}
}
else if (load_store_pendulum == 2)
{
/* Two loads have been issued in this cycle. Increase the priority
of the first store in the ready list to favor it for issuing in
the next cycle. */
pos = lastpos;
while (pos >= 0)
{
if (is_store_insn (ready[pos], &str_mem)
&& !sel_sched_p ()
&& INSN_PRIORITY_KNOWN (ready[pos]))
{
INSN_PRIORITY (ready[pos])++;
/* Adjust the pendulum to account for the fact that a store
was found and increased in priority. This is to prevent
increasing the priority of multiple stores */
load_store_pendulum++;
break;
}
pos--;
}
}
return cached_can_issue_more;
}
/* Do Power9 specific sched_reorder2 reordering of ready list. */ /* Do Power9 specific sched_reorder2 reordering of ready list. */
static int static int
power9_sched_reorder2 (rtx_insn **ready, int lastpos) power9_sched_reorder2 (rtx_insn **ready, int lastpos)
{ {
int pos; int pos;
int i;
rtx_insn *tmp;
enum attr_type type, type2; enum attr_type type, type2;
type = get_attr_type (last_scheduled_insn); type = get_attr_type (last_scheduled_insn);
...@@ -17738,10 +17940,7 @@ power9_sched_reorder2 (rtx_insn **ready, int lastpos) ...@@ -17738,10 +17940,7 @@ power9_sched_reorder2 (rtx_insn **ready, int lastpos)
if (recog_memoized (ready[pos]) >= 0 if (recog_memoized (ready[pos]) >= 0
&& get_attr_type (ready[pos]) == TYPE_DIV) && get_attr_type (ready[pos]) == TYPE_DIV)
{ {
tmp = ready[pos]; move_to_end_of_ready (ready, pos, lastpos);
for (i = pos; i < lastpos; i++)
ready[i] = ready[i + 1];
ready[lastpos] = tmp;
break; break;
} }
pos--; pos--;
...@@ -17784,10 +17983,7 @@ power9_sched_reorder2 (rtx_insn **ready, int lastpos) ...@@ -17784,10 +17983,7 @@ power9_sched_reorder2 (rtx_insn **ready, int lastpos)
{ {
/* Found a vector insn to pair with, move it to the /* Found a vector insn to pair with, move it to the
end of the ready list so it is scheduled next. */ end of the ready list so it is scheduled next. */
tmp = ready[pos]; move_to_end_of_ready (ready, pos, lastpos);
for (i = pos; i < lastpos; i++)
ready[i] = ready[i + 1];
ready[lastpos] = tmp;
vec_pairing = 1; vec_pairing = 1;
return cached_can_issue_more; return cached_can_issue_more;
} }
...@@ -17801,10 +17997,7 @@ power9_sched_reorder2 (rtx_insn **ready, int lastpos) ...@@ -17801,10 +17997,7 @@ power9_sched_reorder2 (rtx_insn **ready, int lastpos)
{ {
/* Didn't find a vector to pair with but did find a vecload, /* Didn't find a vector to pair with but did find a vecload,
move it to the end of the ready list. */ move it to the end of the ready list. */
tmp = ready[vecload_pos]; move_to_end_of_ready (ready, vecload_pos, lastpos);
for (i = vecload_pos; i < lastpos; i++)
ready[i] = ready[i + 1];
ready[lastpos] = tmp;
vec_pairing = 1; vec_pairing = 1;
return cached_can_issue_more; return cached_can_issue_more;
} }
...@@ -17828,10 +18021,7 @@ power9_sched_reorder2 (rtx_insn **ready, int lastpos) ...@@ -17828,10 +18021,7 @@ power9_sched_reorder2 (rtx_insn **ready, int lastpos)
{ {
/* Found a vecload insn to pair with, move it to the /* Found a vecload insn to pair with, move it to the
end of the ready list so it is scheduled next. */ end of the ready list so it is scheduled next. */
tmp = ready[pos]; move_to_end_of_ready (ready, pos, lastpos);
for (i = pos; i < lastpos; i++)
ready[i] = ready[i + 1];
ready[lastpos] = tmp;
vec_pairing = 1; vec_pairing = 1;
return cached_can_issue_more; return cached_can_issue_more;
} }
...@@ -17846,10 +18036,7 @@ power9_sched_reorder2 (rtx_insn **ready, int lastpos) ...@@ -17846,10 +18036,7 @@ power9_sched_reorder2 (rtx_insn **ready, int lastpos)
{ {
/* Didn't find a vecload to pair with but did find a vector /* Didn't find a vecload to pair with but did find a vector
insn, move it to the end of the ready list. */ insn, move it to the end of the ready list. */
tmp = ready[vec_pos]; move_to_end_of_ready (ready, vec_pos, lastpos);
for (i = vec_pos; i < lastpos; i++)
ready[i] = ready[i + 1];
ready[lastpos] = tmp;
vec_pairing = 1; vec_pairing = 1;
return cached_can_issue_more; return cached_can_issue_more;
} }
...@@ -17903,198 +18090,9 @@ rs6000_sched_reorder2 (FILE *dump, int sched_verbose, rtx_insn **ready, ...@@ -17903,198 +18090,9 @@ rs6000_sched_reorder2 (FILE *dump, int sched_verbose, rtx_insn **ready,
if (sched_verbose) if (sched_verbose)
fprintf (dump, "// rs6000_sched_reorder2 :\n"); fprintf (dump, "// rs6000_sched_reorder2 :\n");
/* For Power6, we need to handle some special cases to try and keep the /* Do Power6 dependent reordering if necessary. */
store queue from overflowing and triggering expensive flushes.
This code monitors how load and store instructions are being issued
and skews the ready list one way or the other to increase the likelihood
that a desired instruction is issued at the proper time.
A couple of things are done. First, we maintain a "load_store_pendulum"
to track the current state of load/store issue.
- If the pendulum is at zero, then no loads or stores have been
issued in the current cycle so we do nothing.
- If the pendulum is 1, then a single load has been issued in this
cycle and we attempt to locate another load in the ready list to
issue with it.
- If the pendulum is -2, then two stores have already been
issued in this cycle, so we increase the priority of the first load
in the ready list to increase it's likelihood of being chosen first
in the next cycle.
- If the pendulum is -1, then a single store has been issued in this
cycle and we attempt to locate another store in the ready list to
issue with it, preferring a store to an adjacent memory location to
facilitate store pairing in the store queue.
- If the pendulum is 2, then two loads have already been
issued in this cycle, so we increase the priority of the first store
in the ready list to increase it's likelihood of being chosen first
in the next cycle.
- If the pendulum < -2 or > 2, then do nothing.
Note: This code covers the most common scenarios. There exist non
load/store instructions which make use of the LSU and which
would need to be accounted for to strictly model the behavior
of the machine. Those instructions are currently unaccounted
for to help minimize compile time overhead of this code.
*/
if (rs6000_tune == PROCESSOR_POWER6 && last_scheduled_insn) if (rs6000_tune == PROCESSOR_POWER6 && last_scheduled_insn)
{ return power6_sched_reorder2 (ready, *pn_ready - 1);
int pos;
int i;
rtx_insn *tmp;
rtx load_mem, str_mem;
if (is_store_insn (last_scheduled_insn, &str_mem))
/* Issuing a store, swing the load_store_pendulum to the left */
load_store_pendulum--;
else if (is_load_insn (last_scheduled_insn, &load_mem))
/* Issuing a load, swing the load_store_pendulum to the right */
load_store_pendulum++;
else
return cached_can_issue_more;
/* If the pendulum is balanced, or there is only one instruction on
the ready list, then all is well, so return. */
if ((load_store_pendulum == 0) || (*pn_ready <= 1))
return cached_can_issue_more;
if (load_store_pendulum == 1)
{
/* A load has been issued in this cycle. Scan the ready list
for another load to issue with it */
pos = *pn_ready-1;
while (pos >= 0)
{
if (is_load_insn (ready[pos], &load_mem))
{
/* Found a load. Move it to the head of the ready list,
and adjust it's priority so that it is more likely to
stay there */
tmp = ready[pos];
for (i=pos; i<*pn_ready-1; i++)
ready[i] = ready[i + 1];
ready[*pn_ready-1] = tmp;
if (!sel_sched_p () && INSN_PRIORITY_KNOWN (tmp))
INSN_PRIORITY (tmp)++;
break;
}
pos--;
}
}
else if (load_store_pendulum == -2)
{
/* Two stores have been issued in this cycle. Increase the
priority of the first load in the ready list to favor it for
issuing in the next cycle. */
pos = *pn_ready-1;
while (pos >= 0)
{
if (is_load_insn (ready[pos], &load_mem)
&& !sel_sched_p ()
&& INSN_PRIORITY_KNOWN (ready[pos]))
{
INSN_PRIORITY (ready[pos])++;
/* Adjust the pendulum to account for the fact that a load
was found and increased in priority. This is to prevent
increasing the priority of multiple loads */
load_store_pendulum--;
break;
}
pos--;
}
}
else if (load_store_pendulum == -1)
{
/* A store has been issued in this cycle. Scan the ready list for
another store to issue with it, preferring a store to an adjacent
memory location */
int first_store_pos = -1;
pos = *pn_ready-1;
while (pos >= 0)
{
if (is_store_insn (ready[pos], &str_mem))
{
rtx str_mem2;
/* Maintain the index of the first store found on the
list */
if (first_store_pos == -1)
first_store_pos = pos;
if (is_store_insn (last_scheduled_insn, &str_mem2)
&& adjacent_mem_locations (str_mem, str_mem2))
{
/* Found an adjacent store. Move it to the head of the
ready list, and adjust it's priority so that it is
more likely to stay there */
tmp = ready[pos];
for (i=pos; i<*pn_ready-1; i++)
ready[i] = ready[i + 1];
ready[*pn_ready-1] = tmp;
if (!sel_sched_p () && INSN_PRIORITY_KNOWN (tmp))
INSN_PRIORITY (tmp)++;
first_store_pos = -1;
break;
};
}
pos--;
}
if (first_store_pos >= 0)
{
/* An adjacent store wasn't found, but a non-adjacent store was,
so move the non-adjacent store to the front of the ready
list, and adjust its priority so that it is more likely to
stay there. */
tmp = ready[first_store_pos];
for (i=first_store_pos; i<*pn_ready-1; i++)
ready[i] = ready[i + 1];
ready[*pn_ready-1] = tmp;
if (!sel_sched_p () && INSN_PRIORITY_KNOWN (tmp))
INSN_PRIORITY (tmp)++;
}
}
else if (load_store_pendulum == 2)
{
/* Two loads have been issued in this cycle. Increase the priority
of the first store in the ready list to favor it for issuing in
the next cycle. */
pos = *pn_ready-1;
while (pos >= 0)
{
if (is_store_insn (ready[pos], &str_mem)
&& !sel_sched_p ()
&& INSN_PRIORITY_KNOWN (ready[pos]))
{
INSN_PRIORITY (ready[pos])++;
/* Adjust the pendulum to account for the fact that a store
was found and increased in priority. This is to prevent
increasing the priority of multiple stores */
load_store_pendulum++;
break;
}
pos--;
}
}
}
/* Do Power9 dependent reordering if necessary. */ /* Do Power9 dependent reordering if necessary. */
if (rs6000_tune == PROCESSOR_POWER9 && last_scheduled_insn if (rs6000_tune == PROCESSOR_POWER9 && last_scheduled_insn
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment