mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-08 20:52:05 +08:00
[ARC] Propagate uncached type attribute to each member of a struct.
Like `packed` type attribute, the ARC's `uncached` type attribute needs to be propagated to each member of the struct where it is used, triggering the .di flag for any access of the struct members. However, any complex CFG manipulation may drop memory pointer type attributes, leading to the impossibility to discriminate the direct accesses from normal ones. To solve this issue, we will treat the direct memory accessed specially via unspecs. gcc/ xxxx-xx-xx Claudiu Zissulescu <claziss@synopsys.com> Petro Karashchenko <petro.karashchenko@ring.com> * config/arc/arc.c (arc_is_uncached_mem_p): Check struct attributes if needed. (prepare_move_operands): Generate special unspec instruction for direct access. (arc_isuncached_mem_p): Propagate uncached attribute to each structure member. * config/arc/arc.md (VUNSPEC_ARC_LDDI): Define. (VUNSPEC_ARC_STDI): Likewise. (ALLI): New mode iterator. (mALLI): New mode attribute. (lddi): New instruction pattern. (stdi): Likewise. (stdidi_split): Split instruction for architectures which are not supporting ll64 option. (lddidi_split): Likewise. testsuite/ xxxx-xx-xx Claudiu Zissulescu <claziss@synopsys.com> Petro Karashchenko <petro.karashchenko@ring.com> * gcc.target/arc/uncached-1.c: Update test. * gcc.target/arc/uncached-2.c: Likewise. * gcc.target/arc/uncached-3.c: New test. * gcc.target/arc/uncached-4.c: Likewise. * gcc.target/arc/uncached-5.c: Likewise. * gcc.target/arc/uncached-6.c: Likewise. * gcc.target/arc/uncached-7.c: Likewise. * gcc.target/arc/uncached-8.c: Likewise. * gcc.target/arc/arc.exp (ll64): New predicate.
This commit is contained in:
parent
2744b8b286
commit
62a715c706
@ -1,3 +1,22 @@
|
||||
2020-01-27 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
Petro Karashchenko <petro.karashchenko@ring.com>
|
||||
|
||||
* config/arc/arc.c (arc_is_uncached_mem_p): Check struct
|
||||
attributes if needed.
|
||||
(prepare_move_operands): Generate special unspec instruction for
|
||||
direct access.
|
||||
(arc_isuncached_mem_p): Propagate uncached attribute to each
|
||||
structure member.
|
||||
* config/arc/arc.md (VUNSPEC_ARC_LDDI): Define.
|
||||
(VUNSPEC_ARC_STDI): Likewise.
|
||||
(ALLI): New mode iterator.
|
||||
(mALLI): New mode attribute.
|
||||
(lddi): New instruction pattern.
|
||||
(stdi): Likewise.
|
||||
(stdidi_split): Split instruction for architectures which are not
|
||||
supporting ll64 option.
|
||||
(lddidi_split): Likewise.
|
||||
|
||||
2020-01-27 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
PR rtl-optimization/92989
|
||||
|
@ -9091,49 +9091,71 @@ arc_get_aux_arg (rtx pat, int *auxr)
|
||||
bool
|
||||
prepare_move_operands (rtx *operands, machine_mode mode)
|
||||
{
|
||||
/* First handle aux attribute. */
|
||||
if (mode == SImode
|
||||
&& (MEM_P (operands[0]) || MEM_P (operands[1])))
|
||||
if ((MEM_P (operands[0]) || MEM_P (operands[1]))
|
||||
&& SCALAR_INT_MODE_P (mode))
|
||||
{
|
||||
rtx tmp;
|
||||
int auxr = 0;
|
||||
if (MEM_P (operands[0]) && arc_is_aux_reg_p (operands[0]))
|
||||
/* First handle aux attribute. */
|
||||
if (mode == SImode)
|
||||
{
|
||||
/* Save operation. */
|
||||
if (arc_get_aux_arg (operands[0], &auxr))
|
||||
rtx tmp;
|
||||
int auxr = 0;
|
||||
if (MEM_P (operands[0]) && arc_is_aux_reg_p (operands[0]))
|
||||
{
|
||||
tmp = gen_reg_rtx (SImode);
|
||||
emit_move_insn (tmp, GEN_INT (auxr));
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = XEXP (operands[0], 0);
|
||||
}
|
||||
/* Save operation. */
|
||||
if (arc_get_aux_arg (operands[0], &auxr))
|
||||
{
|
||||
tmp = gen_reg_rtx (SImode);
|
||||
emit_move_insn (tmp, GEN_INT (auxr));
|
||||
}
|
||||
else
|
||||
tmp = XEXP (operands[0], 0);
|
||||
|
||||
operands[1] = force_reg (SImode, operands[1]);
|
||||
operands[1] = force_reg (SImode, operands[1]);
|
||||
emit_insn (gen_rtx_UNSPEC_VOLATILE
|
||||
(VOIDmode, gen_rtvec (2, operands[1], tmp),
|
||||
VUNSPEC_ARC_SR));
|
||||
return true;
|
||||
}
|
||||
if (MEM_P (operands[1]) && arc_is_aux_reg_p (operands[1]))
|
||||
{
|
||||
if (arc_get_aux_arg (operands[1], &auxr))
|
||||
{
|
||||
tmp = gen_reg_rtx (SImode);
|
||||
emit_move_insn (tmp, GEN_INT (auxr));
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = XEXP (operands[1], 0);
|
||||
gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
|
||||
}
|
||||
/* Load operation. */
|
||||
gcc_assert (REG_P (operands[0]));
|
||||
emit_insn (gen_rtx_SET (operands[0],
|
||||
gen_rtx_UNSPEC_VOLATILE
|
||||
(SImode, gen_rtvec (1, tmp),
|
||||
VUNSPEC_ARC_LR)));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/* Second, we check for the uncached. */
|
||||
if (arc_is_uncached_mem_p (operands[0]))
|
||||
{
|
||||
if (!REG_P (operands[1]))
|
||||
operands[1] = force_reg (mode, operands[1]);
|
||||
emit_insn (gen_rtx_UNSPEC_VOLATILE
|
||||
(VOIDmode, gen_rtvec (2, operands[1], tmp),
|
||||
VUNSPEC_ARC_SR));
|
||||
(VOIDmode, gen_rtvec (2, operands[0], operands[1]),
|
||||
VUNSPEC_ARC_STDI));
|
||||
return true;
|
||||
}
|
||||
if (MEM_P (operands[1]) && arc_is_aux_reg_p (operands[1]))
|
||||
if (arc_is_uncached_mem_p (operands[1]))
|
||||
{
|
||||
if (arc_get_aux_arg (operands[1], &auxr))
|
||||
{
|
||||
tmp = gen_reg_rtx (SImode);
|
||||
emit_move_insn (tmp, GEN_INT (auxr));
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = XEXP (operands[1], 0);
|
||||
gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
|
||||
}
|
||||
/* Load operation. */
|
||||
gcc_assert (REG_P (operands[0]));
|
||||
emit_insn (gen_rtx_SET (operands[0],
|
||||
gen_rtx_UNSPEC_VOLATILE
|
||||
(SImode, gen_rtvec (1, tmp),
|
||||
VUNSPEC_ARC_LR)));
|
||||
if (MEM_P (operands[0]))
|
||||
operands[0] = force_reg (mode, operands[0]);
|
||||
emit_insn (gen_rtx_SET
|
||||
(operands[0],
|
||||
gen_rtx_UNSPEC_VOLATILE
|
||||
(mode, gen_rtvec (1, operands[1]),
|
||||
VUNSPEC_ARC_LDDI)));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -11162,23 +11184,39 @@ arc_is_uncached_mem_p (rtx pat)
|
||||
return false;
|
||||
|
||||
/* Get the attributes. */
|
||||
if (TREE_CODE (addr) == MEM_REF)
|
||||
if (TREE_CODE (addr) == MEM_REF
|
||||
|| TREE_CODE (addr) == VAR_DECL)
|
||||
{
|
||||
attrs = TYPE_ATTRIBUTES (TREE_TYPE (addr));
|
||||
if (lookup_attribute ("uncached", attrs))
|
||||
return true;
|
||||
|
||||
}
|
||||
if (TREE_CODE (addr) == MEM_REF)
|
||||
{
|
||||
attrs = TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr, 0)));
|
||||
if (lookup_attribute ("uncached", attrs))
|
||||
return true;
|
||||
attrs = TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr, 1)));
|
||||
if (lookup_attribute ("uncached", attrs))
|
||||
return true;
|
||||
}
|
||||
|
||||
/* For COMPONENT_REF, use the FIELD_DECL from tree operand 1. */
|
||||
if (TREE_CODE (addr) == COMPONENT_REF)
|
||||
/* Check the definitions of the structs. */
|
||||
while (handled_component_p (addr))
|
||||
{
|
||||
attrs = TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr, 1)));
|
||||
if (lookup_attribute ("uncached", attrs))
|
||||
return true;
|
||||
if (TREE_CODE (addr) == COMPONENT_REF)
|
||||
{
|
||||
attrs = TYPE_ATTRIBUTES (TREE_TYPE (addr));
|
||||
if (lookup_attribute ("uncached", attrs))
|
||||
return true;
|
||||
attrs = TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr, 0)));
|
||||
if (lookup_attribute ("uncached", attrs))
|
||||
return true;
|
||||
attrs = TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr, 1)));
|
||||
if (lookup_attribute ("uncached", attrs))
|
||||
return true;
|
||||
}
|
||||
addr = TREE_OPERAND (addr, 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -164,6 +164,8 @@
|
||||
VUNSPEC_ARC_BLOCKAGE
|
||||
VUNSPEC_ARC_EH_RETURN
|
||||
VUNSPEC_ARC_ARC600_RTIE
|
||||
VUNSPEC_ARC_LDDI
|
||||
VUNSPEC_ARC_STDI
|
||||
])
|
||||
|
||||
(define_constants
|
||||
@ -4682,6 +4684,64 @@ core_3, archs4x, archs4xd, archs4xd_slow"
|
||||
[(set_attr "length" "8,4,8,4")
|
||||
(set_attr "type" "sr,sr,sr,sr")])
|
||||
|
||||
(define_mode_iterator ALLI [QI HI SI (DI "TARGET_LL64")])
|
||||
(define_mode_attr mALLI [(QI "b") (HI "%_") (SI "") (DI "d")])
|
||||
|
||||
(define_insn "lddi<mode>"
|
||||
[(set (match_operand:ALLI 0 "register_operand" "=r")
|
||||
(unspec_volatile:ALLI [(match_operand:ALLI 1 "memory_operand" "m")]
|
||||
VUNSPEC_ARC_LDDI))]
|
||||
""
|
||||
"ld<mALLI>%U1.di\\t%0,%1"
|
||||
[(set_attr "type" "load")])
|
||||
|
||||
(define_insn "stdi<mode>"
|
||||
[(unspec_volatile [(match_operand:ALLI 0 "memory_operand" "m,m,Usc")
|
||||
(match_operand:ALLI 1 "nonmemory_operand" "r,Cm3,i")]
|
||||
VUNSPEC_ARC_STDI)]
|
||||
""
|
||||
"st<mALLI>%U0.di\\t%1,%0"
|
||||
[(set_attr "length" "*,*,8")
|
||||
(set_attr "type" "store")])
|
||||
|
||||
(define_insn_and_split "*stdidi_split"
|
||||
[(unspec_volatile [(match_operand:DI 0 "memory_operand" "m")
|
||||
(match_operand:DI 1 "register_operand" "r")]
|
||||
VUNSPEC_ARC_STDI)]
|
||||
"!TARGET_LL64"
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(unspec_volatile:SI [(match_dup 2) (match_dup 3)] VUNSPEC_ARC_STDI)
|
||||
(unspec_volatile:SI [(match_dup 4) (match_dup 5)] VUNSPEC_ARC_STDI)]
|
||||
"
|
||||
{
|
||||
operands[3] = gen_lowpart (SImode, operands[1]);
|
||||
operands[5] = gen_highpart_mode (SImode, DImode, operands[1]);
|
||||
operands[2] = gen_lowpart (SImode, operands[0]);
|
||||
operands[4] = gen_highpart (SImode, operands[0]);
|
||||
}
|
||||
"
|
||||
)
|
||||
|
||||
(define_insn_and_split "*lddidi_split"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(unspec_volatile:DI [(match_operand:DI 1 "memory_operand" "m")]
|
||||
VUNSPEC_ARC_LDDI))]
|
||||
"!TARGET_LL64"
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(set (match_dup 2) (unspec_volatile:SI [(match_dup 3)] VUNSPEC_ARC_LDDI))
|
||||
(set (match_dup 4) (unspec_volatile:SI [(match_dup 5)] VUNSPEC_ARC_LDDI))]
|
||||
"
|
||||
{
|
||||
operands[3] = gen_lowpart (SImode, operands[1]);
|
||||
operands[5] = gen_highpart (SImode, operands[1]);
|
||||
operands[2] = gen_lowpart (SImode, operands[0]);
|
||||
operands[4] = gen_highpart (SImode, operands[0]);
|
||||
}
|
||||
"
|
||||
)
|
||||
|
||||
(define_insn "trap_s"
|
||||
[(unspec_volatile [(match_operand:SI 0 "immediate_operand" "L,Cal")]
|
||||
VUNSPEC_ARC_TRAP_S)]
|
||||
|
@ -1,3 +1,14 @@
|
||||
2020-01-27 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
Petro Karashchenko <petro.karashchenko@ring.com>
|
||||
|
||||
* gcc.target/arc/uncached-3.c: New test.
|
||||
* gcc.target/arc/uncached-4.c: Likewise.
|
||||
* gcc.target/arc/uncached-5.c: Likewise.
|
||||
* gcc.target/arc/uncached-6.c: Likewise.
|
||||
* gcc.target/arc/uncached-7.c: Likewise.
|
||||
* gcc.target/arc/uncached-8.c: Likewise.
|
||||
* gcc.target/arc/arc.exp (ll64): New predicate.
|
||||
|
||||
2020-01-27 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
* gcc.dg/torture/pr93170.c: New test.
|
||||
|
@ -122,6 +122,15 @@ proc check_effective_target_dpfp { } {
|
||||
}]
|
||||
}
|
||||
|
||||
# Return 1 if this is a compiler supporting LL64 option.
|
||||
proc check_effective_target_ll64 { } {
|
||||
return [check_no_compiler_messages ll64 assembly {
|
||||
#if !defined(__ARC_LL64__)
|
||||
#error No ARC LL64
|
||||
#endif
|
||||
}]
|
||||
}
|
||||
|
||||
# If a testcase doesn't have special options, use these.
|
||||
global DEFAULT_CFLAGS
|
||||
if ![info exists DEFAULT_CFLAGS] then {
|
||||
|
@ -8,4 +8,4 @@ int get_stat (void)
|
||||
return *status;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-times "ld\.di" 1 } } */
|
||||
/* { dg-final { scan-assembler-times "ld\.di" 2 } } */
|
||||
|
@ -6,4 +6,4 @@ void clkgen_switch(unsigned int base, unsigned int offset, int val)
|
||||
(volatile unsigned int __attribute__ ((uncached)) *) (base + offset);
|
||||
*dest = val;
|
||||
}
|
||||
/* { dg-final { scan-assembler-times "st\.di" 1 } } */
|
||||
/* { dg-final { scan-assembler-times "st\.di" 2 } } */
|
||||
|
22
gcc/testsuite/gcc.target/arc/uncached-3.c
Normal file
22
gcc/testsuite/gcc.target/arc/uncached-3.c
Normal file
@ -0,0 +1,22 @@
|
||||
/* { dg-do compile } */
|
||||
|
||||
typedef volatile struct {
|
||||
int a;
|
||||
char *b;
|
||||
} __attribute__((uncached)) my_type_t;
|
||||
|
||||
my_type_t x;
|
||||
|
||||
void foo (my_type_t *p)
|
||||
{
|
||||
p->a = 10;
|
||||
p->b = 0;
|
||||
}
|
||||
|
||||
void bar (void)
|
||||
{
|
||||
x.a = 10;
|
||||
x.b = 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-times "st\.di" 4 } } */
|
42
gcc/testsuite/gcc.target/arc/uncached-4.c
Normal file
42
gcc/testsuite/gcc.target/arc/uncached-4.c
Normal file
@ -0,0 +1,42 @@
|
||||
/* { dg-do compile } */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
e1,
|
||||
e2
|
||||
} my_enum_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int a;
|
||||
int *p;
|
||||
} my_struct_t;
|
||||
|
||||
typedef volatile struct
|
||||
{
|
||||
my_enum_t a;
|
||||
my_struct_t b;
|
||||
} __attribute__((uncached)) my_type_t;
|
||||
|
||||
my_type_t x;
|
||||
|
||||
void foo (my_type_t *p)
|
||||
{
|
||||
p->a = e2;
|
||||
p->b.a = 10;
|
||||
p->b.p = NULL;
|
||||
*p->b.p = 10;
|
||||
}
|
||||
|
||||
void bar (void)
|
||||
{
|
||||
x.a = e2;
|
||||
x.b.a = 10;
|
||||
x.b.p = NULL;
|
||||
*x.b.p = 10;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-times "st\.di" 6 } } */
|
||||
/* { dg-final { scan-assembler-times "ld\.di" 2 } } */
|
29
gcc/testsuite/gcc.target/arc/uncached-5.c
Normal file
29
gcc/testsuite/gcc.target/arc/uncached-5.c
Normal file
@ -0,0 +1,29 @@
|
||||
/* { dg-options "-O1" } */
|
||||
/* { dg-do compile } */
|
||||
|
||||
#define RegWrSI(a,v) (*(volatile __attribute__((uncached)) int *)(a)=(v))
|
||||
#define RegWrQI(a,v) (*(volatile __attribute__((uncached)) char *)(a)=(v))
|
||||
#define RegWrHI(a,v) (*(volatile __attribute__((uncached)) short *)(a)=(v))
|
||||
#define RegWrDI(a,v) (*(volatile __attribute__((uncached)) long long *)(a)=(v))
|
||||
|
||||
void foo (int arg, void *p)
|
||||
{
|
||||
RegWrDI (p , arg);
|
||||
RegWrHI (p++, arg);
|
||||
RegWrSI (p++, arg);
|
||||
RegWrQI (p++, arg);
|
||||
}
|
||||
|
||||
void bar (void)
|
||||
{
|
||||
RegWrQI (0x40000, 1);
|
||||
RegWrHI (0x40010, 2);
|
||||
RegWrSI (0x40020, 4);
|
||||
RegWrDI (0x40040, 8);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-times "stb\.di" 2 } } */
|
||||
/* { dg-final { scan-assembler-times "st\[hw\]\.di" 2 } } */
|
||||
/* { dg-final { scan-assembler-times "std\.di" 2 { target { ll64 } } } } */
|
||||
/* { dg-final { scan-assembler-times "st\.di" 2 { target { ll64 } } } } */
|
||||
/* { dg-final { scan-assembler-times "st\.di" 6 { target { ! { ll64 } } } } } */
|
35
gcc/testsuite/gcc.target/arc/uncached-6.c
Normal file
35
gcc/testsuite/gcc.target/arc/uncached-6.c
Normal file
@ -0,0 +1,35 @@
|
||||
/* { dg-options "-O1" } */
|
||||
/* { dg-do compile } */
|
||||
|
||||
#define RegRdSI(v,a) ((v) = *(volatile __attribute__((uncached)) int *)(a))
|
||||
#define RegRdQI(v,a) ((v) = *(volatile __attribute__((uncached)) char *)(a))
|
||||
#define RegRdHI(v,a) ((v) = *(volatile __attribute__((uncached)) short *)(a))
|
||||
#define RegRdDI(v,a) \
|
||||
((v) = *(volatile __attribute__((uncached)) long long *)(a))
|
||||
|
||||
char a0;
|
||||
short a1;
|
||||
int a2;
|
||||
long long a3;
|
||||
|
||||
void foox (void *p)
|
||||
{
|
||||
RegRdQI (a0, p++);
|
||||
RegRdHI (a1, p++);
|
||||
RegRdSI (a2, p++);
|
||||
RegRdDI (a3, p );
|
||||
}
|
||||
|
||||
void barx (int arg)
|
||||
{
|
||||
RegRdQI (a0, 0x40000);
|
||||
RegRdHI (a1, 0x40010);
|
||||
RegRdSI (a2, 0x40020);
|
||||
RegRdDI (a3, 0x40040);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-times "ldb\.di" 2 } } */
|
||||
/* { dg-final { scan-assembler-times "ld\[hw\]\.di" 2 } } */
|
||||
/* { dg-final { scan-assembler-times "ldd\.di" 2 { target { ll64 } } } } */
|
||||
/* { dg-final { scan-assembler-times "ld\.di" 2 { target { ll64 } } } } */
|
||||
/* { dg-final { scan-assembler-times "ld\.di" 6 { target { ! { ll64 } } } } } */
|
11
gcc/testsuite/gcc.target/arc/uncached-7.c
Normal file
11
gcc/testsuite/gcc.target/arc/uncached-7.c
Normal file
@ -0,0 +1,11 @@
|
||||
/* { dg-options "-O1" } */
|
||||
/* { dg-do compile } */
|
||||
|
||||
volatile __attribute__((uncached)) int s[20];
|
||||
|
||||
void s_acc(void)
|
||||
{
|
||||
s[10] = 15;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-times "st\.di" 1 } } */
|
33
gcc/testsuite/gcc.target/arc/uncached-8.c
Normal file
33
gcc/testsuite/gcc.target/arc/uncached-8.c
Normal file
@ -0,0 +1,33 @@
|
||||
/* { dg-do compile } */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int a;
|
||||
} my_structB_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
my_structB_t b;
|
||||
} __attribute__((uncached)) my_structA_t;
|
||||
|
||||
typedef volatile struct
|
||||
{
|
||||
my_structA_t c;
|
||||
} my_type_t;
|
||||
|
||||
my_type_t x;
|
||||
|
||||
void foo (my_type_t *p)
|
||||
{
|
||||
p->c.b.a = 10;
|
||||
}
|
||||
|
||||
void bar (void)
|
||||
{
|
||||
x.c.b.a = 10;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-times "st\.di" 1 } } */
|
||||
/* { dg-final { scan-assembler-times "st\.as\.di" 1 } } */
|
Loading…
x
Reference in New Issue
Block a user