static int divide_cnt;
/* The following variable helps pair and alternate vector and vector load
insns during scheduling. */
-static int vec_load_pendulum;
+static int vec_pairing;
/* Power4 load update and store update instructions are cracked into a
int pos;
int i;
rtx_insn *tmp;
- enum attr_type type;
+ enum attr_type type, type2;
type = get_attr_type (last_scheduled_insn);
/* Last insn was the 2nd divide or not a divide, reset the counter. */
divide_cnt = 0;
- /* Power9 can execute 2 vector operations and 2 vector loads in a single
- cycle. So try to pair up and alternate groups of vector and vector
- load instructions.
-
- To aid this formation, a counter is maintained to keep track of
- vec/vecload insns issued. The value of vec_load_pendulum maintains
- the current state with the following values:
-
- 0 : Initial state, no vec/vecload group has been started.
-
- -1 : 1 vector load has been issued and another has been found on
- the ready list and moved to the end.
-
- -2 : 2 vector loads have been issued and a vector operation has
- been found and moved to the end of the ready list.
-
- -3 : 2 vector loads and a vector insn have been issued and a
- vector operation has been found and moved to the end of the
- ready list.
+ /* The best dispatch throughput for vector and vector load insns can be
+ achieved by interleaving a vector and vector load such that they'll
+ dispatch to the same superslice. If this pairing cannot be achieved
+ then it is best to pair vector insns together and vector load insns
+ together.
- 1 : 1 vector insn has been issued and another has been found and
- moved to the end of the ready list.
+ To aid in this pairing, vec_pairing maintains the current state with
+ the following values:
- 2 : 2 vector insns have been issued and a vector load has been
- found and moved to the end of the ready list.
+ 0 : Initial state, no vecload/vector pairing has been started.
- 3 : 2 vector insns and a vector load have been issued and another
- vector load has been found and moved to the end of the ready
+ 1 : A vecload or vector insn has been issued and a candidate for
+ pairing has been found and moved to the end of the ready
list. */
if (type == TYPE_VECLOAD)
{
/* Issued a vecload. */
- if (vec_load_pendulum == 0)
+ if (vec_pairing == 0)
{
- /* We issued a single vecload, look for another and move it to
- the end of the ready list so it will be scheduled next.
- Set pendulum if found. */
+ int vecload_pos = -1;
+ /* We issued a single vecload, look for a vector insn to pair it
+ with. If one isn't found, try to pair another vecload. */
pos = lastpos;
while (pos >= 0)
{
- if (recog_memoized (ready[pos]) >= 0
- && get_attr_type (ready[pos]) == TYPE_VECLOAD)
+ if (recog_memoized (ready[pos]) >= 0)
{
- tmp = ready[pos];
- for (i = pos; i < lastpos; i++)
- ready[i] = ready[i + 1];
- ready[lastpos] = tmp;
- vec_load_pendulum = -1;
- return cached_can_issue_more;
+ type2 = get_attr_type (ready[pos]);
+ if (is_power9_pairable_vec_type (type2))
+ {
+ /* Found a vector insn to pair with, move it to the
+ end of the ready list so it is scheduled next. */
+ tmp = ready[pos];
+ for (i = pos; i < lastpos; i++)
+ ready[i] = ready[i + 1];
+ ready[lastpos] = tmp;
+ vec_pairing = 1;
+ return cached_can_issue_more;
+ }
+ else if (type2 == TYPE_VECLOAD && vecload_pos == -1)
+ /* Remember position of first vecload seen. */
+ vecload_pos = pos;
}
pos--;
}
- }
- else if (vec_load_pendulum == -1)
- {
- /* This is the second vecload we've issued, search the ready
- list for a vector operation so we can try to schedule a
- pair of those next. If found move to the end of the ready
- list so it is scheduled next and set the pendulum. */
- pos = lastpos;
- while (pos >= 0)
+ if (vecload_pos >= 0)
{
- if (recog_memoized (ready[pos]) >= 0
- && is_power9_pairable_vec_type (
- get_attr_type (ready[pos])))
- {
- tmp = ready[pos];
- for (i = pos; i < lastpos; i++)
- ready[i] = ready[i + 1];
- ready[lastpos] = tmp;
- vec_load_pendulum = -2;
- return cached_can_issue_more;
- }
- pos--;
- }
- }
- else if (vec_load_pendulum == 2)
- {
- /* Two vector ops have been issued and we've just issued a
- vecload, look for another vecload and move to end of ready
- list if found. */
- pos = lastpos;
- while (pos >= 0)
- {
- if (recog_memoized (ready[pos]) >= 0
- && get_attr_type (ready[pos]) == TYPE_VECLOAD)
- {
- tmp = ready[pos];
- for (i = pos; i < lastpos; i++)
- ready[i] = ready[i + 1];
- ready[lastpos] = tmp;
- /* Set pendulum so that next vecload will be seen as
- finishing a group, not start of one. */
- vec_load_pendulum = 3;
- return cached_can_issue_more;
- }
- pos--;
+ /* Didn't find a vector to pair with but did find a vecload,
+ move it to the end of the ready list. */
+ tmp = ready[vecload_pos];
+ for (i = vecload_pos; i < lastpos; i++)
+ ready[i] = ready[i + 1];
+ ready[lastpos] = tmp;
+ vec_pairing = 1;
+ return cached_can_issue_more;
}
}
}
else if (is_power9_pairable_vec_type (type))
{
/* Issued a vector operation. */
- if (vec_load_pendulum == 0)
- /* We issued a single vec op, look for another and move it
- to the end of the ready list so it will be scheduled next.
- Set pendulum if found. */
- {
- pos = lastpos;
- while (pos >= 0)
- {
- if (recog_memoized (ready[pos]) >= 0
- && is_power9_pairable_vec_type (
- get_attr_type (ready[pos])))
- {
- tmp = ready[pos];
- for (i = pos; i < lastpos; i++)
- ready[i] = ready[i + 1];
- ready[lastpos] = tmp;
- vec_load_pendulum = 1;
- return cached_can_issue_more;
- }
- pos--;
- }
- }
- else if (vec_load_pendulum == 1)
+ if (vec_pairing == 0)
{
- /* This is the second vec op we've issued, search the ready
- list for a vecload operation so we can try to schedule a
- pair of those next. If found move to the end of the ready
- list so it is scheduled next and set the pendulum. */
+ int vec_pos = -1;
+ /* We issued a single vector insn, look for a vecload to pair it
+ with. If one isn't found, try to pair another vector. */
pos = lastpos;
while (pos >= 0)
{
- if (recog_memoized (ready[pos]) >= 0
- && get_attr_type (ready[pos]) == TYPE_VECLOAD)
+ if (recog_memoized (ready[pos]) >= 0)
{
- tmp = ready[pos];
- for (i = pos; i < lastpos; i++)
- ready[i] = ready[i + 1];
- ready[lastpos] = tmp;
- vec_load_pendulum = 2;
- return cached_can_issue_more;
+ type2 = get_attr_type (ready[pos]);
+ if (type2 == TYPE_VECLOAD)
+ {
+ /* Found a vecload insn to pair with, move it to the
+ end of the ready list so it is scheduled next. */
+ tmp = ready[pos];
+ for (i = pos; i < lastpos; i++)
+ ready[i] = ready[i + 1];
+ ready[lastpos] = tmp;
+ vec_pairing = 1;
+ return cached_can_issue_more;
+ }
+ else if (is_power9_pairable_vec_type (type2)
+ && vec_pos == -1)
+ /* Remember position of first vector insn seen. */
+ vec_pos = pos;
}
pos--;
}
- }
- else if (vec_load_pendulum == -2)
- {
- /* Two vecload ops have been issued and we've just issued a
- vec op, look for another vec op and move to end of ready
- list if found. */
- pos = lastpos;
- while (pos >= 0)
+ if (vec_pos >= 0)
{
- if (recog_memoized (ready[pos]) >= 0
- && is_power9_pairable_vec_type (
- get_attr_type (ready[pos])))
- {
- tmp = ready[pos];
- for (i = pos; i < lastpos; i++)
- ready[i] = ready[i + 1];
- ready[lastpos] = tmp;
- /* Set pendulum so that next vec op will be seen as
- finishing a group, not start of one. */
- vec_load_pendulum = -3;
- return cached_can_issue_more;
- }
- pos--;
+ /* Didn't find a vecload to pair with but did find a vector
+ insn, move it to the end of the ready list. */
+ tmp = ready[vec_pos];
+ for (i = vec_pos; i < lastpos; i++)
+ ready[i] = ready[i + 1];
+ ready[lastpos] = tmp;
+ vec_pairing = 1;
+ return cached_can_issue_more;
}
}
}
- /* We've either finished a vec/vecload group, couldn't find an insn to
- continue the current group, or the last insn had nothing to do with
- with a group. In any case, reset the pendulum. */
- vec_load_pendulum = 0;
+ /* We've either finished a vec/vecload pair, couldn't find an insn to
+ continue the current pair, or the last insn had nothing to do with
+ with pairing. In any case, reset the state. */
+ vec_pairing = 0;
}
return cached_can_issue_more;
last_scheduled_insn = NULL;
load_store_pendulum = 0;
divide_cnt = 0;
- vec_load_pendulum = 0;
+ vec_pairing = 0;
}
/* The following function is called at the end of scheduling BB.
rtx_insn *last_scheduled_insn;
int load_store_pendulum;
int divide_cnt;
- int vec_load_pendulum;
+ int vec_pairing;
};
typedef struct rs6000_sched_context rs6000_sched_context_def;
sc->last_scheduled_insn = NULL;
sc->load_store_pendulum = 0;
sc->divide_cnt = 0;
- sc->vec_load_pendulum = 0;
+ sc->vec_pairing = 0;
}
else
{
sc->last_scheduled_insn = last_scheduled_insn;
sc->load_store_pendulum = load_store_pendulum;
sc->divide_cnt = divide_cnt;
- sc->vec_load_pendulum = vec_load_pendulum;
+ sc->vec_pairing = vec_pairing;
}
}
last_scheduled_insn = sc->last_scheduled_insn;
load_store_pendulum = sc->load_store_pendulum;
divide_cnt = sc->divide_cnt;
- vec_load_pendulum = sc->vec_load_pendulum;
+ vec_pairing = sc->vec_pairing;
}
/* Free _SC. */