This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH 5/6] [ARC] Add 'uncached' attribute.
- From: Claudiu Zissulescu <Claudiu dot Zissulescu at synopsys dot com>
- To: <gcc-patches at gcc dot gnu dot org>
- Cc: <Claudiu dot Zissulescu at synopsys dot com>, <Francois dot Bedard at synopsys dot com>, <andrew dot burgess at embecosm dot com>
- Date: Thu, 2 Nov 2017 13:30:34 +0100
- Subject: [PATCH 5/6] [ARC] Add 'uncached' attribute.
- Authentication-results: sourceware.org; auth=none
- References: <1509625835-22344-1-git-send-email-claziss@synopsys.com>
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
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