diff mbox series

[5/6,ARC] Add 'uncached' attribute.

Message ID 1509625835-22344-6-git-send-email-claziss@synopsys.com
State New
Headers show
Series New baremetal features and fixes | expand

Commit Message

Claudiu Zissulescu Nov. 2, 2017, 12:30 p.m. UTC
From: claziss <claziss@synopsys.com>

The _Uncached type qualifier can be used to bypass the cache without
resorting to declaring variables as volatile.

gcc/
2017-07-12  Claudiu Zissulescu  <claziss@synopsys.com>

	* config/arc/arc-protos.h (arc_is_uncached_mem_p): Function proto.
	* config/arc/arc.c (arc_handle_uncached_attribute): New function.
	(arc_attribute_table): Add 'uncached' attribute.
	(arc_print_operand): Print '.di' flag for uncached memory
	accesses.
	(arc_in_small_data_p): Do not consider for small data the uncached
	types.
	(arc_is_uncached_mem_p): New function.
	* config/arc/predicates.md (compact_store_memory_operand): Check
	for uncached memory accesses.
	(nonvol_nonimm_operand): Likewise.

gcc/testsuite
2017-07-12  Claudiu Zissulescu  <claziss@synopsys.com>

	* gcc.target/arc/uncached.c: New test.
---
 gcc/config/arc/arc-protos.h             |  1 +
 gcc/config/arc/arc.c                    | 65 ++++++++++++++++++++++++++++++++-
 gcc/config/arc/predicates.md            |  7 +++-
 gcc/testsuite/gcc.target/arc/uncached.c | 18 +++++++++
 4 files changed, 88 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arc/uncached.c

Comments

Sandra Loosemore Nov. 3, 2017, 2:26 a.m. UTC | #1
On 11/02/2017 06:30 AM, Claudiu Zissulescu wrote:
> From: claziss <claziss@synopsys.com>
>
> The _Uncached type qualifier can be used to bypass the cache without
> resorting to declaring variables as volatile.
>
> gcc/
> 2017-07-12  Claudiu Zissulescu  <claziss@synopsys.com>
>
> 	* config/arc/arc-protos.h (arc_is_uncached_mem_p): Function proto.
> 	* config/arc/arc.c (arc_handle_uncached_attribute): New function.
> 	(arc_attribute_table): Add 'uncached' attribute.
> 	(arc_print_operand): Print '.di' flag for uncached memory
> 	accesses.
> 	(arc_in_small_data_p): Do not consider for small data the uncached
> 	types.
> 	(arc_is_uncached_mem_p): New function.
> 	* config/arc/predicates.md (compact_store_memory_operand): Check
> 	for uncached memory accesses.
> 	(nonvol_nonimm_operand): Likewise.

I see no documentation here.

-Sandra
Claudiu Zissulescu Nov. 3, 2017, 11:22 a.m. UTC | #2
> 
> I see no documentation here.
> 

Ups, forgot this one :) Please find it attached. I'll merge it into the final patch when everything is approved.

Thanks,
Claudiu
Sandra Loosemore Nov. 3, 2017, 6:55 p.m. UTC | #3
On 11/03/2017 05:22 AM, Claudiu Zissulescu wrote:
>>
>> I see no documentation here.
>>
>
> Ups, forgot this one :) Please find it attached. I'll merge it into the final patch when everything is approved.
>
> Thanks,
> Claudiu
>
> +@node ARC Type Attributes
> +@subsection ARC Type Attributes
> +
> +@cindex @code{uncached} type attribute, ARC
> +Declaring variables @code{uncached} allows you to exclude data-cache

Since this is a type attribute and not a variable attribute (I presume 
to allow accessing objects through a pointer), it would be better to say

Declaring objects with the @code{uncached} type attribute allows....

> +participation in load and store operations on those variables without

And s/variables/objects/ here too.

> +involving the additional semantic implications of volatile.  The

You probably want @code{volatile} markup here?

> +@code{.di} instruction suffix is used for all loads and stores of data
> +declared @code{uncached}.
> +

Otherwise, the description makes sense to me.  (In fact, I might 
eventually want to copy this attribute over to the Nios II backend, too, 
since it also has similar "io"-variant load/store instructions.)

-Sandra
Claudiu Zissulescu Nov. 9, 2017, 9:09 a.m. UTC | #4
Just for the record, here it is the updated documentation as suggested. And, indeed the description may very well be suited for NIOS io-variant as well.

Thank you Sandra,
Claudiu

---
 gcc/doc/extend.texi | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index a7a770f..3243494 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -6728,6 +6728,7 @@ attributes.
 
 @menu
 * Common Type Attributes::
+* ARC Type Attributes::
 * ARM Type Attributes::
 * MeP Type Attributes::
 * PowerPC Type Attributes::
@@ -7161,6 +7162,16 @@ To specify multiple attributes, separate them by commas within the
 double parentheses: for example, @samp{__attribute__ ((aligned (16),
 packed))}.
 
+@node ARC Type Attributes
+@subsection ARC Type Attributes
+
+@cindex @code{uncached} type attribute, ARC
+Declaring objects with @code{uncached} allows you to exclude
+data-cache participation in load and store operations on those objects
+without involving the additional semantic implications of
+@code{volatile}.  The @code{.di} instruction suffix is used for all
+loads and stores of data declared @code{uncached}.
+
 @node ARM Type Attributes
 @subsection ARM Type Attributes
Andrew Burgess Jan. 29, 2018, 7:25 p.m. UTC | #5
* Claudiu Zissulescu <Claudiu.Zissulescu@synopsys.com> [2017-11-02 13:30:34 +0100]:

> From: claziss <claziss@synopsys.com>
> 
> The _Uncached type qualifier can be used to bypass the cache without
> resorting to declaring variables as volatile.
> 
> gcc/
> 2017-07-12  Claudiu Zissulescu  <claziss@synopsys.com>
> 
> 	* config/arc/arc-protos.h (arc_is_uncached_mem_p): Function proto.
> 	* config/arc/arc.c (arc_handle_uncached_attribute): New function.
> 	(arc_attribute_table): Add 'uncached' attribute.
> 	(arc_print_operand): Print '.di' flag for uncached memory
> 	accesses.
> 	(arc_in_small_data_p): Do not consider for small data the uncached
> 	types.
> 	(arc_is_uncached_mem_p): New function.
> 	* config/arc/predicates.md (compact_store_memory_operand): Check
> 	for uncached memory accesses.
> 	(nonvol_nonimm_operand): Likewise.
> 
> gcc/testsuite
> 2017-07-12  Claudiu Zissulescu  <claziss@synopsys.com>

Looks good, with the updated documentation.

Thanks,
Andrew


> 
> 	* gcc.target/arc/uncached.c: New test.
> ---
>  gcc/config/arc/arc-protos.h             |  1 +
>  gcc/config/arc/arc.c                    | 65 ++++++++++++++++++++++++++++++++-
>  gcc/config/arc/predicates.md            |  7 +++-
>  gcc/testsuite/gcc.target/arc/uncached.c | 18 +++++++++
>  4 files changed, 88 insertions(+), 3 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/arc/uncached.c
> 
> diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
> index f8e7937..cc00730 100644
> --- a/gcc/config/arc/arc-protos.h
> +++ b/gcc/config/arc/arc-protos.h
> @@ -47,6 +47,7 @@ extern void arc_expand_compare_and_swap (rtx *);
>  extern bool compact_memory_operand_p (rtx, machine_mode, bool, bool);
>  extern int arc_return_address_register (unsigned int);
>  extern unsigned int arc_compute_function_type (struct function *);
> +extern bool arc_is_uncached_mem_p (rtx);
>  #endif /* RTX_CODE */
>  
>  extern unsigned int arc_compute_frame_size (int);
> diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
> index 07dd072..a397cbd 100644
> --- a/gcc/config/arc/arc.c
> +++ b/gcc/config/arc/arc.c
> @@ -222,7 +222,7 @@ static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
>  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 *);
>  
>  /* Initialized arc_attribute_table to NULL since arc doesnot have any
>     machine specific supported attributes.  */
> @@ -254,6 +254,9 @@ const struct attribute_spec arc_attribute_table[] =
>    /* Call a function using secure-mode.  */
>    { "secure_call",  1, 1, false, true, true, arc_handle_secure_attribute,
>      false },
> +  /* Bypass caches using .di flag.  */
> +  { "uncached", 0, 0, false, true, false, arc_handle_uncached_attribute,
> +    false },
>    { NULL, 0, 0, false, false, false, NULL, false }
>  };
>  static int arc_comp_type_attributes (const_tree, const_tree);
> @@ -4135,7 +4138,8 @@ arc_print_operand (FILE *file, rtx x, int code)
>  	 refs are defined to use the cache bypass mechanism.  */
>        if (GET_CODE (x) == MEM)
>  	{
> -	  if (MEM_VOLATILE_P (x) && !TARGET_VOLATILE_CACHE_SET )
> +	  if ((MEM_VOLATILE_P (x) && !TARGET_VOLATILE_CACHE_SET)
> +	      || arc_is_uncached_mem_p (x))
>  	    fputs (".di", file);
>  	}
>        else
> @@ -8038,6 +8042,7 @@ static bool
>  arc_in_small_data_p (const_tree decl)
>  {
>    HOST_WIDE_INT size;
> +  tree attr;
>  
>    /* Only variables are going into small data area.  */
>    if (TREE_CODE (decl) != VAR_DECL)
> @@ -8061,6 +8066,11 @@ arc_in_small_data_p (const_tree decl)
>        && TREE_THIS_VOLATILE (decl))
>      return false;
>  
> +  /* Likewise for uncached data.  */
> +  attr = TYPE_ATTRIBUTES (TREE_TYPE (decl));
> +  if (lookup_attribute ("uncached", attr))
> +    return false;
> +
>    if (DECL_SECTION_NAME (decl) != 0)
>      {
>        const char *name = DECL_SECTION_NAME (decl);
> @@ -11066,6 +11076,57 @@ arc_is_secure_call_p (rtx pat)
>    return false;
>  }
>  
> +/* Handle "uncached" qualifier.  */
> +
> +static tree
> +arc_handle_uncached_attribute (tree *node,
> +			       tree name, tree args,
> +			       int flags ATTRIBUTE_UNUSED,
> +			       bool *no_add_attrs)
> +{
> +  if (DECL_P (*node) && TREE_CODE (*node) != TYPE_DECL)
> +    {
> +      error ("%qE attribute only applies to types",
> +	     name);
> +      *no_add_attrs = true;
> +    }
> +  else if (args)
> +    {
> +      warning (OPT_Wattributes, "argument of %qE attribute ignored", name);
> +    }
> +  return NULL_TREE;
> +}
> +
> +/* Return TRUE if PAT is a memory addressing an uncached data.  */
> +
> +bool
> +arc_is_uncached_mem_p (rtx pat)
> +{
> +  tree attrs;
> +  tree ttype;
> +  struct mem_attrs *refattrs;
> +
> +  if (!MEM_P (pat))
> +    return false;
> +
> +  /* Get the memory attributes.  */
> +  refattrs = MEM_ATTRS (pat);
> +  if (!refattrs
> +      || !refattrs->expr)
> +    return false;
> +
> +  /* Get the type declaration.  */
> +  ttype = TREE_TYPE (refattrs->expr);
> +  if (!ttype)
> +    return false;
> +
> +  /* Get the type attributes.  */
> +  attrs = TYPE_ATTRIBUTES (ttype);
> +  if (lookup_attribute ("uncached", attrs))
> +    return true;
> +  return false;
> +}
> +
>  /* 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/config/arc/predicates.md b/gcc/config/arc/predicates.md
> index 3dfe0ca..68887be 100644
> --- a/gcc/config/arc/predicates.md
> +++ b/gcc/config/arc/predicates.md
> @@ -217,6 +217,10 @@
>    if (MEM_VOLATILE_P (op) && !TARGET_VOLATILE_CACHE_SET)
>       return 0;
>  
> +  /* likewise for uncached types.  */
> +  if (arc_is_uncached_mem_p (op))
> +     return 0;
> +
>    size = GET_MODE_SIZE (mode);
>  
>    /* dword operations really put out 2 instructions, so eliminate them.  */
> @@ -412,7 +416,8 @@
>  ;; and only the standard movXX patterns are set up to handle them.
>  (define_predicate "nonvol_nonimm_operand"
>    (and (match_code "subreg, reg, mem")
> -       (match_test "(GET_CODE (op) != MEM || !MEM_VOLATILE_P (op)) && nonimmediate_operand (op, mode)"))
> +       (match_test "(GET_CODE (op) != MEM || !MEM_VOLATILE_P (op)) && nonimmediate_operand (op, mode)")
> +       (match_test "!arc_is_uncached_mem_p (op)"))
>  )
>  
>  ;; Return 1 if OP is a comparison operator valid for the mode of CC.
> diff --git a/gcc/testsuite/gcc.target/arc/uncached.c b/gcc/testsuite/gcc.target/arc/uncached.c
> new file mode 100644
> index 0000000..367e8dc
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arc/uncached.c
> @@ -0,0 +1,18 @@
> +/* { dg-do compile } */
> +
> +/* Check 'uncached' type attribute.  */
> +
> +typedef volatile unsigned int RwReg  __attribute__ ((uncached));
> +
> +typedef struct {
> +  RwReg UART_THR;
> +  int SIDE_DISH;
> +} UART;
> +
> +void uart_putc(UART *port, char c)
> +{
> +    port->UART_THR = c;
> +    port->SIDE_DISH = c;
> +}
> +
> +/* { dg-final { scan-assembler-times "st\.di" 1 } } */
> -- 
> 1.9.1
>
diff mbox series

Patch

diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
index f8e7937..cc00730 100644
--- a/gcc/config/arc/arc-protos.h
+++ b/gcc/config/arc/arc-protos.h
@@ -47,6 +47,7 @@  extern void arc_expand_compare_and_swap (rtx *);
 extern bool compact_memory_operand_p (rtx, machine_mode, bool, bool);
 extern int arc_return_address_register (unsigned int);
 extern unsigned int arc_compute_function_type (struct function *);
+extern bool arc_is_uncached_mem_p (rtx);
 #endif /* RTX_CODE */
 
 extern unsigned int arc_compute_frame_size (int);
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index 07dd072..a397cbd 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -222,7 +222,7 @@  static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
 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 *);
 
 /* Initialized arc_attribute_table to NULL since arc doesnot have any
    machine specific supported attributes.  */
@@ -254,6 +254,9 @@  const struct attribute_spec arc_attribute_table[] =
   /* Call a function using secure-mode.  */
   { "secure_call",  1, 1, false, true, true, arc_handle_secure_attribute,
     false },
+  /* Bypass caches using .di flag.  */
+  { "uncached", 0, 0, false, true, false, arc_handle_uncached_attribute,
+    false },
   { NULL, 0, 0, false, false, false, NULL, false }
 };
 static int arc_comp_type_attributes (const_tree, const_tree);
@@ -4135,7 +4138,8 @@  arc_print_operand (FILE *file, rtx x, int code)
 	 refs are defined to use the cache bypass mechanism.  */
       if (GET_CODE (x) == MEM)
 	{
-	  if (MEM_VOLATILE_P (x) && !TARGET_VOLATILE_CACHE_SET )
+	  if ((MEM_VOLATILE_P (x) && !TARGET_VOLATILE_CACHE_SET)
+	      || arc_is_uncached_mem_p (x))
 	    fputs (".di", file);
 	}
       else
@@ -8038,6 +8042,7 @@  static bool
 arc_in_small_data_p (const_tree decl)
 {
   HOST_WIDE_INT size;
+  tree attr;
 
   /* Only variables are going into small data area.  */
   if (TREE_CODE (decl) != VAR_DECL)
@@ -8061,6 +8066,11 @@  arc_in_small_data_p (const_tree decl)
       && TREE_THIS_VOLATILE (decl))
     return false;
 
+  /* Likewise for uncached data.  */
+  attr = TYPE_ATTRIBUTES (TREE_TYPE (decl));
+  if (lookup_attribute ("uncached", attr))
+    return false;
+
   if (DECL_SECTION_NAME (decl) != 0)
     {
       const char *name = DECL_SECTION_NAME (decl);
@@ -11066,6 +11076,57 @@  arc_is_secure_call_p (rtx pat)
   return false;
 }
 
+/* Handle "uncached" qualifier.  */
+
+static tree
+arc_handle_uncached_attribute (tree *node,
+			       tree name, tree args,
+			       int flags ATTRIBUTE_UNUSED,
+			       bool *no_add_attrs)
+{
+  if (DECL_P (*node) && TREE_CODE (*node) != TYPE_DECL)
+    {
+      error ("%qE attribute only applies to types",
+	     name);
+      *no_add_attrs = true;
+    }
+  else if (args)
+    {
+      warning (OPT_Wattributes, "argument of %qE attribute ignored", name);
+    }
+  return NULL_TREE;
+}
+
+/* Return TRUE if PAT is a memory addressing an uncached data.  */
+
+bool
+arc_is_uncached_mem_p (rtx pat)
+{
+  tree attrs;
+  tree ttype;
+  struct mem_attrs *refattrs;
+
+  if (!MEM_P (pat))
+    return false;
+
+  /* Get the memory attributes.  */
+  refattrs = MEM_ATTRS (pat);
+  if (!refattrs
+      || !refattrs->expr)
+    return false;
+
+  /* Get the type declaration.  */
+  ttype = TREE_TYPE (refattrs->expr);
+  if (!ttype)
+    return false;
+
+  /* Get the type attributes.  */
+  attrs = TYPE_ATTRIBUTES (ttype);
+  if (lookup_attribute ("uncached", attrs))
+    return true;
+  return false;
+}
+
 /* 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/config/arc/predicates.md b/gcc/config/arc/predicates.md
index 3dfe0ca..68887be 100644
--- a/gcc/config/arc/predicates.md
+++ b/gcc/config/arc/predicates.md
@@ -217,6 +217,10 @@ 
   if (MEM_VOLATILE_P (op) && !TARGET_VOLATILE_CACHE_SET)
      return 0;
 
+  /* likewise for uncached types.  */
+  if (arc_is_uncached_mem_p (op))
+     return 0;
+
   size = GET_MODE_SIZE (mode);
 
   /* dword operations really put out 2 instructions, so eliminate them.  */
@@ -412,7 +416,8 @@ 
 ;; and only the standard movXX patterns are set up to handle them.
 (define_predicate "nonvol_nonimm_operand"
   (and (match_code "subreg, reg, mem")
-       (match_test "(GET_CODE (op) != MEM || !MEM_VOLATILE_P (op)) && nonimmediate_operand (op, mode)"))
+       (match_test "(GET_CODE (op) != MEM || !MEM_VOLATILE_P (op)) && nonimmediate_operand (op, mode)")
+       (match_test "!arc_is_uncached_mem_p (op)"))
 )
 
 ;; Return 1 if OP is a comparison operator valid for the mode of CC.
diff --git a/gcc/testsuite/gcc.target/arc/uncached.c b/gcc/testsuite/gcc.target/arc/uncached.c
new file mode 100644
index 0000000..367e8dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/uncached.c
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+
+/* Check 'uncached' type attribute.  */
+
+typedef volatile unsigned int RwReg  __attribute__ ((uncached));
+
+typedef struct {
+  RwReg UART_THR;
+  int SIDE_DISH;
+} UART;
+
+void uart_putc(UART *port, char c)
+{
+    port->UART_THR = c;
+    port->SIDE_DISH = c;
+}
+
+/* { dg-final { scan-assembler-times "st\.di" 1 } } */