summaryrefslogtreecommitdiff
path: root/gcc/config/arc
diff options
context:
space:
mode:
authorClaudiu Zissulescu <claziss@gmail.com>2020-01-27 14:51:03 +0200
committerClaudiu Zissulescu <claziss@gmail.com>2020-01-27 14:51:03 +0200
commit62a715c706d8482560dadfa9ead0766f3c20e434 (patch)
tree3baedb4dc834dcf675bd8f39c44eba8b6b4254fc /gcc/config/arc
parent2744b8b286cbdeecbb6ab03e015dc847a2fb42a2 (diff)
[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.
Diffstat (limited to 'gcc/config/arc')
-rw-r--r--gcc/config/arc/arc.c118
-rw-r--r--gcc/config/arc/arc.md60
2 files changed, 138 insertions, 40 deletions
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index 22475f2732e..e1a865f02e6 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 cf7aa8d83c9..46cb254ed28 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)]