* Claudiu Zissulescu <claudiu.zissule...@synopsys.com> [2017-11-02 13:30:34 +0100]:
> From: claziss <claz...@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 <claz...@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 <claz...@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 >