diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/config/arc/arc.c | 118 | ||||
-rw-r--r-- | gcc/config/arc/arc.md | 60 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arc/arc.exp | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arc/uncached-1.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arc/uncached-2.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arc/uncached-3.c | 22 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arc/uncached-4.c | 42 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arc/uncached-5.c | 29 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arc/uncached-6.c | 35 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arc/uncached-7.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arc/uncached-8.c | 33 |
13 files changed, 351 insertions, 42 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 91dfcd7..2cc61d6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index 22475f2..e1a865f 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -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)); + /* 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]); + emit_insn (gen_rtx_UNSPEC_VOLATILE + (VOIDmode, gen_rtvec (2, operands[1], tmp), + VUNSPEC_ARC_SR)); + return true; } - else + if (MEM_P (operands[1]) && arc_is_aux_reg_p (operands[1])) { - tmp = XEXP (operands[0], 0); + 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; } - - operands[1] = force_reg (SImode, operands[1]); + } + /* 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,24 +11184,40 @@ 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; - } - - /* For COMPONENT_REF, use the FIELD_DECL from tree operand 1. */ - if (TREE_CODE (addr) == COMPONENT_REF) - { attrs = TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr, 1))); if (lookup_attribute ("uncached", attrs)) return true; } + + /* Check the definitions of the structs. */ + while (handled_component_p (addr)) + { + 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; } diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md index cf7aa8d..46cb254 100644 --- a/gcc/config/arc/arc.md +++ b/gcc/config/arc/arc.md @@ -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)] diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 16ddef0..9919342 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/gcc.target/arc/arc.exp b/gcc/testsuite/gcc.target/arc/arc.exp index 8d1844e..501d458 100644 --- a/gcc/testsuite/gcc.target/arc/arc.exp +++ b/gcc/testsuite/gcc.target/arc/arc.exp @@ -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 { diff --git a/gcc/testsuite/gcc.target/arc/uncached-1.c b/gcc/testsuite/gcc.target/arc/uncached-1.c index 7a6bade..fa5ecb7 100644 --- a/gcc/testsuite/gcc.target/arc/uncached-1.c +++ b/gcc/testsuite/gcc.target/arc/uncached-1.c @@ -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 } } */ diff --git a/gcc/testsuite/gcc.target/arc/uncached-2.c b/gcc/testsuite/gcc.target/arc/uncached-2.c index 89eed32..9d6bfbb 100644 --- a/gcc/testsuite/gcc.target/arc/uncached-2.c +++ b/gcc/testsuite/gcc.target/arc/uncached-2.c @@ -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 } } */ diff --git a/gcc/testsuite/gcc.target/arc/uncached-3.c b/gcc/testsuite/gcc.target/arc/uncached-3.c new file mode 100644 index 0000000..f2a317b --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/uncached-3.c @@ -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 } } */ diff --git a/gcc/testsuite/gcc.target/arc/uncached-4.c b/gcc/testsuite/gcc.target/arc/uncached-4.c new file mode 100644 index 0000000..fecb166 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/uncached-4.c @@ -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 } } */ diff --git a/gcc/testsuite/gcc.target/arc/uncached-5.c b/gcc/testsuite/gcc.target/arc/uncached-5.c new file mode 100644 index 0000000..4fe0464 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/uncached-5.c @@ -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 } } } } } */ diff --git a/gcc/testsuite/gcc.target/arc/uncached-6.c b/gcc/testsuite/gcc.target/arc/uncached-6.c new file mode 100644 index 0000000..581a9ec --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/uncached-6.c @@ -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 } } } } } */ diff --git a/gcc/testsuite/gcc.target/arc/uncached-7.c b/gcc/testsuite/gcc.target/arc/uncached-7.c new file mode 100644 index 0000000..4001b8b --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/uncached-7.c @@ -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 } } */ diff --git a/gcc/testsuite/gcc.target/arc/uncached-8.c b/gcc/testsuite/gcc.target/arc/uncached-8.c new file mode 100644 index 0000000..060229b --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/uncached-8.c @@ -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 } } */ |