-/* Compute the function units used by INSN. This caches the value
- returned by function_units_used. A function unit is encoded as the
- unit number if the value is non-negative and the compliment of a
- mask if the value is negative. A function unit index is the
- non-negative encoding. */
-
-HAIFA_INLINE int
-insn_unit (insn)
- rtx insn;
-{
- register int unit = INSN_UNIT (insn);
-
- if (unit == 0)
- {
- recog_memoized (insn);
-
- /* A USE insn, or something else we don't need to understand.
- We can't pass these directly to function_units_used because it will
- trigger a fatal error for unrecognizable insns. */
- if (INSN_CODE (insn) < 0)
- unit = -1;
- else
- {
- unit = function_units_used (insn);
- /* Increment non-negative values so we can cache zero. */
- if (unit >= 0)
- unit++;
- }
- /* We only cache 16 bits of the result, so if the value is out of
- range, don't cache it. */
- if (FUNCTION_UNITS_SIZE < HOST_BITS_PER_SHORT
- || unit >= 0
- || (unit & ~((1 << (HOST_BITS_PER_SHORT - 1)) - 1)) == 0)
- INSN_UNIT (insn) = unit;
- }
- return (unit > 0 ? unit - 1 : unit);
-}
-
-/* Compute the blockage range for executing INSN on UNIT. This caches
- the value returned by the blockage_range_function for the unit.
- These values are encoded in an int where the upper half gives the
- minimum value and the lower half gives the maximum value. */
-
-HAIFA_INLINE static unsigned int
-blockage_range (unit, insn)
- int unit;
- rtx insn;
-{
- unsigned int blockage = INSN_BLOCKAGE (insn);
- unsigned int range;
-
- if ((int) UNIT_BLOCKED (blockage) != unit + 1)
- {
- range = function_units[unit].blockage_range_function (insn);
- /* We only cache the blockage range for one unit and then only if
- the values fit. */
- if (HOST_BITS_PER_INT >= UNIT_BITS + 2 * BLOCKAGE_BITS)
- INSN_BLOCKAGE (insn) = ENCODE_BLOCKAGE (unit + 1, range);
- }
- else
- range = BLOCKAGE_RANGE (blockage);
-
- return range;
-}
-
-/* A vector indexed by function unit instance giving the last insn to use
- the unit. The value of the function unit instance index for unit U
- instance I is (U + I * FUNCTION_UNITS_SIZE). */
-static rtx unit_last_insn[FUNCTION_UNITS_SIZE * MAX_MULTIPLICITY];
-
-/* A vector indexed by function unit instance giving the minimum time when
- the unit will unblock based on the maximum blockage cost. */
-static int unit_tick[FUNCTION_UNITS_SIZE * MAX_MULTIPLICITY];
-
-/* A vector indexed by function unit number giving the number of insns
- that remain to use the unit. */
-static int unit_n_insns[FUNCTION_UNITS_SIZE];
-
-/* Access the unit_last_insn array. Used by the visualization code. */
-
-rtx
-get_unit_last_insn (instance)
- int instance;
-{
- return unit_last_insn[instance];
-}
-
-/* Reset the function unit state to the null state. */
-
-static void
-clear_units ()
-{
- memset ((char *) unit_last_insn, 0, sizeof (unit_last_insn));
- memset ((char *) unit_tick, 0, sizeof (unit_tick));
- memset ((char *) unit_n_insns, 0, sizeof (unit_n_insns));
-}
-
-/* Return the issue-delay of an insn. */
-
-HAIFA_INLINE int
-insn_issue_delay (insn)
- rtx insn;
-{
- int i, delay = 0;
- int unit = insn_unit (insn);
-
- /* Efficiency note: in fact, we are working 'hard' to compute a
- value that was available in md file, and is not available in
- function_units[] structure. It would be nice to have this
- value there, too. */
- if (unit >= 0)
- {
- if (function_units[unit].blockage_range_function &&
- function_units[unit].blockage_function)
- delay = function_units[unit].blockage_function (insn, insn);
- }
- else
- for (i = 0, unit = ~unit; unit; i++, unit >>= 1)
- if ((unit & 1) != 0 && function_units[i].blockage_range_function
- && function_units[i].blockage_function)
- delay = MAX (delay, function_units[i].blockage_function (insn, insn));
-
- return delay;
-}
-
-/* Return the actual hazard cost of executing INSN on the unit UNIT,
- instance INSTANCE at time CLOCK if the previous actual hazard cost
- was COST. */
-
-HAIFA_INLINE int
-actual_hazard_this_instance (unit, instance, insn, clock, cost)
- int unit, instance, clock, cost;
- rtx insn;
-{
- int tick = unit_tick[instance]; /* Issue time of the last issued insn. */
-
- if (tick - clock > cost)
- {
- /* The scheduler is operating forward, so unit's last insn is the
- executing insn and INSN is the candidate insn. We want a
- more exact measure of the blockage if we execute INSN at CLOCK
- given when we committed the execution of the unit's last insn.
-
- The blockage value is given by either the unit's max blockage
- constant, blockage range function, or blockage function. Use
- the most exact form for the given unit. */
-
- if (function_units[unit].blockage_range_function)
- {
- if (function_units[unit].blockage_function)
- tick += (function_units[unit].blockage_function
- (unit_last_insn[instance], insn)
- - function_units[unit].max_blockage);
- else
- tick += ((int) MAX_BLOCKAGE_COST (blockage_range (unit, insn))
- - function_units[unit].max_blockage);
- }
- if (tick - clock > cost)
- cost = tick - clock;
- }
- return cost;
-}
-
-/* Record INSN as having begun execution on the units encoded by UNIT at
- time CLOCK. */
-
-HAIFA_INLINE static void
-schedule_unit (unit, insn, clock)
- int unit, clock;
- rtx insn;
-{
- int i;
-
- if (unit >= 0)
- {
- int instance = unit;
-#if MAX_MULTIPLICITY > 1
- /* Find the first free instance of the function unit and use that
- one. We assume that one is free. */
- for (i = function_units[unit].multiplicity - 1; i > 0; i--)
- {
- if (!actual_hazard_this_instance (unit, instance, insn, clock, 0))
- break;
- instance += FUNCTION_UNITS_SIZE;
- }
-#endif
- unit_last_insn[instance] = insn;
- unit_tick[instance] = (clock + function_units[unit].max_blockage);
- }
- else
- for (i = 0, unit = ~unit; unit; i++, unit >>= 1)
- if ((unit & 1) != 0)
- schedule_unit (i, insn, clock);
-}
-
-/* Return the actual hazard cost of executing INSN on the units encoded by
- UNIT at time CLOCK if the previous actual hazard cost was COST. */
-
-HAIFA_INLINE static int
-actual_hazard (unit, insn, clock, cost)
- int unit, clock, cost;
- rtx insn;
-{
- int i;
-
- if (unit >= 0)
- {
- /* Find the instance of the function unit with the minimum hazard. */
- int instance = unit;
- int best_cost = actual_hazard_this_instance (unit, instance, insn,
- clock, cost);
-#if MAX_MULTIPLICITY > 1
- int this_cost;
-
- if (best_cost > cost)
- {
- for (i = function_units[unit].multiplicity - 1; i > 0; i--)
- {
- instance += FUNCTION_UNITS_SIZE;
- this_cost = actual_hazard_this_instance (unit, instance, insn,
- clock, cost);
- if (this_cost < best_cost)
- {
- best_cost = this_cost;
- if (this_cost <= cost)
- break;
- }
- }
- }
-#endif
- cost = MAX (cost, best_cost);
- }
- else
- for (i = 0, unit = ~unit; unit; i++, unit >>= 1)
- if ((unit & 1) != 0)
- cost = actual_hazard (i, insn, clock, cost);
-
- return cost;
-}
-
-/* Return the potential hazard cost of executing an instruction on the
- units encoded by UNIT if the previous potential hazard cost was COST.
- An insn with a large blockage time is chosen in preference to one
- with a smaller time; an insn that uses a unit that is more likely
- to be used is chosen in preference to one with a unit that is less
- used. We are trying to minimize a subsequent actual hazard. */
-
-HAIFA_INLINE static int
-potential_hazard (unit, insn, cost)
- int unit, cost;
- rtx insn;
-{
- int i, ncost;
- unsigned int minb, maxb;
-
- if (unit >= 0)
- {
- minb = maxb = function_units[unit].max_blockage;
- if (maxb > 1)
- {
- if (function_units[unit].blockage_range_function)
- {
- maxb = minb = blockage_range (unit, insn);
- maxb = MAX_BLOCKAGE_COST (maxb);
- minb = MIN_BLOCKAGE_COST (minb);
- }
-
- if (maxb > 1)
- {
- /* Make the number of instructions left dominate. Make the
- minimum delay dominate the maximum delay. If all these
- are the same, use the unit number to add an arbitrary
- ordering. Other terms can be added. */
- ncost = minb * 0x40 + maxb;
- ncost *= (unit_n_insns[unit] - 1) * 0x1000 + unit;
- if (ncost > cost)
- cost = ncost;
- }
- }
- }
- else
- for (i = 0, unit = ~unit; unit; i++, unit >>= 1)
- if ((unit & 1) != 0)
- cost = potential_hazard (i, insn, cost);
-
- return cost;
-}
-