Commit 8180c03f by Claudiu Zissulescu Committed by Claudiu Zissulescu

[ARC] Add 'uncached' attribute.

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

gcc/
2018-01-31  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/doc/extend.texi (ARC Type Attribute): New subsection.

gcc/testsuite
2018-01-31  Claudiu Zissulescu  <claziss@synopsys.com>

	* gcc.target/arc/uncached.c: New test.

From-SVN: r257222
parent 2f857e1b
2018-01-31 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/doc/extend.texi (ARC Type Attribute): New subsection.
2018-01-31 Jakub Jelinek <jakub@redhat.com> 2018-01-31 Jakub Jelinek <jakub@redhat.com>
PR c/84100 PR c/84100
......
...@@ -47,6 +47,7 @@ extern void arc_expand_compare_and_swap (rtx *); ...@@ -47,6 +47,7 @@ extern void arc_expand_compare_and_swap (rtx *);
extern bool compact_memory_operand_p (rtx, machine_mode, bool, bool); extern bool compact_memory_operand_p (rtx, machine_mode, bool, bool);
extern int arc_return_address_register (unsigned int); extern int arc_return_address_register (unsigned int);
extern unsigned int arc_compute_function_type (struct function *); extern unsigned int arc_compute_function_type (struct function *);
extern bool arc_is_uncached_mem_p (rtx);
#endif /* RTX_CODE */ #endif /* RTX_CODE */
extern unsigned int arc_compute_frame_size (int); extern unsigned int arc_compute_frame_size (int);
......
...@@ -227,7 +227,7 @@ static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *); ...@@ -227,7 +227,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_fndecl_attribute (tree *, tree, tree, int, bool *);
static tree arc_handle_jli_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_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 /* Initialized arc_attribute_table to NULL since arc doesnot have any
machine specific supported attributes. */ machine specific supported attributes. */
...@@ -253,13 +253,16 @@ const struct attribute_spec arc_attribute_table[] = ...@@ -253,13 +253,16 @@ const struct attribute_spec arc_attribute_table[] =
NULL }, NULL },
/* Functions calls made using jli instruction. The pointer in JLI /* Functions calls made using jli instruction. The pointer in JLI
table is found latter. */ table is found latter. */
{ "jli_always", 0, 0, false, true, true, NULL, NULL }, { "jli_always", 0, 0, false, true, true, false, NULL, NULL },
/* Functions calls made using jli instruction. The pointer in JLI /* Functions calls made using jli instruction. The pointer in JLI
table is given as input parameter. */ table is given as input parameter. */
{ "jli_fixed", 1, 1, false, true, true, arc_handle_jli_attribute, { "jli_fixed", 1, 1, false, true, true, false, arc_handle_jli_attribute,
NULL }, NULL },
/* Call a function using secure-mode. */ /* Call a function using secure-mode. */
{ "secure_call", 1, 1, false, true, true, arc_handle_secure_attribute, { "secure_call", 1, 1, false, true, true, false, arc_handle_secure_attribute,
NULL },
/* Bypass caches using .di flag. */
{ "uncached", 0, 0, false, true, false, false, arc_handle_uncached_attribute,
NULL }, NULL },
{ NULL, 0, 0, false, false, false, false, NULL, NULL } { NULL, 0, 0, false, false, false, false, NULL, NULL }
}; };
...@@ -4193,7 +4196,8 @@ arc_print_operand (FILE *file, rtx x, int code) ...@@ -4193,7 +4196,8 @@ arc_print_operand (FILE *file, rtx x, int code)
refs are defined to use the cache bypass mechanism. */ refs are defined to use the cache bypass mechanism. */
if (GET_CODE (x) == MEM) 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); fputs (".di", file);
} }
else else
...@@ -8102,6 +8106,7 @@ static bool ...@@ -8102,6 +8106,7 @@ static bool
arc_in_small_data_p (const_tree decl) arc_in_small_data_p (const_tree decl)
{ {
HOST_WIDE_INT size; HOST_WIDE_INT size;
tree attr;
/* Only variables are going into small data area. */ /* Only variables are going into small data area. */
if (TREE_CODE (decl) != VAR_DECL) if (TREE_CODE (decl) != VAR_DECL)
...@@ -8125,6 +8130,11 @@ arc_in_small_data_p (const_tree decl) ...@@ -8125,6 +8130,11 @@ arc_in_small_data_p (const_tree decl)
&& TREE_THIS_VOLATILE (decl)) && TREE_THIS_VOLATILE (decl))
return false; 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) if (DECL_SECTION_NAME (decl) != 0)
{ {
const char *name = DECL_SECTION_NAME (decl); const char *name = DECL_SECTION_NAME (decl);
...@@ -11130,6 +11140,57 @@ arc_is_secure_call_p (rtx pat) ...@@ -11130,6 +11140,57 @@ arc_is_secure_call_p (rtx pat)
return false; 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 /* 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 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, case. We also don't want to use them for PC-relative accesses,
......
...@@ -217,6 +217,10 @@ ...@@ -217,6 +217,10 @@
if (MEM_VOLATILE_P (op) && !TARGET_VOLATILE_CACHE_SET) if (MEM_VOLATILE_P (op) && !TARGET_VOLATILE_CACHE_SET)
return 0; return 0;
/* likewise for uncached types. */
if (arc_is_uncached_mem_p (op))
return 0;
size = GET_MODE_SIZE (mode); size = GET_MODE_SIZE (mode);
/* dword operations really put out 2 instructions, so eliminate them. */ /* dword operations really put out 2 instructions, so eliminate them. */
...@@ -412,7 +416,8 @@ ...@@ -412,7 +416,8 @@
;; and only the standard movXX patterns are set up to handle them. ;; and only the standard movXX patterns are set up to handle them.
(define_predicate "nonvol_nonimm_operand" (define_predicate "nonvol_nonimm_operand"
(and (match_code "subreg, reg, mem") (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. ;; Return 1 if OP is a comparison operator valid for the mode of CC.
......
...@@ -6817,6 +6817,7 @@ attributes. ...@@ -6817,6 +6817,7 @@ attributes.
@menu @menu
* Common Type Attributes:: * Common Type Attributes::
* ARC Type Attributes::
* ARM Type Attributes:: * ARM Type Attributes::
* MeP Type Attributes:: * MeP Type Attributes::
* PowerPC Type Attributes:: * PowerPC Type Attributes::
...@@ -7250,6 +7251,16 @@ To specify multiple attributes, separate them by commas within the ...@@ -7250,6 +7251,16 @@ To specify multiple attributes, separate them by commas within the
double parentheses: for example, @samp{__attribute__ ((aligned (16), double parentheses: for example, @samp{__attribute__ ((aligned (16),
packed))}. 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 @node ARM Type Attributes
@subsection ARM Type Attributes @subsection ARM Type Attributes
......
2018-01-31 Claudiu Zissulescu <claziss@synopsys.com>
* gcc.target/arc/uncached.c: New test.
2018-01-31 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> 2018-01-31 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
PR lto/83954 PR lto/83954
......
/* { 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 } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment