gccint: Scheduling

1 
1 18.17 Adjusting the Instruction Scheduler
1 =========================================
1 
1 The instruction scheduler may need a fair amount of machine-specific
1 adjustment in order to produce good code.  GCC provides several target
1 hooks for this purpose.  It is usually enough to define just a few of
1 them: try the first ones in this list first.
1 
1  -- Target Hook: int TARGET_SCHED_ISSUE_RATE (void)
1      This hook returns the maximum number of instructions that can ever
1      issue at the same time on the target machine.  The default is one.
1      Although the insn scheduler can define itself the possibility of
1      issue an insn on the same cycle, the value can serve as an
1      additional constraint to issue insns on the same simulated
1      processor cycle (see hooks 'TARGET_SCHED_REORDER' and
1      'TARGET_SCHED_REORDER2').  This value must be constant over the
1      entire compilation.  If you need it to vary depending on what the
1      instructions are, you must use 'TARGET_SCHED_VARIABLE_ISSUE'.
1 
1  -- Target Hook: int TARGET_SCHED_VARIABLE_ISSUE (FILE *FILE, int
1           VERBOSE, rtx_insn *INSN, int MORE)
1      This hook is executed by the scheduler after it has scheduled an
1      insn from the ready list.  It should return the number of insns
1      which can still be issued in the current cycle.  The default is
1      'MORE - 1' for insns other than 'CLOBBER' and 'USE', which normally
1      are not counted against the issue rate.  You should define this
1      hook if some insns take more machine resources than others, so that
1      fewer insns can follow them in the same cycle.  FILE is either a
1      null pointer, or a stdio stream to write any debug output to.
1      VERBOSE is the verbose level provided by '-fsched-verbose-N'.  INSN
1      is the instruction that was scheduled.
1 
1  -- Target Hook: int TARGET_SCHED_ADJUST_COST (rtx_insn *INSN, int
1           DEP_TYPE1, rtx_insn *DEP_INSN, int COST, unsigned int DW)
1      This function corrects the value of COST based on the relationship
1      between INSN and DEP_INSN through a dependence of type dep_type,
1      and strength DW.  It should return the new value.  The default is
1      to make no adjustment to COST.  This can be used for example to
1      specify to the scheduler using the traditional pipeline description
1      that an output- or anti-dependence does not incur the same cost as
1      a data-dependence.  If the scheduler using the automaton based
1      pipeline description, the cost of anti-dependence is zero and the
1      cost of output-dependence is maximum of one and the difference of
1      latency times of the first and the second insns.  If these values
1      are not acceptable, you could use the hook to modify them too.  See
1      also ⇒Processor pipeline description.
1 
1  -- Target Hook: int TARGET_SCHED_ADJUST_PRIORITY (rtx_insn *INSN, int
1           PRIORITY)
1      This hook adjusts the integer scheduling priority PRIORITY of INSN.
1      It should return the new priority.  Increase the priority to
1      execute INSN earlier, reduce the priority to execute INSN later.
1      Do not define this hook if you do not need to adjust the scheduling
1      priorities of insns.
1 
1  -- Target Hook: int TARGET_SCHED_REORDER (FILE *FILE, int VERBOSE,
1           rtx_insn **READY, int *N_READYP, int CLOCK)
1      This hook is executed by the scheduler after it has scheduled the
1      ready list, to allow the machine description to reorder it (for
1      example to combine two small instructions together on 'VLIW'
1      machines).  FILE is either a null pointer, or a stdio stream to
1      write any debug output to.  VERBOSE is the verbose level provided
1      by '-fsched-verbose-N'.  READY is a pointer to the ready list of
1      instructions that are ready to be scheduled.  N_READYP is a pointer
1      to the number of elements in the ready list.  The scheduler reads
1      the ready list in reverse order, starting with READY[*N_READYP - 1]
1      and going to READY[0].  CLOCK is the timer tick of the scheduler.
1      You may modify the ready list and the number of ready insns.  The
1      return value is the number of insns that can issue this cycle;
1      normally this is just 'issue_rate'.  See also
1      'TARGET_SCHED_REORDER2'.
1 
1  -- Target Hook: int TARGET_SCHED_REORDER2 (FILE *FILE, int VERBOSE,
1           rtx_insn **READY, int *N_READYP, int CLOCK)
1      Like 'TARGET_SCHED_REORDER', but called at a different time.  That
1      function is called whenever the scheduler starts a new cycle.  This
1      one is called once per iteration over a cycle, immediately after
1      'TARGET_SCHED_VARIABLE_ISSUE'; it can reorder the ready list and
1      return the number of insns to be scheduled in the same cycle.
1      Defining this hook can be useful if there are frequent situations
1      where scheduling one insn causes other insns to become ready in the
1      same cycle.  These other insns can then be taken into account
1      properly.
1 
1  -- Target Hook: bool TARGET_SCHED_MACRO_FUSION_P (void)
1      This hook is used to check whether target platform supports macro
1      fusion.
1 
1  -- Target Hook: bool TARGET_SCHED_MACRO_FUSION_PAIR_P (rtx_insn *PREV,
1           rtx_insn *CURR)
1      This hook is used to check whether two insns should be macro fused
1      for a target microarchitecture.  If this hook returns true for the
1      given insn pair (PREV and CURR), the scheduler will put them into a
1      sched group, and they will not be scheduled apart.  The two insns
1      will be either two SET insns or a compare and a conditional jump
1      and this hook should validate any dependencies needed to fuse the
1      two insns together.
1 
1  -- Target Hook: void TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK
1           (rtx_insn *HEAD, rtx_insn *TAIL)
1      This hook is called after evaluation forward dependencies of insns
1      in chain given by two parameter values (HEAD and TAIL
1      correspondingly) but before insns scheduling of the insn chain.
1      For example, it can be used for better insn classification if it
1      requires analysis of dependencies.  This hook can use backward and
1      forward dependencies of the insn scheduler because they are already
1      calculated.
1 
1  -- Target Hook: void TARGET_SCHED_INIT (FILE *FILE, int VERBOSE, int
1           MAX_READY)
1      This hook is executed by the scheduler at the beginning of each
1      block of instructions that are to be scheduled.  FILE is either a
1      null pointer, or a stdio stream to write any debug output to.
1      VERBOSE is the verbose level provided by '-fsched-verbose-N'.
1      MAX_READY is the maximum number of insns in the current scheduling
1      region that can be live at the same time.  This can be used to
1      allocate scratch space if it is needed, e.g. by
1      'TARGET_SCHED_REORDER'.
1 
1  -- Target Hook: void TARGET_SCHED_FINISH (FILE *FILE, int VERBOSE)
1      This hook is executed by the scheduler at the end of each block of
1      instructions that are to be scheduled.  It can be used to perform
1      cleanup of any actions done by the other scheduling hooks.  FILE is
1      either a null pointer, or a stdio stream to write any debug output
1      to.  VERBOSE is the verbose level provided by '-fsched-verbose-N'.
1 
1  -- Target Hook: void TARGET_SCHED_INIT_GLOBAL (FILE *FILE, int VERBOSE,
1           int OLD_MAX_UID)
1      This hook is executed by the scheduler after function level
1      initializations.  FILE is either a null pointer, or a stdio stream
1      to write any debug output to.  VERBOSE is the verbose level
1      provided by '-fsched-verbose-N'.  OLD_MAX_UID is the maximum insn
1      uid when scheduling begins.
1 
1  -- Target Hook: void TARGET_SCHED_FINISH_GLOBAL (FILE *FILE, int
1           VERBOSE)
1      This is the cleanup hook corresponding to
1      'TARGET_SCHED_INIT_GLOBAL'.  FILE is either a null pointer, or a
1      stdio stream to write any debug output to.  VERBOSE is the verbose
1      level provided by '-fsched-verbose-N'.
1 
1  -- Target Hook: rtx TARGET_SCHED_DFA_PRE_CYCLE_INSN (void)
1      The hook returns an RTL insn.  The automaton state used in the
1      pipeline hazard recognizer is changed as if the insn were scheduled
1      when the new simulated processor cycle starts.  Usage of the hook
1      may simplify the automaton pipeline description for some VLIW
1      processors.  If the hook is defined, it is used only for the
1      automaton based pipeline description.  The default is not to change
1      the state when the new simulated processor cycle starts.
1 
1  -- Target Hook: void TARGET_SCHED_INIT_DFA_PRE_CYCLE_INSN (void)
1      The hook can be used to initialize data used by the previous hook.
1 
1  -- Target Hook: rtx_insn * TARGET_SCHED_DFA_POST_CYCLE_INSN (void)
1      The hook is analogous to 'TARGET_SCHED_DFA_PRE_CYCLE_INSN' but used
1      to changed the state as if the insn were scheduled when the new
1      simulated processor cycle finishes.
1 
1  -- Target Hook: void TARGET_SCHED_INIT_DFA_POST_CYCLE_INSN (void)
1      The hook is analogous to 'TARGET_SCHED_INIT_DFA_PRE_CYCLE_INSN' but
1      used to initialize data used by the previous hook.
1 
1  -- Target Hook: void TARGET_SCHED_DFA_PRE_ADVANCE_CYCLE (void)
1      The hook to notify target that the current simulated cycle is about
1      to finish.  The hook is analogous to
1      'TARGET_SCHED_DFA_PRE_CYCLE_INSN' but used to change the state in
1      more complicated situations - e.g., when advancing state on a
1      single insn is not enough.
1 
1  -- Target Hook: void TARGET_SCHED_DFA_POST_ADVANCE_CYCLE (void)
1      The hook to notify target that new simulated cycle has just
1      started.  The hook is analogous to
1      'TARGET_SCHED_DFA_POST_CYCLE_INSN' but used to change the state in
1      more complicated situations - e.g., when advancing state on a
1      single insn is not enough.
1 
1  -- Target Hook: int TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
1           (void)
1      This hook controls better choosing an insn from the ready insn
1      queue for the DFA-based insn scheduler.  Usually the scheduler
1      chooses the first insn from the queue.  If the hook returns a
1      positive value, an additional scheduler code tries all permutations
1      of 'TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD ()' subsequent
1      ready insns to choose an insn whose issue will result in maximal
1      number of issued insns on the same cycle.  For the VLIW processor,
1      the code could actually solve the problem of packing simple insns
1      into the VLIW insn.  Of course, if the rules of VLIW packing are
1      described in the automaton.
1 
1      This code also could be used for superscalar RISC processors.  Let
1      us consider a superscalar RISC processor with 3 pipelines.  Some
1      insns can be executed in pipelines A or B, some insns can be
1      executed only in pipelines B or C, and one insn can be executed in
1      pipeline B.  The processor may issue the 1st insn into A and the
1      2nd one into B.  In this case, the 3rd insn will wait for freeing B
1      until the next cycle.  If the scheduler issues the 3rd insn the
1      first, the processor could issue all 3 insns per cycle.
1 
1      Actually this code demonstrates advantages of the automaton based
1      pipeline hazard recognizer.  We try quickly and easy many insn
1      schedules to choose the best one.
1 
1      The default is no multipass scheduling.
1 
1  -- Target Hook: int
1           TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD
1           (rtx_insn *INSN, int READY_INDEX)
1 
1      This hook controls what insns from the ready insn queue will be
1      considered for the multipass insn scheduling.  If the hook returns
1      zero for INSN, the insn will be considered in multipass scheduling.
1      Positive return values will remove INSN from consideration on the
1      current round of multipass scheduling.  Negative return values will
1      remove INSN from consideration for given number of cycles.
1      Backends should be careful about returning non-zero for highest
1      priority instruction at position 0 in the ready list.  READY_INDEX
1      is passed to allow backends make correct judgements.
1 
1      The default is that any ready insns can be chosen to be issued.
1 
1  -- Target Hook: void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_BEGIN (void
1           *DATA, signed char *READY_TRY, int N_READY, bool
1           FIRST_CYCLE_INSN_P)
1      This hook prepares the target backend for a new round of multipass
1      scheduling.
1 
1  -- Target Hook: void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_ISSUE (void
1           *DATA, signed char *READY_TRY, int N_READY, rtx_insn *INSN,
1           const void *PREV_DATA)
1      This hook is called when multipass scheduling evaluates instruction
1      INSN.
1 
1  -- Target Hook: void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_BACKTRACK
1           (const void *DATA, signed char *READY_TRY, int N_READY)
1      This is called when multipass scheduling backtracks from evaluation
1      of an instruction.
1 
1  -- Target Hook: void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_END (const void
1           *DATA)
1      This hook notifies the target about the result of the concluded
1      current round of multipass scheduling.
1 
1  -- Target Hook: void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_INIT (void
1           *DATA)
1      This hook initializes target-specific data used in multipass
1      scheduling.
1 
1  -- Target Hook: void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_FINI (void
1           *DATA)
1      This hook finalizes target-specific data used in multipass
1      scheduling.
1 
1  -- Target Hook: int TARGET_SCHED_DFA_NEW_CYCLE (FILE *DUMP, int
1           VERBOSE, rtx_insn *INSN, int LAST_CLOCK, int CLOCK, int
1           *SORT_P)
1      This hook is called by the insn scheduler before issuing INSN on
1      cycle CLOCK.  If the hook returns nonzero, INSN is not issued on
1      this processor cycle.  Instead, the processor cycle is advanced.
1      If *SORT_P is zero, the insn ready queue is not sorted on the new
1      cycle start as usually.  DUMP and VERBOSE specify the file and
1      verbosity level to use for debugging output.  LAST_CLOCK and CLOCK
1      are, respectively, the processor cycle on which the previous insn
1      has been issued, and the current processor cycle.
1 
1  -- Target Hook: bool TARGET_SCHED_IS_COSTLY_DEPENDENCE (struct _dep
1           *_DEP, int COST, int DISTANCE)
1      This hook is used to define which dependences are considered costly
1      by the target, so costly that it is not advisable to schedule the
1      insns that are involved in the dependence too close to one another.
1      The parameters to this hook are as follows: The first parameter
1      _DEP is the dependence being evaluated.  The second parameter COST
1      is the cost of the dependence as estimated by the scheduler, and
1      the third parameter DISTANCE is the distance in cycles between the
1      two insns.  The hook returns 'true' if considering the distance
1      between the two insns the dependence between them is considered
1      costly by the target, and 'false' otherwise.
1 
1      Defining this hook can be useful in multiple-issue out-of-order
1      machines, where (a) it's practically hopeless to predict the actual
1      data/resource delays, however: (b) there's a better chance to
1      predict the actual grouping that will be formed, and (c) correctly
1      emulating the grouping can be very important.  In such targets one
1      may want to allow issuing dependent insns closer to one
1      another--i.e., closer than the dependence distance; however, not in
1      cases of "costly dependences", which this hooks allows to define.
1 
1  -- Target Hook: void TARGET_SCHED_H_I_D_EXTENDED (void)
1      This hook is called by the insn scheduler after emitting a new
1      instruction to the instruction stream.  The hook notifies a target
1      backend to extend its per instruction data structures.
1 
1  -- Target Hook: void * TARGET_SCHED_ALLOC_SCHED_CONTEXT (void)
1      Return a pointer to a store large enough to hold target scheduling
1      context.
1 
1  -- Target Hook: void TARGET_SCHED_INIT_SCHED_CONTEXT (void *TC, bool
1           CLEAN_P)
1      Initialize store pointed to by TC to hold target scheduling
1      context.  It CLEAN_P is true then initialize TC as if scheduler is
1      at the beginning of the block.  Otherwise, copy the current context
1      into TC.
1 
1  -- Target Hook: void TARGET_SCHED_SET_SCHED_CONTEXT (void *TC)
1      Copy target scheduling context pointed to by TC to the current
1      context.
1 
1  -- Target Hook: void TARGET_SCHED_CLEAR_SCHED_CONTEXT (void *TC)
1      Deallocate internal data in target scheduling context pointed to by
1      TC.
1 
1  -- Target Hook: void TARGET_SCHED_FREE_SCHED_CONTEXT (void *TC)
1      Deallocate a store for target scheduling context pointed to by TC.
1 
1  -- Target Hook: int TARGET_SCHED_SPECULATE_INSN (rtx_insn *INSN,
1           unsigned int DEP_STATUS, rtx *NEW_PAT)
1      This hook is called by the insn scheduler when INSN has only
1      speculative dependencies and therefore can be scheduled
1      speculatively.  The hook is used to check if the pattern of INSN
1      has a speculative version and, in case of successful check, to
1      generate that speculative pattern.  The hook should return 1, if
1      the instruction has a speculative form, or -1, if it doesn't.
1      REQUEST describes the type of requested speculation.  If the return
1      value equals 1 then NEW_PAT is assigned the generated speculative
1      pattern.
1 
1  -- Target Hook: bool TARGET_SCHED_NEEDS_BLOCK_P (unsigned int
1           DEP_STATUS)
1      This hook is called by the insn scheduler during generation of
1      recovery code for INSN.  It should return 'true', if the
1      corresponding check instruction should branch to recovery code, or
1      'false' otherwise.
1 
1  -- Target Hook: rtx TARGET_SCHED_GEN_SPEC_CHECK (rtx_insn *INSN,
1           rtx_insn *LABEL, unsigned int DS)
1      This hook is called by the insn scheduler to generate a pattern for
1      recovery check instruction.  If MUTATE_P is zero, then INSN is a
1      speculative instruction for which the check should be generated.
1      LABEL is either a label of a basic block, where recovery code
1      should be emitted, or a null pointer, when requested check doesn't
1      branch to recovery code (a simple check).  If MUTATE_P is nonzero,
1      then a pattern for a branchy check corresponding to a simple check
1      denoted by INSN should be generated.  In this case LABEL can't be
1      null.
1 
1  -- Target Hook: void TARGET_SCHED_SET_SCHED_FLAGS (struct spec_info_def
1           *SPEC_INFO)
1      This hook is used by the insn scheduler to find out what features
1      should be enabled/used.  The structure *SPEC_INFO should be filled
1      in by the target.  The structure describes speculation types that
1      can be used in the scheduler.
1 
1  -- Target Hook: bool TARGET_SCHED_CAN_SPECULATE_INSN (rtx_insn *INSN)
1      Some instructions should never be speculated by the schedulers,
1      usually because the instruction is too expensive to get this wrong.
1      Often such instructions have long latency, and often they are not
1      fully modeled in the pipeline descriptions.  This hook should
1      return 'false' if INSN should not be speculated.
1 
1  -- Target Hook: int TARGET_SCHED_SMS_RES_MII (struct ddg *G)
1      This hook is called by the swing modulo scheduler to calculate a
1      resource-based lower bound which is based on the resources
1      available in the machine and the resources required by each
1      instruction.  The target backend can use G to calculate such bound.
1      A very simple lower bound will be used in case this hook is not
1      implemented: the total number of instructions divided by the issue
1      rate.
1 
1  -- Target Hook: bool TARGET_SCHED_DISPATCH (rtx_insn *INSN, int X)
1      This hook is called by Haifa Scheduler.  It returns true if
1      dispatch scheduling is supported in hardware and the condition
1      specified in the parameter is true.
1 
1  -- Target Hook: void TARGET_SCHED_DISPATCH_DO (rtx_insn *INSN, int X)
1      This hook is called by Haifa Scheduler.  It performs the operation
1      specified in its second parameter.
1 
1  -- Target Hook: bool TARGET_SCHED_EXPOSED_PIPELINE
1      True if the processor has an exposed pipeline, which means that not
1      just the order of instructions is important for correctness when
1      scheduling, but also the latencies of operations.
1 
1  -- Target Hook: int TARGET_SCHED_REASSOCIATION_WIDTH (unsigned int OPC,
1           machine_mode MODE)
1      This hook is called by tree reassociator to determine a level of
1      parallelism required in output calculations chain.
1 
1  -- Target Hook: void TARGET_SCHED_FUSION_PRIORITY (rtx_insn *INSN, int
1           MAX_PRI, int *FUSION_PRI, int *PRI)
1      This hook is called by scheduling fusion pass.  It calculates
1      fusion priorities for each instruction passed in by parameter.  The
1      priorities are returned via pointer parameters.
1 
1      INSN is the instruction whose priorities need to be calculated.
1      MAX_PRI is the maximum priority can be returned in any cases.
1      FUSION_PRI is the pointer parameter through which INSN's fusion
1      priority should be calculated and returned.  PRI is the pointer
1      parameter through which INSN's priority should be calculated and
1      returned.
1 
1      Same FUSION_PRI should be returned for instructions which should be
1      scheduled together.  Different PRI should be returned for
1      instructions with same FUSION_PRI.  FUSION_PRI is the major sort
1      key, PRI is the minor sort key.  All instructions will be scheduled
1      according to the two priorities.  All priorities calculated should
1      be between 0 (exclusive) and MAX_PRI (inclusive).  To avoid false
1      dependencies, FUSION_PRI of instructions which need to be scheduled
1      together should be smaller than FUSION_PRI of irrelevant
1      instructions.
1 
1      Given below example:
1 
1               ldr r10, [r1, 4]
1               add r4, r4, r10
1               ldr r15, [r2, 8]
1               sub r5, r5, r15
1               ldr r11, [r1, 0]
1               add r4, r4, r11
1               ldr r16, [r2, 12]
1               sub r5, r5, r16
1 
1      On targets like ARM/AArch64, the two pairs of consecutive loads
1      should be merged.  Since peephole2 pass can't help in this case
1      unless consecutive loads are actually next to each other in
1      instruction flow.  That's where this scheduling fusion pass works.
1      This hook calculates priority for each instruction based on its
1      fustion type, like:
1 
1               ldr r10, [r1, 4]  ; fusion_pri=99,  pri=96
1               add r4, r4, r10   ; fusion_pri=100, pri=100
1               ldr r15, [r2, 8]  ; fusion_pri=98,  pri=92
1               sub r5, r5, r15   ; fusion_pri=100, pri=100
1               ldr r11, [r1, 0]  ; fusion_pri=99,  pri=100
1               add r4, r4, r11   ; fusion_pri=100, pri=100
1               ldr r16, [r2, 12] ; fusion_pri=98,  pri=88
1               sub r5, r5, r16   ; fusion_pri=100, pri=100
1 
1      Scheduling fusion pass then sorts all ready to issue instructions
1      according to the priorities.  As a result, instructions of same
1      fusion type will be pushed together in instruction flow, like:
1 
1               ldr r11, [r1, 0]
1               ldr r10, [r1, 4]
1               ldr r15, [r2, 8]
1               ldr r16, [r2, 12]
1               add r4, r4, r10
1               sub r5, r5, r15
1               add r4, r4, r11
1               sub r5, r5, r16
1 
1      Now peephole2 pass can simply merge the two pairs of loads.
1 
1      Since scheduling fusion pass relies on peephole2 to do real fusion
1      work, it is only enabled by default when peephole2 is in effect.
1 
1      This is firstly introduced on ARM/AArch64 targets, please refer to
1      the hook implementation for how different fusion types are
1      supported.
1 
1  -- Target Hook: void TARGET_EXPAND_DIVMOD_LIBFUNC (rtx LIBFUNC,
1           machine_mode MODE, rtx OP0, rtx OP1, rtx *QUOT, rtx *REM)
1      Define this hook for enabling divmod transform if the port does not
1      have hardware divmod insn but defines target-specific divmod
1      libfuncs.
1