This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH 5/6] [ARC] Add 'uncached' attribute.
- From: Andrew Burgess <andrew dot burgess at embecosm dot com>
- To: Claudiu Zissulescu <Claudiu dot Zissulescu at synopsys dot com>
- Cc: gcc-patches at gcc dot gnu dot org, Francois dot Bedard at synopsys dot com
- Date: Mon, 29 Jan 2018 19:25:54 +0000
- Subject: Re: [PATCH 5/6] [ARC] Add 'uncached' attribute.
- Authentication-results: sourceware.org; auth=none
- References: <1509625835-22344-1-git-send-email-claziss@synopsys.com> <1509625835-22344-6-git-send-email-claziss@synopsys.com>
* 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
>