Next: , Previous: Costs, Up: Target Macros


17.18 调整指令调度器

指令调度器可能需要一些机器特定的调整,来产生好的代码。GCC为此提供了几个target钩子。通常定义它们的一部分就足够了:先尝试该列表中最前面的。

— Target Hook: int TARGET_SCHED_ISSUE_RATE (void)

该钩子返回在target机器上同一时间可以发射的最大指令数目。缺省为1。 虽然insn调度器本身可以定义同一周期发射一个insn的可能能性, 但该值可以作为额外的约束,用于相同模拟处理器周期的insn发射 (参见钩子‘TARGET_SCHED_REORDER’和‘TARGET_SCHED_REORDER2’)。 该值在整个编译过程中必须为常量。如果你需要其依赖指令是什么而变化, 则必须使用‘TARGET_SCHED_VARIABLE_ISSUE’。

— Target Hook: int TARGET_SCHED_VARIABLE_ISSUE (FILE *file, int verbose, rtx insn, int more)

该钩子在调度器从就绪列表中调度了一个insn之后被执行。 其应该返回在当前周期仍然可以被发射的insn数目。 对于CLOBBERUSE之外的insn,缺省为‘more - 1’, 其通常不根据发射频率来计数。你应该定义该钩子, 如果一些insn比其它的需要更多的机器资源, 使得在同一周期它们后面可以跟随较少的insn。file或者为一个null指针, 或者一个stdio流,用来写入调试输出。 verbose-fsched-verbose-n提供的详细级别。 insn为被调度的指针。

— Target Hook: int TARGET_SCHED_ADJUST_COST (rtx insn, rtx link, rtx dep_insn, int cost)

该函数根据insndep_insn通过依赖链接的关系来更正cost值。 其应该返回新的值。缺省为不对cost进行调整。 例如这可以用于指定调度器使用传统的流水线描述, 即输出或反向依赖不产生与数据依赖相同的代价。 如果调度器使用基于流水线描述的自动机,则反向依赖的代码为0, 输出依赖的代价为1和第一个insn与第二个insn之间的延迟时间的最大值。 如果这些值无法接受,你应该使用该钩子来修改它们。参见Processor pipeline description

— Target Hook: int TARGET_SCHED_ADJUST_PRIORITY (rtx insn, int priority)

该钩子调整insn的整数调度有限级priority。其应该返回新的priority。 增加优先级来提前执行insn,减少优先级来推迟执行insn。 如果不需要调整insn的调度优先级,则不需要定义该钩子。

— Target Hook: int TARGET_SCHED_REORDER (FILE *file, int verbose, rtx *ready, int *n_readyp, int clock)

该钩子在调度器调度完就绪列表后被执行, 以允许机器描述来重新排序(例如在‘VLIW’机器上,将两个小指令合并一起)。 file或者为一个null指针,或者一个stdio流,用来写入调试输出。 verbose-fsched-verbose-n提供的详细级别。 ready为指向已经被调度的指令就绪列表的指针。 n_readyp为指向在就绪列表中的元素个数的指针。 调度器按照相反的顺序读取就绪列表,从ready[*n_readyp-1]开始, 到ready[0]。clock为调度器的时钟tick。你可以修改就绪列表和insn。 返回值为这个周期可以发射的insn数;这通常只是为issue_rate。 参见‘TARGET_SCHED_REORDER2’。

— Target Hook: int TARGET_SCHED_REORDER2 (FILE *file, int verbose, rtx *ready, int *n_ready, clock)

类似于‘TARGET_SCHED_REORDER’,只不过在不同的时间被调用。 该函数每当调度器开始一个新的周期时被调用。其在每个周期都被调用一次, 紧跟在‘TARGET_SCHED_VARIABLE_ISSUE’之后; 其可以重排就绪列表并返回在同一周期被调度的insn数目。 如果常常调度一个insn会引起其他insn可以在同一周期就绪,则定义该钩子会很有用。 这样其它insn便可以被适当的考虑进来。

— Target Hook: void TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK (rtx head, rtx tail)

该钩子在由两个参数值给出的链中向前评估完insn的依赖关系之后, 但在insn链的调度之前被调用。例如,其可以被用于更好的insn分类, 如果其需要依赖分析。该钩子可以使用insn调度器的向后和向前依赖, 因为它们已经被计算好了。

— Target Hook: void TARGET_SCHED_INIT (FILE *file, int verbose, int max_ready)

该钩子在每个要被调度的指令块的起始处被调用。file或者为一个null指针, 或者一个stdio流,用来写入调试输出。 verbose-fsched-verbose-n提供的详细级别。 max_ready为在当前调度域中可以同时活跃的insn最大数。 这可以用来分配需要的草稿空间,例如,‘TARGET_SCHED_REORDER’。

— Target Hook: void TARGET_SCHED_FINISH (FILE *file, int verbose)

该钩子在每个要被调度的指令块的起始处被调用。 其可以用于执行清除由其它调度钩子完成的任何动作。file或者为一个null指针, 或者一个stdio流,用来写入调试输出。 verbose-fsched-verbose-n提供的详细级别。

— Target Hook: void TARGET_SCHED_INIT_GLOBAL (FILE *file, int verbose, int old_max_uid)

该钩子在函数级初始化的时候被调度器执行。file或者为一个null指针, 或者一个stdio流,用来写入调试输出。 verbose-fsched-verbose-n提供的详细级别。 old_max_uid为调度开始时,最大的insn uid。

— Target Hook: void TARGET_SCHED_FINISH_GLOBAL (FILE *file, int verbose)

这是一个清除钩子,对应于TARGET_SCHED_INIT_GLOBALfile或者为一个null指针,或者一个stdio流,用来写入调试输出。 verbose-fsched-verbose-n提供的详细级别。

— Target Hook: int TARGET_SCHED_DFA_PRE_CYCLE_INSN (void)

该钩子返回一个RTL insn。流水线冒险识别器中的自动机状态, 按照当新的模拟处理器周期开始,insn被调度的样子被改变。 该钩子的用法可以简化一些VLIW处理器的自动机流水线描述。 如果钩子被定义,其只用于基于自动机的流水线描述。缺省为不改变状态, 当新的模拟处理器周期开始时。

— Target Hook: void TARGET_SCHED_INIT_DFA_PRE_CYCLE_INSN (void)

该钩子可以用于初始化先前的钩子所使用的数据。

— Target Hook: int TARGET_SCHED_DFA_POST_CYCLE_INSN (void)

该钩子与‘TARGET_SCHED_DFA_PRE_CYCLE_INSN’类似,但用于改变状态, 按照当新的模拟处理器周期结束时insn被调度的方式。

— Target Hook: void TARGET_SCHED_INIT_DFA_POST_CYCLE_INSN (void)

该钩子与‘TARGET_SCHED_INIT_DFA_PRE_CYCLE_INSN’类似, 但用于初始化先前的钩子所使用的数据。

— Target Hook: void TARGET_SCHED_DFA_PRE_CYCLE_ADVANCE (void)

该钩子用来通报target,当前模拟周期将要完成。 该钩子类似于‘TARGET_SCHED_DFA_PRE_CYCLE_INSN’, 但用于在更复杂的情况下改变状态,例如当在一个单独的insn上前移一个状态并不足够时。

— Target Hook: void TARGET_SCHED_DFA_POST_CYCLE_ADVANCE (void)

该钩子用来通报target,新的模拟周期刚刚开始。 该钩子类似于‘TARGET_SCHED_DFA_POST_CYCLE_INSN’, 但用于在更复杂的情况下改变状态,例如当在一个单独的insn上前移一个状态并不足够时。

— Target Hook: int TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD (void)

该钩子控制基于DFA的insn调度器来更好的选择一个insn, 从就绪insn队列中。通常调度器从队列中选择第一个insn。如果钩子返回一个正值, 则会有额外的调度器代码来尝试所有的‘TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD ()’的排列组合, 来选择一个insn,使得发射该insn将在同一周期产生最大的insn发射数。 对于VLIW处理器, 代码实际上解决了将简单insn打包成VLIW insn的问题。 当然,如果VLIW打包规则在自动机中有描述。

该代码还能用于超标量RISC处理器。 让我们考虑一个具有3级流水的超标量RISC处理器。 一些insn可以在流水线AB中被执行, 一些insn只能在流水线BC中执行, 并且有一个insn可以在流水线B中被执行。处理器可以发射第一个insn到A, 第二个到B。这种情况下,第三个insn将会等待释放B,直到下一个周期。 如果调度器先发射第三个insn,则处理器可以一个周期发射所有的3个insn。

实际上该代码证明了基于自动机的流水线冒险识别器的优点。 我们最快且最容易的尝试许多insn调度,并选择最好的一种。

缺省为不进行多遍的调度。

— Target Hook: int TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD (rtx insn)

该钩子控制了对于多遍insn调度,就绪insn队列中的什么样的insn将被考虑。 如果钩子返回0,对于最为参数传递的insn,则insn将不被选择发射。

缺省为所有的就绪insn都可以被选择发射。

— Target Hook: int TARGET_SCHED_DFA_NEW_CYCLE (FILE *dump, int verbose, rtx insn, int last_clock, int clock, int *sort_p)

该钩子在给定的周期,在发射作为第三个参数传递的insn之前被insn调度器调用。 如果钩子返回非零,则insn在给定的处理器周期将不被发射。替代的, 处理器周期将前移。如果最后一个参数的值为0, 则insn就绪队列没有在新的周期开始时按照通常的方式被排序。 第一个参数传递了调试输出的文件。第二个参数传递了调试输出的详细级别。 第四个和第五个参数值分别对应于之前insn被发射的处理器周期,以及当前处理器周期。

— Target Hook: bool TARGET_SCHED_IS_COSTLY_DEPENDENCE (struct dep_def *_dep, int cost, int distance)

该钩子用于定义哪种依赖被target认为是具有昂贵代价的, 以至于将insn调度成依赖太近是不明智的。参数为: 第一个参数_dep为被评估的依赖。第二个参数cost为依赖的代价, 第三个参数distance为两个insn的周期距离。钩子返回true, 如果考虑两个insn间的距离,它们间的依赖被 target认为是昂贵的, 否则为false

在多发射,乱序机器上,定义该钩子可以有用, (a)实际中是无法预测真实的数据/资源延迟, 但是(b)有一个更好的机会来预测实际要被执行的组, 并且(c)正确模拟分组会非常重要。在这样的target上, 可能想要允许发射距离较近的依赖insn,即,比依赖距离近; 但是对于“昂贵的依赖”不这样做,这样就可以定义该钩子。

— Target Hook: void TARGET_SCHED_H_I_D_EXTENDED (void)

该钩子在输出一个新的指令到指令流之后被insn调度器调用。 钩子通知target后端来延伸它的每个指令的数据结构。

— Target Hook: void * TARGET_SCHED_ALLOC_SCHED_CONTEXT (void)

Return a pointer to a store large enough to hold target scheduling context.

— Target Hook: void TARGET_SCHED_INIT_SCHED_CONTEXT (void *tc, bool clean_p)

Initialize store pointed to by tc to hold target scheduling context. It clean_p is true then initialize tc as if scheduler is at the beginning of the block. Otherwise, copy the current context into tc.

— Target Hook: void TARGET_SCHED_SET_SCHED_CONTEXT (void *tc)

Copy target scheduling context pointed to by tc to the current context.

— Target Hook: void TARGET_SCHED_CLEAR_SCHED_CONTEXT (void *tc)

Deallocate internal data in target scheduling context pointed to by tc.

— Target Hook: void TARGET_SCHED_FREE_SCHED_CONTEXT (void *tc)

Deallocate a store for target scheduling context pointed to by tc.

— Target Hook: int TARGET_SCHED_SPECULATE_INSN (rtx insn, int request, rtx *new_pat)

该钩子当insn只有投机依赖,并因此可以被投机的调度时,被调用。 钩子用于检查insn的指令模式是否具有一个投机版本,并且如果检查成功, 则生成那个投机模式。钩子应该返回1,如果具有投机形式,或者-1,如果不具有。 request描述了请求投机的类型。如果返回值等于1, 则new_pat被赋值为生成的投机指令模式。

— Target Hook: int TARGET_SCHED_NEEDS_BLOCK_P (rtx insn)

该钩子在为insn生成恢复代码时,被insn调度器调用。其应该返回非零, 如果相应的检查指令应该分支跳转到回复代码,否则为0.

— Target Hook: rtx TARGET_SCHED_GEN_CHECK (rtx insn, rtx label, int mutate_p)

该钩子被insn调度器调用,来为恢复检查指令产生一个指令模式。 如果mutate_p为0,则insn为一个投机指令,对此应该生成检查。 label或者为一个基本快的标号,恢复代码应该被生成的地方, 或者为一个null指针,当请求的检查没有分支到恢复代码(简单的检查)。 如果mutate_p为非 0, 则由insn注解的对应于一个简单检查的指令模式应该被生成。 这种情况下,label不能为null。

— Target Hook: int TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD_SPEC (rtx insn)

该钩子用于在就绪列表中第一个指令上没有调用‘TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD’的情况。 钩子用于丢弃从当前周期调度的起始于就绪列表的投机指令。对于非投机指令, 钩子应该总是返回非零。例如,在ia64后端,钩子用于取消数据投机insn, 当ALAT表将满时。

— Target Hook: void TARGET_SCHED_SET_SCHED_FLAGS (unsigned int *flags, spec_info_t spec_info)

该钩子被insn调度器用于查找什么特点应该被启用。 flags初始时可以设置了SCHED_RGN或SCHED_EBB位。这指示调度器过程, 应该提供什么数据。target后端应该修改flags,通过修改对应于下列特点的位: USE_DEPS_LIST, USE_GLAT, DETACH_LIFE_INFO和DO_SPECULATION。 对于DO_SPECULATION特点,一个额外的结构体spec_info应该由target来填充。 该结构体描述了调度器中可以使用的投机类型。

— Target Hook: int TARGET_SCHED_SMS_RES_MII (struct ddg *g)

该钩子被swing modulo调度器调用,来计算基于资源的下界, 其基于在机器上可用的资源以及每个指令要求的资源。 target后端可以使用g来计算这个边界。如果没有实现该钩子, 则会使用一个非常简单的下界:指令总数除以发射率。