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