[RFC][AARCH64] Machine reorg pass for aarch64/Falkor to handle prefetcher tag collision

Kugan Vivekanandarajah kugan.vivekanandarajah@linaro.org
Thu Feb 15 20:50:00 GMT 2018


Hi,

On 14 February 2018 at 09:47, Kugan Vivekanandarajah
<kugan.vivekanandarajah@linaro.org> wrote:
> Hi Kyrill,
>
> On 13 February 2018 at 20:47, Kyrill  Tkachov
> <kyrylo.tkachov@foss.arm.com> wrote:
>> Hi Kugan,
>>
>> On 12/02/18 23:58, Kugan Vivekanandarajah wrote:
>>>
>>> Implements a machine reorg pass for aarch64/Falkor to handle
>>> prefetcher tag collision. This is strictly not part of the loop
>>> unroller but for Falkor, unrolling can make h/w prefetcher performing
>>> badly if there are too much tag collisions based on the discussions in
>>> https://gcc.gnu.org/ml/gcc/2017-10/msg00178.html.
>>>
>>
>> Could you expand a bit more on what transformation exactly this pass does?
>
> This is similar to what LLVM does in https://reviews.llvm.org/D35366.
>
> Falkor hardware prefetcher works well when signature of the prefetches
> (or tags as computed in the patch - similar to LLVM) are different for
> different memory streams. If different memory streams  have the same
> signature, it can result in bad performance. This machine reorg pass
> tries to change the signature of memory loads by changing the base
> register with a free register.
>
>> From my understanding the loads that use the same base
>> register and offset and have the same destination register
>> are considered part of the same stream by the hardware prefetcher, so for
>> example:
>> ldr x0, [x1, 16] (load1)
>> ... (set x1 to something else)
>> ldr x0, [x1, 16] (load2)
>>
>> will cause the prefetcher to think that both loads are part of the same
>> stream,
>> so this pass tries to rewrite the sequence into:
>> ldr x0, [x1, 16]
>> ... (set x1 to something else)
>> mov tmp, x1
>> ldr x0, [tmp, 16]
>>
>> Where the tag/signature is the combination of destination x0, base x1 and
>> offset 16.
>> Is this a fair description?
>
> This is precisely what is happening.
>
>>
>> I've got some comments on the patch itself
>>
>>> gcc/ChangeLog:
>>>
>>> 2018-02-12  Kugan Vivekanandarajah <kuganv@linaro.org>
>>>
>>>     * config/aarch64/aarch64.c (iv_p): New.
>>>     (strided_load_p): Likwise.
>>>     (make_tag): Likesie.
>>>     (get_load_info): Likewise.
>>>     (aarch64_reorg): Likewise.
>>>     (TARGET_MACHINE_DEPENDENT_REORG): Implement new target hook.
>>
>>
>> New functions need function comments describing the arguments at least.
>> Functions like make_tag, get_load_info etc can get tricky to maintain
>> without
>> some documentation on what they are supposed to accept and return.
>
> I wil add the comments.
>
>>
>> I think the pass should be enabled at certain optimisation levels, say -O2?
>> I don't think it would be desirable at -Os since it creates extra moves that
>> increase code size.
>
> Ok, I will change this.
>
>>
>> That being said, I would recommend you implement this as an aarch64-specific
>> pass,
>> in a similar way to cortex-a57-fma-steering.c. That way you can register it
>> in
>> aarch64-passes.def and have flexibility as to when exactly the pass gets to
>> run
>> (i.e. you wouldn't be limited by when machine_reorg gets run).
>>
>> Also, I suggest you don't use the "if (aarch64_tune != falkor) return;" way
>> of
>> gating this pass. Do it in a similar way to the FMA steering pass that is,
>> define a new flag in aarch64-tuning-flags.def and use it in the tune_flags
>> field
>> of the falkor tuning struct.
>
> Ok, I will revise the patch.

Here is the revised patch.

Thanks,
Kugan

gcc/ChangeLog:

2018-02-15  Kugan Vivekanandarajah  <kuganv@linaro.org>

    * config.gcc: Add falkor-tag-collision-avoidance.o to extra_objs for
        aarch64-*-*.
    * config/aarch64/aarch64-protos.h
(make_pass_tag_collision_avoidance): Declare.
    * config/aarch64/aarch64-passes.def: Insert tag collision avoidance pass.
    * config/aarch64/aarch64-tuning-flags.def
    (AARCH64_EXTRA_TUNE_AVOID_PREFETCH_TAG_COLLISION): Define.
    * config/aarch64/aarch64.c (qdf24xx_tunings): Add
    AARCH64_EXTRA_TUNE_AVOID_PREFETCH_TAG_COLLISION.
    * config/aarch64/falkor-tag-collision-avoidance.c: New file.
    * config/aarch64/t-aarch64: Add falkor-tag-collision-avoidance.o.


>
>
> Thanks,
> Kugan
>
>>
>> Hope this helps,
>> Kyrill
-------------- next part --------------
diff --git a/gcc/config.gcc b/gcc/config.gcc
index eca156a..c3f3e1a 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -303,7 +303,7 @@ aarch64*-*-*)
 	extra_headers="arm_fp16.h arm_neon.h arm_acle.h"
 	c_target_objs="aarch64-c.o"
 	cxx_target_objs="aarch64-c.o"
-	extra_objs="aarch64-builtins.o aarch-common.o cortex-a57-fma-steering.o"
+	extra_objs="aarch64-builtins.o aarch-common.o cortex-a57-fma-steering.o falkor-tag-collision-avoidance.o"
 	target_gtfiles="\$(srcdir)/config/aarch64/aarch64-builtins.c"
 	target_has_targetm_common=yes
 	;;
diff --git a/gcc/config/aarch64/aarch64-passes.def b/gcc/config/aarch64/aarch64-passes.def
index 87747b4..d4b6a43 100644
--- a/gcc/config/aarch64/aarch64-passes.def
+++ b/gcc/config/aarch64/aarch64-passes.def
@@ -19,3 +19,4 @@
    <http://www.gnu.org/licenses/>.  */
 
 INSERT_PASS_AFTER (pass_regrename, 1, pass_fma_steering);
+INSERT_PASS_AFTER (pass_fast_rtl_dce, 1, pass_tag_collision_avoidance);
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 2d705d2..d8f6964 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -544,6 +544,7 @@ std::string aarch64_get_extension_string_for_isa_flags (unsigned long,
 							unsigned long);
 
 rtl_opt_pass *make_pass_fma_steering (gcc::context *ctxt);
+rtl_opt_pass *make_pass_tag_collision_avoidance (gcc::context *ctxt);
 
 poly_uint64 aarch64_regmode_natural_size (machine_mode);
 
diff --git a/gcc/config/aarch64/aarch64-tuning-flags.def b/gcc/config/aarch64/aarch64-tuning-flags.def
index ea9ead2..c0dd178 100644
--- a/gcc/config/aarch64/aarch64-tuning-flags.def
+++ b/gcc/config/aarch64/aarch64-tuning-flags.def
@@ -41,4 +41,6 @@ AARCH64_EXTRA_TUNING_OPTION ("slow_unaligned_ldpw", SLOW_UNALIGNED_LDPW)
    are not considered cheap.  */
 AARCH64_EXTRA_TUNING_OPTION ("cheap_shift_extend", CHEAP_SHIFT_EXTEND)
 
+AARCH64_EXTRA_TUNING_OPTION ("avoid_prefetch_tag_collision", AVOID_PREFETCH_TAG_COLLISION)
+
 #undef AARCH64_EXTRA_TUNING_OPTION
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 2e70f3a..b075325 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -875,7 +875,7 @@ static const struct tune_params qdf24xx_tunings =
   2,	/* min_div_recip_mul_df.  */
   0,	/* max_case_values.  */
   tune_params::AUTOPREFETCHER_WEAK,	/* autoprefetcher_model.  */
-  (AARCH64_EXTRA_TUNE_NONE),		/* tune_flags.  */
+  (AARCH64_EXTRA_TUNE_AVOID_PREFETCH_TAG_COLLISION), /* tune_flags.  */
   &qdf24xx_prefetch_tune
 };
 
diff --git a/gcc/config/aarch64/falkor-tag-collision-avoidance.c b/gcc/config/aarch64/falkor-tag-collision-avoidance.c
index e69de29..1fe320f 100644
--- a/gcc/config/aarch64/falkor-tag-collision-avoidance.c
+++ b/gcc/config/aarch64/falkor-tag-collision-avoidance.c
@@ -0,0 +1,468 @@
+/* Tag Collision Avoidance pass for Falkor.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#define IN_TARGET_CODE 1
+
+#include "config.h"
+#define INCLUDE_LIST
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "target.h"
+#include "rtl.h"
+#include "tree.h"
+#include "tree-pass.h"
+#include "aarch64-protos.h"
+#include "hash-map.h"
+#include "cfgloop.h"
+#include "cfgrtl.h"
+#include "rtl-iter.h"
+#include "df.h"
+#include "memmodel.h"
+#include "optabs.h"
+#include "regs.h"
+#include "recog.h"
+
+/*
+   Falkor hardware prefetcher works well when signature of the prefetches
+   (or tags as computed in the patch) are different for different memory
+   streams.  If different memory streams  have the same signature, it can
+   result in bad performance.  This pass tries to change the signature of
+   memory loads by changing the base register with a free register.
+
+   Signature (TAG) is based on SRC, DST and Offset.  If the signature is
+   is same, it will be considered part of the same stream by the hardware
+   prefetcher, for example:
+   ldr x0, [x1, 16] (load stream 1)
+   x1 is resused for a different stream
+   ldr x0, [x1, 16] (load stream 2)
+
+   will cause the prefetcher to think that both loads are part of the same
+   stream, so this pass tries to rewrite the sequence into:
+   ldr x0, [x1, 16]
+   mov tmp, x1
+   ldr x0, [tmp, 16]
+   Such that the signatures are different.  */
+
+
+/* Return true if the REG is an IV in the LOOP, false otherwise.
+   This is an approximate check and does not rely on the functionality
+   provided likes of biv () as the loop form might not be suitable for
+   such analysis.  */
+
+static bool
+iv_p (rtx reg, struct loop *loop)
+{
+  df_ref adef;
+  unsigned regno = REGNO (reg);
+  bool def_in_loop = false;
+  bool def_out_loop = false;
+
+  if (GET_MODE_CLASS (GET_MODE (reg)) != MODE_INT)
+    return false;
+
+  for (adef = DF_REG_DEF_CHAIN (regno); adef; adef = DF_REF_NEXT_REG (adef))
+    {
+      if (!DF_REF_INSN_INFO (adef)
+	  || !NONDEBUG_INSN_P (DF_REF_INSN (adef)))
+	continue;
+
+      basic_block bb = DF_REF_BB (adef);
+      if (dominated_by_p (CDI_DOMINATORS, bb, loop->header)
+	  && bb->loop_father == loop)
+	{
+	  rtx_insn *insn = DF_REF_INSN (adef);
+	  recog_memoized (insn);
+	  rtx pat = PATTERN (insn);
+	  if (GET_CODE (pat) != SET)
+	    continue;
+	  rtx x = SET_SRC (pat);
+	  if (GET_CODE (x) == ZERO_EXTRACT
+	      || GET_CODE (x) == ZERO_EXTEND
+	      || GET_CODE (x) == SIGN_EXTEND)
+	    x = XEXP (x, 0);
+	  if (MEM_P (x))
+	    continue;
+	  if (GET_CODE (x) == POST_INC
+	      || GET_CODE (x) == POST_DEC
+	      || GET_CODE (x) == PRE_INC
+	      || GET_CODE (x) == PRE_DEC)
+	    def_in_loop = true;
+	  else if (BINARY_P (x))
+	    def_in_loop = true;
+	}
+      if (dominated_by_p (CDI_DOMINATORS, loop->header, bb))
+	def_out_loop = true;
+      if (def_in_loop && def_out_loop)
+	return true;
+    }
+  return false;
+}
+
+/* Return true if X is a strided load in the LOOP, false otherwise.
+   If it is a strided load, set the BASE and OFFSET.  Also, if this is
+   a pre/post increment load, set PRE_POST to true.  */
+
+static bool
+strided_load_p (rtx x,
+		struct loop *loop,
+		bool *pre_post,
+		rtx *base,
+		rtx *offset)
+{
+  /* Loadded value is extended, get src.  */
+  if (GET_CODE (x) == ZERO_EXTRACT
+      || GET_CODE (x) == ZERO_EXTEND
+      || GET_CODE (x) == SIGN_EXTEND)
+    x = XEXP (x, 0);
+
+  /* If it is not MEM_P, it is not lodade from mem.  */
+  if (!MEM_P (x))
+    return false;
+
+  /* Get the src of MEM_P.  */
+  x = XEXP (x, 0);
+
+  /* If it is a post/pre increment, get the src.  */
+  if (GET_CODE (x) == POST_INC
+      || GET_CODE (x) == POST_DEC
+      || GET_CODE (x) == PRE_INC
+      || GET_CODE (x) == PRE_DEC)
+    {
+      x = XEXP (x, 0);
+      *pre_post = true;
+    }
+
+  /* get base and offset depending on the type.  */
+  if (REG_P (x)
+      || UNARY_P (x))
+    {
+      if (!REG_P (x))
+	x = XEXP (x, 0);
+      if (REG_P (x)
+	  && iv_p (x, loop))
+	{
+	  *base = x;
+	  return true;
+	}
+    }
+  else if (BINARY_P (x))
+    {
+      rtx reg1, reg2;
+      reg1 = XEXP (x, 0);
+
+      if (REG_P (reg1)
+	  && REGNO (reg1) == SP_REGNUM)
+	return false;
+      reg2 = XEXP (x, 1);
+
+      if (REG_P (reg1)
+	  && iv_p (reg1, loop))
+	{
+
+	  *base = reg1;
+	  *offset = reg2;
+	  return true;
+	}
+
+      if (REG_P (reg1)
+	  && REG_P (reg2)
+	  && iv_p (reg2, loop))
+	{
+	  *base = reg1;
+	  *offset = reg2;
+	  return true;
+	}
+    }
+  return false;
+}
+
+/* Compute the TAG (or signature) based on BASE, DEST and
+   OFFSET of the load.  */
+
+static unsigned
+make_tag (unsigned dest, unsigned base, unsigned offset)
+{
+  return (dest & 0xf)
+    | ((base & 0xf) << 4)
+    | ((offset & 0x3f) << 8);
+}
+
+
+/* Return true if INSN is a strided load in LOOP.
+   If it is a strided load, set the DEST, BASE and OFFSET.
+   Also, if this is a pre/post increment load, set PRE_POST
+   to true.  */
+
+static bool
+get_load_info (rtx_insn *insn,
+	       struct loop *loop,
+	       bool *pre_post,
+	       rtx *base,
+	       rtx *dest,
+	       rtx *offset)
+{
+  subrtx_var_iterator::array_type array;
+  if (!INSN_P (insn) || recog_memoized (insn) < 0)
+    return false;
+  rtx pat = PATTERN (insn);
+  switch (GET_CODE (pat))
+    {
+    case PARALLEL:
+	{
+	  for (int j = 0; j < XVECLEN (pat, 0); ++j)
+	    {
+	      rtx ex = XVECEXP (pat, 0, j);
+	      FOR_EACH_SUBRTX_VAR (iter, array, ex, NONCONST)
+		{
+		  const_rtx x = *iter;
+		  if (GET_CODE (x) == SET
+		      && strided_load_p (SET_SRC (x), loop, pre_post,
+					 base, offset))
+		    {
+		      *dest = SET_DEST (x);
+		      return true;
+		    }
+		}
+	    }
+	}
+      break;
+
+    case SET:
+      FOR_EACH_SUBRTX_VAR (iter, array, SET_SRC (pat), NONCONST)
+	{
+	  rtx x = *iter;
+	  if (strided_load_p (x, loop, pre_post,
+			      base, offset))
+	    {
+	      *dest = SET_DEST (pat);
+	      return true;
+	    }
+	}
+
+    default:
+      break;
+    }
+  return false;
+}
+
+/* Tag collision avoidance pass for Falkor.  */
+
+void
+execute_tag_collision_avoidance ()
+{
+  basic_block *body, bb;
+  struct loop *loop;
+  rtx_insn *insn;
+
+  compute_bb_for_insn ();
+  /* Compute live regs.  */
+  df_compute_regs_ever_live (true);
+  df_analyze ();
+
+  /* Find the loops.  */
+  loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
+  calculate_dominance_info (CDI_DOMINATORS);
+  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+    {
+      hash_map <rtx, auto_vec<rtx_insn *> > tag_map (512);
+      body = get_loop_body (loop);
+      auto_vec <rtx> tags;
+
+      /* Record all the memory tags.  */
+      for (unsigned i = 0; i < loop->num_nodes; i++)
+	{
+	  bb = body[i];
+	  FOR_BB_INSNS (bb, insn)
+	    {
+	      unsigned tag;
+	      rtx base = NULL_RTX;
+	      rtx dest = NULL_RTX;
+	      rtx offset = NULL_RTX;
+	      bool pre_or_post = false;
+
+	      if (!INSN_P (insn)
+		  || DEBUG_INSN_P (insn))
+		continue;
+
+	      if (get_load_info (insn, loop, &pre_or_post,
+				 &base, &dest, &offset)
+		  && REG_P (dest))
+		{
+		  int int_offset = 0;
+		  if (offset && REG_P (offset))
+		    int_offset = (1 << 5) | REGNO (offset);
+		  else if (offset && CONST_INT_P (offset))
+		    {
+		      int_offset = INTVAL (offset);
+		      int_offset /= GET_MODE_SIZE (GET_MODE (dest)).to_constant ();
+		      if (!pre_or_post)
+			int_offset >>= 2;
+		    }
+		  tag = make_tag (REGNO (dest), REGNO (base), int_offset);
+		  rtx t = GEN_INT (tag);
+		  if (!tag_map.get (t))
+		    tags.safe_push (t);
+		  tag_map.get_or_insert (t).safe_push (insn);
+		}
+	    }
+	}
+
+      for (unsigned i = 0; i < tags.length (); ++i)
+	{
+	  rtx t = tags[i];
+	  auto_vec<rtx_insn *> *v = tag_map.get (t);
+
+	  for (int j = v->length () - 1; j > 0; --j)
+	    {
+	      /* Get the insns that has tags colliding.  */
+	      rtx_insn *insn = (*v)[j];
+	      rtx pat;
+	      bool changed = false;
+	      int int_offset = 0;
+	      rtx base = NULL_RTX;
+	      rtx dest = NULL_RTX;
+	      rtx offset = NULL_RTX;
+	      bool pre_or_post = false;
+
+	      if (!get_load_info (insn, loop, &pre_or_post,
+				  &base, &dest, &offset))
+		gcc_assert (false);
+
+	      if (offset && REG_P (offset))
+		int_offset = (1 << 5) | REGNO (offset);
+	      else if (offset && CONST_INT_P (offset))
+		{
+		  int_offset = INTVAL (offset);
+		  int_offset /= GET_MODE_SIZE (GET_MODE (dest)).to_constant ();
+		  if (!pre_or_post)
+		    int_offset >>= 2;
+		}
+
+	      /* Go over temporary registers and find a free register, if
+		 available.  */
+	      for (int k = R9_REGNUM; !changed && (k <= R15_REGNUM); k++)
+		if (!df_hard_reg_used_p (k))
+		  {
+		    unsigned tag;
+		    rtx t;
+
+		    tag = make_tag (REGNO (dest), k, int_offset);
+		    t = GEN_INT (tag);
+		    /* Check to see if the new tag also collides with an
+		       existing load.  */
+		    if (tag_map.get (t))
+		      continue;
+
+		    machine_mode mode = GET_MODE (base);
+		    rtx new_reg = gen_rtx_REG (mode, k);
+		    t = GEN_INT (make_tag (REGNO (dest), REGNO (new_reg),
+					   int_offset));
+		    vec <rtx_insn *> *v2 = tag_map.get (t);
+		    if (v2 && (v2->length () > 0))
+		      continue;
+
+		    /* Change the insn: dest = load (base, offset)
+		       into tmp = base; dest = load (tmp, offset).  */
+		    extract_insn (insn);
+		    for (int l = 0;
+			 (!changed) && (l < recog_data.n_operands); l++)
+		      {
+			subrtx_ptr_iterator::array_type array;
+			rtx *op = recog_data.operand_loc[l];
+
+			if (recog_data.operand_type[l] == OP_OUT)
+			  continue;
+
+			FOR_EACH_SUBRTX_PTR (iter, array, op, NONCONST)
+			  {
+			    rtx *loc = *iter;
+			    rtx x = *loc;
+
+			    if (!changed && (base == x))
+			      {
+				pat = gen_rtx_SET (new_reg, base);
+				if (validate_change (insn, loc, new_reg, false))
+				  {
+				    emit_insn_before (pat, insn);
+				    if (pre_or_post)
+				      {
+					rtx pat2 = gen_rtx_SET (base, new_reg);
+					emit_insn_after (pat2, insn);
+				      }
+				  }
+				v->pop ();
+				tag_map.get_or_insert (t).safe_push (insn);
+				changed = true;
+				break;
+			      }
+			  }
+		      }
+		  }
+	    }
+	}
+    }
+
+  loop_optimizer_finalize ();
+}
+
+
+const pass_data pass_data_tag_collision_avoidance =
+{
+  RTL_PASS, /* type */
+  "tag_collision_avoidance", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  TV_NONE, /* tv_id */
+  0, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  TODO_df_finish, /* todo_flags_finish */
+};
+
+class pass_tag_collision_avoidance : public rtl_opt_pass
+{
+public:
+  pass_tag_collision_avoidance (gcc::context *ctxt)
+    : rtl_opt_pass (pass_data_tag_collision_avoidance, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  virtual bool gate (function *)
+    {
+      return (aarch64_tune_params.extra_tuning_flags
+	      & AARCH64_EXTRA_TUNE_AVOID_PREFETCH_TAG_COLLISION)
+	      && optimize >= 2;
+    }
+
+  virtual unsigned int execute (function *)
+    {
+      execute_tag_collision_avoidance ();
+      return 0;
+    }
+
+}; // class pass_tag_collision_avoidance
+
+/* Create a new pass instance.  */
+
+rtl_opt_pass *
+make_pass_tag_collision_avoidance (gcc::context *ctxt)
+{
+  return new pass_tag_collision_avoidance (ctxt);
+}
diff --git a/gcc/config/aarch64/t-aarch64 b/gcc/config/aarch64/t-aarch64
index 0be1f0d..f185b40 100644
--- a/gcc/config/aarch64/t-aarch64
+++ b/gcc/config/aarch64/t-aarch64
@@ -67,6 +67,15 @@ cortex-a57-fma-steering.o: $(srcdir)/config/aarch64/cortex-a57-fma-steering.c \
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
 		$(srcdir)/config/aarch64/cortex-a57-fma-steering.c
 
+falkor-tag-collision-avoidance.o: $(srcdir)/config/aarch64/falkor-tag-collision-avoidance.c \
+    $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(REGS_H) insn-config.h $(RTL_BASE_H) \
+    dominance.h cfg.h cfganal.h $(BASIC_BLOCK_H) $(INSN_ATTR_H) $(RECOG_H) \
+    output.h hash-map.h $(DF_H) $(OBSTACK_H) $(TARGET_H) $(RTL_H) \
+    $(CONTEXT_H) $(TREE_PASS_H) regrename.h \
+    $(srcdir)/config/aarch64/aarch64-protos.h
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+		$(srcdir)/config/aarch64/falkor-tag-collision-avoidance.c
+
 comma=,
 MULTILIB_OPTIONS    = $(subst $(comma),/, $(patsubst %, mabi=%, $(subst $(comma),$(comma)mabi=,$(TM_MULTILIB_CONFIG))))
 MULTILIB_DIRNAMES   = $(subst $(comma), ,$(TM_MULTILIB_CONFIG))


More information about the Gcc-patches mailing list