This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH RFC]Pair load store instructions using a generic scheduling fusion pass

On 09/30/14 03:22, Bin Cheng wrote:

2014-09-30  Bin Cheng<>
	    Mike Stump<>

	* timevar.def (TV_SCHED_FUSION): New time var.
	* passes.def (pass_sched_fusion): New pass.
	* config/arm/arm.c (TARGET_SCHED_FUSION_PRIORITY): New.
	(extract_base_offset_in_addr, fusion_load_store): New.
	(arm_sched_fusion_priority): New.
	(arm_option_override): Disable scheduling fusion on non-armv7
	processors by default.
	* sched-int.h (struct _haifa_insn_data): New field.
	* sched-rgn.c (rest_of_handle_sched_fusion): New.
	(pass_data_sched_fusion, pass_sched_fusion): New.
	(make_pass_sched_fusion): New.
	* haifa-sched.c (sched_fusion): New.
	(insn_cost): Handle sched_fusion.
	(priority): Handle sched_fusion by calling target hook.
	(enum rfs_decision): New enum value.
	(rfs_str): New element for RFS_FUSION.
	(rank_for_schedule): Support sched_fusion.
	(schedule_insn, max_issue, prune_ready_list): Handle sched_fusion.
	(schedule_block, fix_tick_ready): Handle sched_fusion.
	* common.opt (flag_schedule_fusion): New.
	* tree-pass.h (make_pass_sched_fusion): New.
	* target.def (fusion_priority): New.
	* doc/tm.texi: Regenerated.
	* doc/invoke.texi (-fschedule-fusion): New.

2014-09-30  Bin Cheng<>

	* New test.
	* Improve scanning string.


Index: gcc/doc/tm.texi
--- gcc/doc/tm.texi	(revision 215662)
+++ gcc/doc/tm.texi	(working copy)
@@ -6677,6 +6677,29 @@ This hook is called by tree reassociator to determ
  parallelism required in output calculations chain.
  @end deftypefn

+@deftypefn {Target Hook} void TARGET_SCHED_FUSION_PRIORITY (rtx_insn *@var{insn}, int @var{max_pri}, int *@var{fusion_pri}, int *@var{pri})
+This hook is called by scheduling fusion pass.  It calculates fusion
+priorities for each instruction passed in by parameter.  The priorities
+are returned via pointer parameters.
+@var{insn} is the instruction whose priorities need to be calculated.
+@var{max_pri} is the maximum priority can be returned in any cases.
+@var{fusion_pri} is the pointer parameter through which @var{insn}'s
+fusion priority should be calculated and returned.
+@var{pri} is the pointer parameter through which @var{insn}'s priority
+should be calculated and returned.
+Same @var{fusion_pri} should be returned for instructions which should
+be scheduled together.  Different @var{pri} should be returned for
+instructions with same @var{fusion_pri}.  All instructions will be
+scheduled according to the two priorities.  @var{fusion_pri} is the major
+sort key, @var{pri} is the minor sort key.  All priorities calculated
+should be between 0 (exclusive) and @var{max_pri} (inclusive).  To avoid
+false dependencies, @var{fusion_pri} of instructions which need to be
+scheduled together should be smaller than @var{fusion_pri} of irrelevant
+@end deftypefn
  @node Sections
  @section Dividing the Output into Sections (Texts, Data, @dots{})
  @c the above section title is WAY too long.  maybe cut the part between
So I think we need to clarify that this hook is useful when fusing to related insns, but which don't have a data dependency. Somehow we need to describe that the insns to be fused should have the same (or +-1) priority. It may be useful to use code from the ARM implementation to show how to use this to pair up loads as an example.

It may also be useful to refer to the code which reorders insns in the ready queue for cases where we want to fuse two truly independent insns.

+  if (sched_fusion)
+    {
+      /* The instruction that has the same fusion priority as the last
+	 instruction is the instruction we picked next.  If that is not
+	 the case, we sort ready list firstly by fusion priority, then
+	 by priority, and at last by INSN_LUID.  */
+      int a = INSN_FUSION_PRIORITY (tmp);
+      int b = INSN_FUSION_PRIORITY (tmp2);
+      int last = -1;
+      if (last_nondebug_scheduled_insn
+	  && !NOTE_P (last_nondebug_scheduled_insn)
+	  && BLOCK_FOR_INSN (tmp)
+	       == BLOCK_FOR_INSN (last_nondebug_scheduled_insn))
+	last = INSN_FUSION_PRIORITY (last_nondebug_scheduled_insn);
+      if (a != last && b != last)
+	{
+	  if (a == b)
+	    {
+	      a = INSN_PRIORITY (tmp);
+	      b = INSN_PRIORITY (tmp2);
+	    }
+	  if (a != b)
+	    return rfs_result (RFS_FUSION, b - a);
+	  else
+	    return rfs_result (RFS_FUSION, INSN_LUID (tmp) - INSN_LUID (tmp2));
rfs_result's signature has changed, I think you need to pass in tmp & tmp2. You'll need to make that trivial update for all the callers.

Can you make those changes and repost so that I can look at the docs (I think the implementation is fine and won't need further review).


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]