arm, aarch64: Add support for __GCC_ASM_FLAG_OUTPUTS__
authorRichard Henderson <richard.henderson@linaro.org>
Thu, 14 Nov 2019 13:44:34 +0000 (13:44 +0000)
committerRichard Henderson <rth@gcc.gnu.org>
Thu, 14 Nov 2019 13:44:34 +0000 (05:44 -0800)
Since all but a couple of lines is shared between the two targets,
enable them both at once.

* config/arm/aarch-common-protos.h (arm_md_asm_adjust): Declare.
* config/arm/aarch-common.c (arm_md_asm_adjust): New.
* config/arm/arm-c.c (arm_cpu_builtins): Define
__GCC_ASM_FLAG_OUTPUTS__.
* config/arm/arm.c (TARGET_MD_ASM_ADJUST): New.
* config/aarch64/aarch64-c.c (aarch64_define_unconditional_macros):
Define __GCC_ASM_FLAG_OUTPUTS__.
* config/aarch64/aarch64.c (TARGET_MD_ASM_ADJUST): New.
* doc/extend.texi (FlagOutputOperands): Add documentation
for ARM and AArch64.

From-SVN: r278226

gcc/ChangeLog
gcc/config/aarch64/aarch64-c.c
gcc/config/aarch64/aarch64.c
gcc/config/arm/aarch-common-protos.h
gcc/config/arm/aarch-common.c
gcc/config/arm/arm-c.c
gcc/config/arm/arm.c
gcc/doc/extend.texi

index 1043db59c8f1f9ccc1180dff4711bd15492a2a79..b4427fa5cd2ecbaf6bded0be17d2ed78b7c51529 100644 (file)
@@ -1,5 +1,16 @@
 2019-11-14  Richard Henderson  <richard.henderson@linaro.org>
 
+       * config/arm/aarch-common-protos.h (arm_md_asm_adjust): Declare.
+       * config/arm/aarch-common.c (arm_md_asm_adjust): New.
+       * config/arm/arm-c.c (arm_cpu_builtins): Define
+       __GCC_ASM_FLAG_OUTPUTS__.
+       * config/arm/arm.c (TARGET_MD_ASM_ADJUST): New.
+       * config/aarch64/aarch64-c.c (aarch64_define_unconditional_macros):
+       Define __GCC_ASM_FLAG_OUTPUTS__.
+       * config/aarch64/aarch64.c (TARGET_MD_ASM_ADJUST): New.
+       * doc/extend.texi (FlagOutputOperands): Add documentation
+       for ARM and AArch64.
+
        * config/arm/arm-modes.def (CC_NZ): Rename from CC_NOOV.
        * config/arm/predicates.md (nz_comparison_operator): Rename
        from noov_comparison_operator.
index 7c322ca0813caea8894abd0106dec04a75e714dc..0af859f1c144d8925f188657941f751228398de2 100644 (file)
@@ -69,6 +69,8 @@ aarch64_define_unconditional_macros (cpp_reader *pfile)
   builtin_define ("__ARM_FEATURE_UNALIGNED");
   builtin_define ("__ARM_PCS_AAPCS64");
   builtin_define_with_int_value ("__ARM_SIZEOF_WCHAR_T", WCHAR_TYPE_SIZE / 8);
+
+  builtin_define ("__GCC_ASM_FLAG_OUTPUTS__");
 }
 
 /* Undefine/redefine macros that depend on the current backend state and may
index d2a3c7ef90a97bd099f592e147830ceca0b9e3d9..9a5f27fea3a0b2f255c4e2549757be9b271da826 100644 (file)
@@ -21933,6 +21933,9 @@ aarch64_libgcc_floating_mode_supported_p
 #undef TARGET_STRICT_ARGUMENT_NAMING
 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
 
+#undef TARGET_MD_ASM_ADJUST
+#define TARGET_MD_ASM_ADJUST arm_md_asm_adjust
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-aarch64.h"
index 3bf38a104f6941eec1ce88db7d6b6ceb7da0af92..f15cf336e9dfbd2fdd742a32e83dfa9c8751f2a0 100644 (file)
@@ -23,6 +23,8 @@
 #ifndef GCC_AARCH_COMMON_PROTOS_H
 #define GCC_AARCH_COMMON_PROTOS_H
 
+#include "hard-reg-set.h"
+
 extern int aarch_accumulator_forwarding (rtx_insn *, rtx_insn *);
 extern bool aarch_rev16_p (rtx);
 extern bool aarch_rev16_shleft_mask_imm_p (rtx, machine_mode);
@@ -141,5 +143,9 @@ struct cpu_cost_table
   const struct vector_cost_table vect;
 };
 
+rtx_insn *
+arm_md_asm_adjust (vec<rtx> &outputs, vec<rtx> &/*inputs*/,
+                   vec<const char *> &constraints,
+                   vec<rtx> &clobbers, HARD_REG_SET &clobbered_regs);
 
 #endif /* GCC_AARCH_COMMON_PROTOS_H */
index 965a07a43e3129dd1743d4a79813a597feca0b71..760ef6c9c0a2f8477dc95e05c7f831f02277bd3c 100644 (file)
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "insn-modes.h"
 #include "tm.h"
 #include "rtl.h"
 #include "rtl-iter.h"
 #include "memmodel.h"
+#include "diagnostic.h"
+#include "tree.h"
+#include "expr.h"
+#include "function.h"
+#include "emit-rtl.h"
 
 /* Return TRUE if X is either an arithmetic shift left, or
    is a multiplication by a power of two.  */
@@ -520,3 +526,133 @@ arm_mac_accumulator_is_mul_result (rtx producer, rtx consumer)
           && !reg_overlap_mentioned_p (mul_result, mac_op0)
           && !reg_overlap_mentioned_p (mul_result, mac_op1));
 }
+
+/* Worker function for TARGET_MD_ASM_ADJUST.
+   We implement asm flag outputs.  */
+
+rtx_insn *
+arm_md_asm_adjust (vec<rtx> &outputs, vec<rtx> &/*inputs*/,
+                   vec<const char *> &constraints,
+                   vec<rtx> &/*clobbers*/, HARD_REG_SET &/*clobbered_regs*/)
+{
+  bool saw_asm_flag = false;
+
+  start_sequence ();
+  for (unsigned i = 0, n = outputs.length (); i < n; ++i)
+    {
+      const char *con = constraints[i];
+      if (strncmp (con, "=@cc", 4) != 0)
+       continue;
+      con += 4;
+      if (strchr (con, ',') != NULL)
+       {
+         error ("alternatives not allowed in %<asm%> flag output");
+         continue;
+       }
+
+      machine_mode mode;
+      rtx_code code;
+      int con01 = 0;
+
+#define C(X, Y)  (unsigned char)(X) * 256 + (unsigned char)(Y)
+
+      /* All of the condition codes are two characters.  */
+      if (con[0] != 0 && con[1] != 0 && con[2] == 0)
+       con01 = C(con[0], con[1]);
+
+      switch (con01)
+       {
+       case C('c', 'c'):
+       case C('l', 'o'):
+         mode = CC_Cmode, code = GEU;
+         break;
+       case C('c', 's'):
+       case C('h', 's'):
+         mode = CC_Cmode, code = LTU;
+         break;
+       case C('e', 'q'):
+         mode = CC_NZmode, code = EQ;
+         break;
+       case C('g', 'e'):
+         mode = CCmode, code = GE;
+         break;
+       case C('g', 't'):
+         mode = CCmode, code = GT;
+         break;
+       case C('h', 'i'):
+         mode = CCmode, code = GTU;
+         break;
+       case C('l', 'e'):
+         mode = CCmode, code = LE;
+         break;
+       case C('l', 's'):
+         mode = CCmode, code = LEU;
+         break;
+       case C('l', 't'):
+         mode = CCmode, code = LT;
+         break;
+       case C('m', 'i'):
+         mode = CC_NZmode, code = LT;
+         break;
+       case C('n', 'e'):
+         mode = CC_NZmode, code = NE;
+         break;
+       case C('p', 'l'):
+         mode = CC_NZmode, code = GE;
+         break;
+       case C('v', 'c'):
+         mode = CC_Vmode, code = EQ;
+         break;
+       case C('v', 's'):
+         mode = CC_Vmode, code = NE;
+         break;
+       default:
+         error ("unknown %<asm%> flag output %qs", constraints[i]);
+         continue;
+       }
+
+#undef C
+
+      rtx dest = outputs[i];
+      machine_mode dest_mode = GET_MODE (dest);
+      if (!SCALAR_INT_MODE_P (dest_mode))
+       {
+         error ("invalid type for %<asm%> flag output");
+         continue;
+       }
+
+      if (!saw_asm_flag)
+       {
+         /* This is the first asm flag output.  Here we put the flags
+            register in as the real output and adjust the condition to
+            allow it.  */
+         constraints[i] = "=c";
+         outputs[i] = gen_rtx_REG (CCmode, CC_REGNUM);
+         saw_asm_flag = true;
+       }
+      else
+       {
+         /* We don't need the flags register as output twice.  */
+         constraints[i] = "=X";
+         outputs[i] = gen_rtx_SCRATCH (word_mode);
+       }
+
+      rtx x = gen_rtx_REG (mode, CC_REGNUM);
+      x = gen_rtx_fmt_ee (code, word_mode, x, const0_rtx);
+
+      if (dest_mode == word_mode)
+       emit_insn (gen_rtx_SET (dest, x));
+      else
+       {
+         rtx tmp = gen_reg_rtx (word_mode);
+         emit_insn (gen_rtx_SET (tmp, x));
+
+         tmp = convert_modes (dest_mode, word_mode, tmp, true);
+         emit_move_insn (dest, tmp);
+       }
+    }
+  rtx_insn *seq = get_insns ();
+  end_sequence ();
+
+  return saw_asm_flag ? seq : NULL;
+}
index 34695fa0112e90e4bdf317da0b9fd1d3194bf0a2..c4485ce7af15f1fa135a3658677642ed18663968 100644 (file)
@@ -122,6 +122,7 @@ arm_cpu_builtins (struct cpp_reader* pfile)
   if (arm_arch_notm)
     builtin_define ("__ARM_ARCH_ISA_ARM");
   builtin_define ("__APCS_32__");
+  builtin_define ("__GCC_ASM_FLAG_OUTPUTS__");
 
   def_or_undef_macro (pfile, "__thumb__", TARGET_THUMB);
   def_or_undef_macro (pfile, "__thumb2__", TARGET_THUMB2);
index d996207853c2bb9b763d2459a43e8708724dafee..fea3882a2a625bfc11a0175ee9bae0437aa70ace 100644 (file)
@@ -816,6 +816,9 @@ static const struct attribute_spec arm_attribute_table[] =
 
 #undef TARGET_CONSTANT_ALIGNMENT
 #define TARGET_CONSTANT_ALIGNMENT arm_constant_alignment
+
+#undef TARGET_MD_ASM_ADJUST
+#define TARGET_MD_ASM_ADJUST arm_md_asm_adjust
 \f
 /* Obstack for minipool constant handling.  */
 static struct obstack minipool_obstack;
index 9db4f9b1d2991000223e00f155e28817d76efde4..1c8ae0d5cd316f2af8b3f6458f0703c840efb545 100644 (file)
@@ -9771,6 +9771,45 @@ referenced within the assembler template via @code{%0} etc, as there's
 no corresponding text in the assembly language.
 
 @table @asis
+@item ARM
+@itemx AArch64
+The flag output constraints for the ARM family are of the form
+@samp{=@@cc@var{cond}} where @var{cond} is one of the standard
+conditions defined in the ARM ARM for @code{ConditionHolds}.
+
+@table @code
+@item eq
+Z flag set, or equal
+@item ne
+Z flag clear or not equal
+@item cs
+@itemx hs
+C flag set or unsigned greater than equal
+@item cc
+@itemx lo
+C flag clear or unsigned less than
+@item mi
+N flag set or ``minus''
+@item pl
+N flag clear or ``plus''
+@item vs
+V flag set or signed overflow
+@item vc
+V flag clear
+@item hi
+unsigned greater than
+@item ls
+unsigned less than equal
+@item ge
+signed greater than equal
+@item lt
+signed less than
+@item gt
+signed greater than
+@item le
+signed less than equal
+@end table
+
 @item x86 family
 The flag output constraints for the x86 family are of the form
 @samp{=@@cc@var{cond}} where @var{cond} is one of the standard