[PATCH v2 4/6] arm, aarch64: Add support for __GCC_ASM_FLAG_OUTPUTS__

Richard Earnshaw (lists) Richard.Earnshaw@arm.com
Thu Nov 14 14:53:00 GMT 2019


On 14/11/2019 10:07, Richard Henderson wrote:
> 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.

In AArch64 when SVE is enabled, there are some additional condition 
names which are more suited for describing the way conditions are set by 
the SVE instructions.  Do you plan to support those as well?

R.

> ---
>   gcc/config/arm/aarch-common-protos.h |   6 ++
>   gcc/config/aarch64/aarch64-c.c       |   2 +
>   gcc/config/aarch64/aarch64.c         |   3 +
>   gcc/config/arm/aarch-common.c        | 136 +++++++++++++++++++++++++++
>   gcc/config/arm/arm-c.c               |   1 +
>   gcc/config/arm/arm.c                 |   3 +
>   gcc/doc/extend.texi                  |  39 ++++++++
>   7 files changed, 190 insertions(+)
> 
> diff --git a/gcc/config/arm/aarch-common-protos.h b/gcc/config/arm/aarch-common-protos.h
> index 3bf38a104f6..f15cf336e9d 100644
> --- a/gcc/config/arm/aarch-common-protos.h
> +++ b/gcc/config/arm/aarch-common-protos.h
> @@ -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 */
> diff --git a/gcc/config/aarch64/aarch64-c.c b/gcc/config/aarch64/aarch64-c.c
> index 7c322ca0813..0af859f1c14 100644
> --- a/gcc/config/aarch64/aarch64-c.c
> +++ b/gcc/config/aarch64/aarch64-c.c
> @@ -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
> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
> index d2a3c7ef90a..9a5f27fea3a 100644
> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -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"
> diff --git a/gcc/config/arm/aarch-common.c b/gcc/config/arm/aarch-common.c
> index 965a07a43e3..760ef6c9c0a 100644
> --- a/gcc/config/arm/aarch-common.c
> +++ b/gcc/config/arm/aarch-common.c
> @@ -26,10 +26,16 @@
>   #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;
> +}
> diff --git a/gcc/config/arm/arm-c.c b/gcc/config/arm/arm-c.c
> index 34695fa0112..c4485ce7af1 100644
> --- a/gcc/config/arm/arm-c.c
> +++ b/gcc/config/arm/arm-c.c
> @@ -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);
> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> index d996207853c..fea3882a2a6 100644
> --- a/gcc/config/arm/arm.c
> +++ b/gcc/config/arm/arm.c
> @@ -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
>   

>   /* Obstack for minipool constant handling.  */
>   static struct obstack minipool_obstack;
> diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> index 9db4f9b1d29..1c8ae0d5cd3 100644
> --- a/gcc/doc/extend.texi
> +++ b/gcc/doc/extend.texi
> @@ -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
> 



More information about the Gcc-patches mailing list