AArch64 - use CSDB based sequences if speculation tracking is enabled
authorRichard Earnshaw <rearnsha@arm.com>
Tue, 31 Jul 2018 17:36:26 +0000 (17:36 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Tue, 31 Jul 2018 17:36:26 +0000 (17:36 +0000)
In this final patch, now that we can track speculation through conditional
branches, we can use this information to use a less expensive CSDB based
speculation barrier.

* config/aarch64/iterators.md (ALLI_TI): New iterator.
* config/aarch64/aarch64.md (despeculate_copy<ALLI_TI:mode>): New
expand.
(despeculate_copy<ALLI:mode>_insn): New insn.
(despeculate_copyti_insn): New insn.
(despeculate_simple<ALLI:mode>): New insn
(despeculate_simpleti): New insn.
* config/aarch64/aarch64.c (aarch64_speculation_safe_value): New
function.
(TARGET_SPECULATION_SAFE_VALUE): Redefine to
aarch64_speculation_safe_value.
(aarch64_print_operand): Handle const0_rtx in modifier 'H'.

From-SVN: r263174

gcc/ChangeLog
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.md
gcc/config/aarch64/iterators.md

index c21608a178e67fe40104e7a2bbb168949a07fa49..48a2002cfd746212a1fdf4fba0f59d0127628f7b 100644 (file)
@@ -1,3 +1,18 @@
+2018-07-31  Richard Earnshaw  <rearnsha@arm.com>
+
+       * config/aarch64/iterators.md (ALLI_TI): New iterator.
+       * config/aarch64/aarch64.md (despeculate_copy<ALLI_TI:mode>): New
+       expand.
+       (despeculate_copy<ALLI:mode>_insn): New insn.
+       (despeculate_copyti_insn): New insn.
+       (despeculate_simple<ALLI:mode>): New insn
+       (despeculate_simpleti): New insn.
+       * config/aarch64/aarch64.c (aarch64_speculation_safe_value): New
+       function.
+       (TARGET_SPECULATION_SAFE_VALUE): Redefine to
+       aarch64_speculation_safe_value.
+       (aarch64_print_operand): Handle const0_rtx in modifier 'H'.
+
 2018-07-31  Richard Earnshaw  <rearnsha@arm.com>
 
        * config/aarch64/aarch64-speculation.cc: New file.
index dc8cd2bd6881d0e28b57049b639ee8899cade286..f743f577357451cb69cfca6d44e5e5ac14ea2529 100644 (file)
@@ -6785,6 +6785,12 @@ aarch64_print_operand (FILE *f, rtx x, int code)
       break;
 
     case 'H':
+      if (x == const0_rtx)
+       {
+         asm_fprintf (f, "xzr");
+         break;
+       }
+
       if (!REG_P (x) || !GP_REGNUM_P (REGNO (x) + 1))
        {
          output_operand_lossage ("invalid operand for '%%%c'", code);
@@ -17778,6 +17784,45 @@ aarch64_select_early_remat_modes (sbitmap modes)
     }
 }
 
+/* Override the default target speculation_safe_value.  */
+static rtx
+aarch64_speculation_safe_value (machine_mode mode,
+                               rtx result, rtx val, rtx failval)
+{
+  /* Maybe we should warn if falling back to hard barriers.  They are
+     likely to be noticably more expensive than the alternative below.  */
+  if (!aarch64_track_speculation)
+    return default_speculation_safe_value (mode, result, val, failval);
+
+  if (!REG_P (val))
+    val = copy_to_mode_reg (mode, val);
+
+  if (!aarch64_reg_or_zero (failval, mode))
+    failval = copy_to_mode_reg (mode, failval);
+
+  switch (mode)
+    {
+    case E_QImode:
+      emit_insn (gen_despeculate_copyqi (result, val, failval));
+      break;
+    case E_HImode:
+      emit_insn (gen_despeculate_copyhi (result, val, failval));
+      break;
+    case E_SImode:
+      emit_insn (gen_despeculate_copysi (result, val, failval));
+      break;
+    case E_DImode:
+      emit_insn (gen_despeculate_copydi (result, val, failval));
+      break;
+    case E_TImode:
+      emit_insn (gen_despeculate_copyti (result, val, failval));
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  return result;
+}
+
 /* Target-specific selftests.  */
 
 #if CHECKING_P
@@ -18250,6 +18295,9 @@ aarch64_libgcc_floating_mode_supported_p
 #undef TARGET_SELECT_EARLY_REMAT_MODES
 #define TARGET_SELECT_EARLY_REMAT_MODES aarch64_select_early_remat_modes
 
+#undef TARGET_SPECULATION_SAFE_VALUE
+#define TARGET_SPECULATION_SAFE_VALUE aarch64_speculation_safe_value
+
 #if CHECKING_P
 #undef TARGET_RUN_TARGET_SELFTESTS
 #define TARGET_RUN_TARGET_SELFTESTS selftest::aarch64_run_selftests
index 3dcc054a15a615d97ccd51ae3b6f0306a4c7fcbe..9f3cadecad0f488b13bd4578f93e61abbe0db167 100644 (file)
    (set_attr "speculation_barrier" "true")]
 )
 
+;; Support for __builtin_speculation_safe_value when we have speculation
+;; tracking enabled.  Use the speculation tracker to decide whether to
+;; copy operand 1 to the target, or to copy the fail value (operand 2).
+(define_expand "despeculate_copy<ALLI_TI:mode>"
+  [(set (match_operand:ALLI_TI 0 "register_operand" "=r")
+       (unspec_volatile:ALLI_TI
+        [(match_operand:ALLI_TI 1 "register_operand" "r")
+         (match_operand:ALLI_TI 2 "aarch64_reg_or_zero" "rZ")
+         (use (reg:DI SPECULATION_TRACKER_REGNUM))
+         (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
+  ""
+  "
+  {
+    if (operands[2] == const0_rtx)
+      {
+       rtx tracker;
+       if (<MODE>mode == TImode)
+         tracker = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
+       else
+         tracker = gen_rtx_REG (<MODE>mode, SPECULATION_TRACKER_REGNUM);
+
+       emit_insn (gen_despeculate_simple<mode> (operands[0], operands[1],
+                                                tracker));
+       DONE;
+      }
+  }
+  "
+)
+
+;; Patterns to match despeculate_copy<mode>.  Note that "hint 0x14" is the
+;; encoding for CSDB, but will work in older versions of the assembler.
+(define_insn "*despeculate_copy<ALLI:mode>_insn"
+  [(set (match_operand:ALLI 0 "register_operand" "=r")
+       (unspec_volatile:ALLI
+        [(match_operand:ALLI 1 "register_operand" "r")
+         (match_operand:ALLI 2 "aarch64_reg_or_zero" "rZ")
+         (use (reg:DI SPECULATION_TRACKER_REGNUM))
+         (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
+  ""
+  {
+    operands[3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
+    output_asm_insn ("cmp\\t%3, #0\;csel\\t%<w>0, %<w>1, %<w>2, ne\;hint\t0x14 // csdb",
+                    operands);
+    return "";
+  }
+  [(set_attr "length" "12")
+   (set_attr "type" "block")
+   (set_attr "speculation_barrier" "true")]
+)
+
+;; Pattern to match despeculate_copyti
+(define_insn "*despeculate_copyti_insn"
+  [(set (match_operand:TI 0 "register_operand" "=r")
+       (unspec_volatile:TI
+        [(match_operand:TI 1 "register_operand" "r")
+         (match_operand:TI 2 "aarch64_reg_or_zero" "rZ")
+         (use (reg:DI SPECULATION_TRACKER_REGNUM))
+         (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
+  ""
+  {
+    operands[3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
+    output_asm_insn
+      ("cmp\\t%3, #0\;csel\\t%0, %1, %2, ne\;csel\\t%H0, %H1, %H2, ne\;hint\t0x14 // csdb",
+       operands);
+    return "";
+  }
+  [(set_attr "length" "16")
+   (set_attr "type" "block")
+   (set_attr "speculation_barrier" "true")]
+)
+
+(define_insn "despeculate_simple<ALLI:mode>"
+  [(set (match_operand:ALLI 0 "register_operand" "=r")
+       (unspec_volatile:ALLI
+        [(match_operand:ALLI 1 "register_operand" "r")
+         (use (match_operand:ALLI 2 "register_operand" ""))]
+        UNSPECV_SPECULATION_BARRIER))]
+  ""
+  "and\\t%<w>0, %<w>1, %<w>2\;hint\t0x14 // csdb"
+  [(set_attr "type" "block")
+   (set_attr "length" "8")
+   (set_attr "speculation_barrier" "true")]
+)
+
+(define_insn "despeculate_simpleti"
+  [(set (match_operand:TI 0 "register_operand" "=r")
+       (unspec_volatile:TI
+        [(match_operand:TI 1 "register_operand" "r")
+         (use (match_operand:DI 2 "register_operand" ""))]
+        UNSPECV_SPECULATION_BARRIER))]
+  ""
+  "and\\t%0, %1, %2\;and\\t%H0, %H1, %2\;hint\t0x14 // csdb"
+  [(set_attr "type" "block")
+   (set_attr "length" "12")
+   (set_attr "speculation_barrier" "true")]
+)
+
 ;; AdvSIMD Stuff
 (include "aarch64-simd.md")
 
index d846118d3b6b18da3796c98a5bd9aa6e15d83595..450edea8ca090f78e054eedc94b59abdebb68b55 100644 (file)
@@ -35,6 +35,9 @@
 ;; Iterator for all integer modes (up to 64-bit)
 (define_mode_iterator ALLI [QI HI SI DI])
 
+;; Iterator for all integer modes (up to 128-bit)
+(define_mode_iterator ALLI_TI [QI HI SI DI TI])
+
 ;; Iterator for all integer modes that can be extended (up to 64-bit)
 (define_mode_iterator ALLX [QI HI SI])