* Claudiu Zissulescu <claudiu.zissule...@synopsys.com> [2017-11-02 13:30:35 
+0100]:

> From: claziss <claz...@synopsys.com>
> 
> The 'aux' variable attribute is used to directly access the auxiliary
> register space from C.
> 
> gcc/
> 2017-07-25  Claudiu Zissulescu  <claz...@synopsys.com>
> 
>       * config/arc/arc.c (arc_handle_aux_attribute): New function.
>       (arc_attribute_table): Add 'aux' attribute.
>       (arc_in_small_data_p): Consider aux like variables.
>       (arc_is_aux_reg_p): New function.
>       (arc_asm_output_aligned_decl_local): Ignore 'aux' like variables.
>       (arc_get_aux_arg): New function.
>       (prepare_move_operands): Handle aux-register access.
>       (arc_handle_aux_attribute): New function.
>       * doc/extend.texi (ARC Variable attributes): Add subsection.
> 
> testsuite/
> 2017-07-25  Claudiu Zissulescu  <claz...@synopsys.com>
> 
>       * gcc.target/arc/taux-1.c: New test.
>       * gcc.target/arc/taux-2.c: Likewise.

Looks good.

Sorry for the time taken to review this series.

Thanks,
Andrew


> ---
>  gcc/config/arc/arc.c                  | 160 
> +++++++++++++++++++++++++++++++++-
>  gcc/doc/extend.texi                   |  13 +++
>  gcc/testsuite/gcc.target/arc/taux-1.c |  38 ++++++++
>  gcc/testsuite/gcc.target/arc/taux-2.c |  15 ++++
>  4 files changed, 225 insertions(+), 1 deletion(-)
>  create mode 100644 gcc/testsuite/gcc.target/arc/taux-1.c
>  create mode 100644 gcc/testsuite/gcc.target/arc/taux-2.c
> 
> diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
> index a397cbd..33f68ef 100644
> --- a/gcc/config/arc/arc.c
> +++ b/gcc/config/arc/arc.c
> @@ -223,6 +223,7 @@ static tree arc_handle_fndecl_attribute (tree *, tree, 
> tree, int, bool *);
>  static tree arc_handle_jli_attribute (tree *, tree, tree, int, bool *);
>  static tree arc_handle_secure_attribute (tree *, tree, tree, int, bool *);
>  static tree arc_handle_uncached_attribute (tree *, tree, tree, int, bool *);
> +static tree arc_handle_aux_attribute (tree *, tree, tree, int, bool *);
>  
>  /* Initialized arc_attribute_table to NULL since arc doesnot have any
>     machine specific supported attributes.  */
> @@ -257,6 +258,8 @@ const struct attribute_spec arc_attribute_table[] =
>    /* Bypass caches using .di flag.  */
>    { "uncached", 0, 0, false, true, false, arc_handle_uncached_attribute,
>      false },
> +  /* Declare a variable as aux.  */
> +  { "aux", 0, 1, true, false, false, arc_handle_aux_attribute, false },
>    { NULL, 0, 0, false, false, false, NULL, false }
>  };
>  static int arc_comp_type_attributes (const_tree, const_tree);
> @@ -8071,6 +8074,11 @@ arc_in_small_data_p (const_tree decl)
>    if (lookup_attribute ("uncached", attr))
>      return false;
>  
> +  /* and for aux regs.  */
> +  attr = DECL_ATTRIBUTES (decl);
> +  if (lookup_attribute ("aux", attr))
> +    return false;
> +
>    if (DECL_SECTION_NAME (decl) != 0)
>      {
>        const char *name = DECL_SECTION_NAME (decl);
> @@ -8238,6 +8246,35 @@ compact_sda_memory_operand (rtx op, machine_mode mode, 
> bool short_p)
>    return false;
>  }
>  
> +/* Return TRUE if PAT is accessing an aux-reg.  */
> +
> +static bool
> +arc_is_aux_reg_p (rtx pat)
> +{
> +  tree attrs = NULL_TREE;
> +  tree addr;
> +
> +  if (!MEM_P (pat))
> +    return false;
> +
> +  /* Get the memory attributes.  */
> +  addr = MEM_EXPR (pat);
> +  if (!addr)
> +    return false;
> +
> +  /* Get the attributes.  */
> +  if (TREE_CODE (addr) == VAR_DECL)
> +    attrs = DECL_ATTRIBUTES (addr);
> +  else if (TREE_CODE (addr) == MEM_REF)
> +    attrs = TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr, 0)));
> +  else
> +    return false;
> +
> +  if (lookup_attribute ("aux", attrs))
> +    return true;
> +  return false;
> +}
> +
>  /* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL.  */
>  
>  void
> @@ -8246,7 +8283,14 @@ arc_asm_output_aligned_decl_local (FILE * stream, tree 
> decl, const char * name,
>                                  unsigned HOST_WIDE_INT align,
>                                  unsigned HOST_WIDE_INT globalize_p)
>  {
> -  int in_small_data =   arc_in_small_data_p (decl);
> +  int in_small_data = arc_in_small_data_p (decl);
> +  rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
> +
> +  /* Don't output aux-reg symbols.  */
> +  if (mem != NULL_RTX && MEM_P (mem)
> +      && SYMBOL_REF_P (XEXP (mem, 0))
> +      && arc_is_aux_reg_p (mem))
> +    return;
>  
>    if (in_small_data)
>      switch_to_section (get_named_section (NULL, ".sbss", 0));
> @@ -8586,12 +8630,80 @@ arc_expand_movmem (rtx *operands)
>    return true;
>  }
>  
> +static bool
> +arc_get_aux_arg (rtx pat, int *auxr)
> +{
> +  tree attr, addr = MEM_EXPR (pat);
> +  if (TREE_CODE (addr) != VAR_DECL)
> +    return false;
> +
> +  attr = DECL_ATTRIBUTES (addr);
> +  if (lookup_attribute ("aux", attr))
> +    {
> +      tree arg = TREE_VALUE (attr);
> +      if (arg)
> +     {
> +       *auxr = TREE_INT_CST_LOW (TREE_VALUE (arg));
> +       return true;
> +     }
> +    }
> +
> +  return false;
> +}
> +
>  /* Prepare operands for move in MODE.  Return true iff the move has
>     been emitted.  */
>  
>  bool
>  prepare_move_operands (rtx *operands, machine_mode mode)
>  {
> +  /* First handle aux attribute.  */
> +  if (mode == SImode
> +      && (MEM_P (operands[0]) || MEM_P (operands[1])))
> +    {
> +      rtx tmp;
> +      int auxr = 0;
> +      if (MEM_P (operands[0]) && arc_is_aux_reg_p (operands[0]))
> +     {
> +       /* Save operation.  */
> +       if (arc_get_aux_arg (operands[0], &auxr))
> +         {
> +           tmp = gen_reg_rtx (SImode);
> +           emit_move_insn (tmp, GEN_INT (auxr));
> +         }
> +       else
> +         {
> +           tmp = XEXP (operands[0], 0);
> +         }
> +
> +       operands[1] = force_reg (SImode, operands[1]);
> +       emit_insn (gen_rtx_UNSPEC_VOLATILE
> +                  (VOIDmode, gen_rtvec (2, operands[1], tmp),
> +                   VUNSPEC_ARC_SR));
> +       return true;
> +     }
> +      if (MEM_P (operands[1]) && arc_is_aux_reg_p (operands[1]))
> +     {
> +       if (arc_get_aux_arg (operands[1], &auxr))
> +         {
> +           tmp = gen_reg_rtx (SImode);
> +           emit_move_insn (tmp, GEN_INT (auxr));
> +         }
> +       else
> +         {
> +           tmp = XEXP (operands[1], 0);
> +           gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
> +         }
> +       /* Load operation.  */
> +       gcc_assert (REG_P (operands[0]));
> +       emit_insn (gen_rtx_SET (operands[0],
> +                               gen_rtx_UNSPEC_VOLATILE
> +                               (SImode, gen_rtvec (1, tmp),
> +                                VUNSPEC_ARC_LR)));
> +       return true;
> +     }
> +    }
> +
>    /* We used to do this only for MODE_INT Modes, but addresses to floating
>       point variables may well be in the small data section.  */
>    if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[0], Pmode))
> @@ -11127,6 +11239,52 @@ arc_is_uncached_mem_p (rtx pat)
>    return false;
>  }
>  
> +/* Handle aux attribute.  The auxiliary registers are addressed using
> +   special instructions lr and sr.  The attribute 'aux' indicates if a
> +   variable refers to the aux-regs and what is the register number
> +   desired.  */
> +
> +static tree
> +arc_handle_aux_attribute (tree *node,
> +                       tree name, tree args, int,
> +                       bool *no_add_attrs)
> +{
> +  /* Isn't it better to use address spaces for the aux-regs?  */
> +  if (DECL_P (*node))
> +    {
> +      if (TREE_CODE (*node) != VAR_DECL)
> +     {
> +       error ("%qE attribute only applies to variables",  name);
> +       *no_add_attrs = true;
> +     }
> +      else if (args)
> +     {
> +       if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
> +         TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
> +       tree arg = TREE_VALUE (args);
> +       if (TREE_CODE (arg) != INTEGER_CST)
> +         {
> +           warning (0, "%qE attribute allows only an integer "
> +                    "constant argument", name);
> +           *no_add_attrs = true;
> +         }
> +       /* FIXME! add range check.  TREE_INT_CST_LOW (arg) */
> +     }
> +
> +      if (TREE_CODE (*node) == VAR_DECL)
> +     {
> +       tree fntype = TREE_TYPE (*node);
> +       if (fntype && TREE_CODE (fntype) == POINTER_TYPE)
> +         {
> +           tree attrs = tree_cons (get_identifier ("aux"), NULL_TREE,
> +                                   TYPE_ATTRIBUTES (fntype));
> +           TYPE_ATTRIBUTES (fntype) = attrs;
> +         }
> +     }
> +    }
> +  return NULL_TREE;
> +}
> +
>  /* Implement TARGET_USE_ANCHORS_FOR_SYMBOL_P.  We don't want to use
>     anchors for small data: the GP register acts as an anchor in that
>     case.  We also don't want to use them for PC-relative accesses,
> diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> index 0f8ba05..1f6ef4e 100644
> --- a/gcc/doc/extend.texi
> +++ b/gcc/doc/extend.texi
> @@ -5803,6 +5803,7 @@ attributes.
>  
>  @menu
>  * Common Variable Attributes::
> +* ARC Variable Attributes::
>  * AVR Variable Attributes::
>  * Blackfin Variable Attributes::
>  * H8/300 Variable Attributes::
> @@ -6165,6 +6166,18 @@ The @code{weak} attribute is described in
>  
>  @end table
>  
> +@node ARC Variable Attributes
> +@subsection ARC Variable Attributes
> +
> +@table @code
> +@item aux
> +@cindex @code{aux} variable attribute, ARC
> +The @code{aux} attribute is used to directly access the ARC's
> +auxiliary register space from C.  The auxilirary register number is
> +given via attribute argument.
> +
> +@end table
> +
>  @node AVR Variable Attributes
>  @subsection AVR Variable Attributes
>  
> diff --git a/gcc/testsuite/gcc.target/arc/taux-1.c 
> b/gcc/testsuite/gcc.target/arc/taux-1.c
> new file mode 100644
> index 0000000..a2b7778
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arc/taux-1.c
> @@ -0,0 +1,38 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O1 */
> +
> +
> +#define __aux() __attribute__((aux))
> +
> +__aux() int *a_ptr;
> +extern __aux() int a_var;
> +
> +/* Generates:
> +   mov r0, @a_var
> +   sr  10,[r0]
> +*/
> +void foo (void)
> +{
> +  a_var = 10;
> +}
> +
> +/* Generates:
> +   mov r0, @a_ptr
> +   sr  a_var,[r0]
> +*/
> +void foo1 (void)
> +{
> +  a_ptr = &a_var;
> +}
> +
> +/* Generates:
> +   lr  %r1,[a_ptr]
> +   sr  10,[%r1]
> +*/
> +void foo2 (void)
> +{
> +  *a_ptr = 10;
> +}
> +
> +/* { dg-final { scan-assembler-times "sr" 3 } } */
> +/* { dg-final { scan-assembler-times "lr" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/arc/taux-2.c 
> b/gcc/testsuite/gcc.target/arc/taux-2.c
> new file mode 100644
> index 0000000..5644bcd
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arc/taux-2.c
> @@ -0,0 +1,15 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O1 */
> +
> +#define __aux(r) __attribute__((aux(r)))
> +static volatile __aux(0x1000) int var;
> +
> +int foo (void)
> +{
> +  var++;
> +}
> +
> +/* { dg-final { scan-assembler-times "sr" 1 } } */
> +/* { dg-final { scan-assembler-times "lr" 1 } } */
> +/* { dg-final { scan-assembler "4096" } } */
> +/* { dg-final { scan-assembler-not "\\.type\tvar, @object" } } */
> -- 
> 1.9.1
> 

Reply via email to