Commit 673f01b8 by Claudiu Zissulescu Committed by Claudiu Zissulescu

[ARC] Fix for PR89838

gcc/
xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>

	* config/arc/arc.c (arc_symbol_binds_local_p): New function.
	(arc_legitimize_pic_address): Simplify and cleanup the function.
	(SYMBOLIC_CONST): Remove.
	(prepare_pic_move): Likewise.
	(prepare_move_operands): Handle complex mov cases here.
	(arc_legitimize_address_0): Remove call to
	arc_legitimize_pic_address.
	(arc_legitimize_address): Remove call to
	arc_legitimize_tls_address.
	* config/arc/arc.md (movqi_insn): Allow Cm3 match.
	(movhi_insn): Likewise.

/gcc/testsuite
xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>

	* gcc.target/arc/pr89838.c: New file.

From-SVN: r272643
parent 5e580306
2019-06-25 Claudiu Zissulescu <claziss@synopsys.com>
* config/arc/arc.c (arc_symbol_binds_local_p): New function.
(arc_legitimize_pic_address): Simplify and cleanup the function.
(SYMBOLIC_CONST): Remove.
(prepare_pic_move): Likewise.
(prepare_move_operands): Handle complex mov cases here.
(arc_legitimize_address_0): Remove call to
arc_legitimize_pic_address.
(arc_legitimize_address): Remove call to
arc_legitimize_tls_address.
* config/arc/arc.md (movqi_insn): Allow Cm3 match.
(movhi_insn): Likewise.
2019-06-25 Jozef Lawrynowicz <jozef.l@mittosystems.com> 2019-06-25 Jozef Lawrynowicz <jozef.l@mittosystems.com>
* gcc/c-family/c-common.c (c_common_nodes_and_builtins): Define * gcc/c-family/c-common.c (c_common_nodes_and_builtins): Define
......
...@@ -5975,130 +5975,47 @@ arc_legitimize_tls_address (rtx addr, enum tls_model model) ...@@ -5975,130 +5975,47 @@ arc_legitimize_tls_address (rtx addr, enum tls_model model)
} }
} }
/* Legitimize a pic address reference in ORIG. /* Return true if SYMBOL_REF X binds locally. */
The return value is the legitimated address.
If OLDX is non-zero, it is the target to assign the address to first. */
static rtx static bool
arc_legitimize_pic_address (rtx orig, rtx oldx) arc_symbol_binds_local_p (const_rtx x)
{ {
rtx addr = orig; return (SYMBOL_REF_DECL (x)
rtx pat = orig; ? targetm.binds_local_p (SYMBOL_REF_DECL (x))
rtx base; : SYMBOL_REF_LOCAL_P (x));
}
/* Legitimize a pic address reference in ADDR. The return value is
the legitimated address. */
if (oldx == orig) static rtx
oldx = NULL; arc_legitimize_pic_address (rtx addr)
{
if (!flag_pic)
return addr;
if (GET_CODE (addr) == LABEL_REF) switch (GET_CODE (addr))
; /* Do nothing. */
else if (GET_CODE (addr) == SYMBOL_REF)
{ {
enum tls_model model = SYMBOL_REF_TLS_MODEL (addr); case SYMBOL_REF:
if (model != 0) /* TLS symbols are handled in different place. */
return arc_legitimize_tls_address (addr, model); if (SYMBOL_REF_TLS_MODEL (addr))
else if (!flag_pic) return addr;
return orig;
else if (CONSTANT_POOL_ADDRESS_P (addr) || SYMBOL_REF_LOCAL_P (addr))
return arc_unspec_offset (addr, ARC_UNSPEC_GOTOFFPC);
/* This symbol must be referenced via a load from the Global /* This symbol must be referenced via a load from the Global
Offset Table (@GOTPC). */ Offset Table (@GOTPC). */
pat = arc_unspec_offset (addr, ARC_UNSPEC_GOT); if (!arc_symbol_binds_local_p (addr))
pat = gen_const_mem (Pmode, pat); return gen_const_mem (Pmode, arc_unspec_offset (addr, ARC_UNSPEC_GOT));
if (oldx == NULL)
oldx = gen_reg_rtx (Pmode);
emit_move_insn (oldx, pat);
pat = oldx;
}
else
{
if (GET_CODE (addr) == CONST)
{
addr = XEXP (addr, 0);
if (GET_CODE (addr) == UNSPEC)
{
/* Check that the unspec is one of the ones we generate? */
return orig;
}
/* fwprop is placing in the REG_EQUIV notes constant pic
unspecs expressions. Then, loop may use these notes for
optimizations resulting in complex patterns that are not
supported by the current implementation. The following
two if-cases are simplifying the complex patters to
simpler ones. */
else if (GET_CODE (addr) == MINUS)
{
rtx op0 = XEXP (addr, 0);
rtx op1 = XEXP (addr, 1);
gcc_assert (oldx);
gcc_assert (GET_CODE (op1) == UNSPEC);
emit_move_insn (oldx,
gen_rtx_CONST (SImode,
arc_legitimize_pic_address (op1,
NULL_RTX)));
emit_insn (gen_rtx_SET (oldx, gen_rtx_MINUS (SImode, op0, oldx)));
return oldx;
}
else if (GET_CODE (addr) != PLUS)
{
rtx tmp = XEXP (addr, 0);
enum rtx_code code = GET_CODE (addr);
/* It only works for UNARY operations. */
gcc_assert (UNARY_P (addr));
gcc_assert (GET_CODE (tmp) == UNSPEC);
gcc_assert (oldx);
emit_move_insn
(oldx,
gen_rtx_CONST (SImode,
arc_legitimize_pic_address (tmp,
NULL_RTX)));
emit_insn (gen_rtx_SET (oldx,
gen_rtx_fmt_ee (code, SImode,
oldx, const0_rtx)));
return oldx;
}
else
{
gcc_assert (GET_CODE (addr) == PLUS);
if (GET_CODE (XEXP (addr, 0)) == UNSPEC)
return orig;
}
}
if (GET_CODE (addr) == PLUS)
{
rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);
base = arc_legitimize_pic_address (op0, oldx);
pat = arc_legitimize_pic_address (op1,
base == oldx ? NULL_RTX : oldx);
if (base == op0 && pat == op1) /* Local symb: use @pcl to access it. */
return orig; /* Fall through. */
case LABEL_REF:
return arc_unspec_offset (addr, ARC_UNSPEC_GOTOFFPC);
if (GET_CODE (pat) == CONST_INT) default:
pat = plus_constant (Pmode, base, INTVAL (pat)); break;
else
{
if (GET_CODE (pat) == PLUS && CONSTANT_P (XEXP (pat, 1)))
{
base = gen_rtx_PLUS (Pmode, base, XEXP (pat, 0));
pat = XEXP (pat, 1);
}
pat = gen_rtx_PLUS (Pmode, base, pat);
}
}
} }
return pat; return addr;
} }
/* Output address constant X to FILE, taking PIC into account. */ /* Output address constant X to FILE, taking PIC into account. */
...@@ -6260,28 +6177,6 @@ arc_output_pic_addr_const (FILE * file, rtx x, int code) ...@@ -6260,28 +6177,6 @@ arc_output_pic_addr_const (FILE * file, rtx x, int code)
} }
} }
#define SYMBOLIC_CONST(X) \
(GET_CODE (X) == SYMBOL_REF \
|| GET_CODE (X) == LABEL_REF \
|| (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
/* Emit insns to move operands[1] into operands[0]. */
static void
prepare_pic_move (rtx *operands, machine_mode)
{
if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1])
&& flag_pic)
operands[1] = force_reg (Pmode, operands[1]);
else
{
rtx temp = (reload_in_progress ? operands[0]
: flag_pic? gen_reg_rtx (Pmode) : NULL_RTX);
operands[1] = arc_legitimize_pic_address (operands[1], temp);
}
}
/* The function returning the number of words, at the beginning of an /* The function returning the number of words, at the beginning of an
argument, must be put in registers. The returned value must be argument, must be put in registers. The returned value must be
zero for arguments that are passed entirely in registers or that zero for arguments that are passed entirely in registers or that
...@@ -9061,30 +8956,38 @@ prepare_move_operands (rtx *operands, machine_mode mode) ...@@ -9061,30 +8956,38 @@ prepare_move_operands (rtx *operands, machine_mode mode)
} }
} }
if (mode == SImode && SYMBOLIC_CONST (operands[1])) if (GET_CODE (operands[1]) == SYMBOL_REF)
{ {
prepare_pic_move (operands, SImode); enum tls_model model = SYMBOL_REF_TLS_MODEL (operands[1]);
if (MEM_P (operands[0]) && flag_pic)
/* Disable any REG_EQUALs associated with the symref operands[1] = force_reg (mode, operands[1]);
otherwise the optimization pass undoes the work done else if (model)
here and references the variable directly. */ operands[1] = arc_legitimize_tls_address (operands[1], model);
} }
operands[1] = arc_legitimize_pic_address (operands[1]);
/* Store instructions are limited, they only accept as address an
immediate, a register or a register plus a small immediate. */
if (MEM_P (operands[0]) if (MEM_P (operands[0])
&& !(reload_in_progress || reload_completed)) && !move_dest_operand (operands[0], mode))
{ {
operands[1] = force_reg (mode, operands[1]); rtx tmp0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
if (!move_dest_operand (operands[0], mode)) rtx tmp1 = change_address (operands[0], mode, tmp0);
{ MEM_COPY_ATTRIBUTES (tmp1, operands[0]);
rtx addr = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); operands[0] = tmp1;
/* This is like change_address_1 (operands[0], mode, 0, 1) ,
except that we can't use that function because it is static. */
rtx pat = change_address (operands[0], mode, addr);
MEM_COPY_ATTRIBUTES (pat, operands[0]);
operands[0] = pat;
}
} }
/* Check if it is constant but it is not legitimized. */
if (CONSTANT_P (operands[1])
&& !arc_legitimate_constant_p (mode, operands[1]))
operands[1] = force_reg (mode, XEXP (operands[1], 0));
else if (MEM_P (operands[0])
&& ((CONSTANT_P (operands[1])
&& !satisfies_constraint_Cm3 (operands[1]))
|| MEM_P (operands[1])))
operands[1] = force_reg (mode, operands[1]);
return false; return false;
} }
...@@ -9555,11 +9458,10 @@ arc_legitimize_address_0 (rtx x, rtx oldx ATTRIBUTE_UNUSED, ...@@ -9555,11 +9458,10 @@ arc_legitimize_address_0 (rtx x, rtx oldx ATTRIBUTE_UNUSED,
{ {
rtx addr, inner; rtx addr, inner;
if (flag_pic && SYMBOLIC_CONST (x))
(x) = arc_legitimize_pic_address (x, 0);
addr = x; addr = x;
if (GET_CODE (addr) == CONST) if (GET_CODE (addr) == CONST)
addr = XEXP (addr, 0); addr = XEXP (addr, 0);
if (GET_CODE (addr) == PLUS if (GET_CODE (addr) == PLUS
&& CONST_INT_P (XEXP (addr, 1)) && CONST_INT_P (XEXP (addr, 1))
&& ((GET_CODE (XEXP (addr, 0)) == SYMBOL_REF && ((GET_CODE (XEXP (addr, 0)) == SYMBOL_REF
...@@ -9590,13 +9492,6 @@ arc_legitimize_address_0 (rtx x, rtx oldx ATTRIBUTE_UNUSED, ...@@ -9590,13 +9492,6 @@ arc_legitimize_address_0 (rtx x, rtx oldx ATTRIBUTE_UNUSED,
static rtx static rtx
arc_legitimize_address (rtx orig_x, rtx oldx, machine_mode mode) arc_legitimize_address (rtx orig_x, rtx oldx, machine_mode mode)
{ {
if (GET_CODE (orig_x) == SYMBOL_REF)
{
enum tls_model model = SYMBOL_REF_TLS_MODEL (orig_x);
if (model != 0)
return arc_legitimize_tls_address (orig_x, model);
}
rtx new_x = arc_legitimize_address_0 (orig_x, oldx, mode); rtx new_x = arc_legitimize_address_0 (orig_x, oldx, mode);
if (new_x) if (new_x)
......
...@@ -671,7 +671,9 @@ core_3, archs4x, archs4xd, archs4xd_slow" ...@@ -671,7 +671,9 @@ core_3, archs4x, archs4xd, archs4xd_slow"
[(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q, w,Rcq#q, h, w, w,???w,h, w,Rcq, S,!*x, r,r, Ucm,m,???m, m,Usc") [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q, w,Rcq#q, h, w, w,???w,h, w,Rcq, S,!*x, r,r, Ucm,m,???m, m,Usc")
(match_operand:QI 1 "move_src_operand" " cL, cP,Rcq#q, P,hCm1,cL, I,?Rac,i,?i, T,Rcq,Usd,Ucm,m,?Rac,c,?Rac,Cm3,i"))] (match_operand:QI 1 "move_src_operand" " cL, cP,Rcq#q, P,hCm1,cL, I,?Rac,i,?i, T,Rcq,Usd,Ucm,m,?Rac,c,?Rac,Cm3,i"))]
"register_operand (operands[0], QImode) "register_operand (operands[0], QImode)
|| register_operand (operands[1], QImode)" || register_operand (operands[1], QImode)
|| (satisfies_constraint_Cm3 (operands[1])
&& memory_operand (operands[0], QImode))"
"@ "@
mov%? %0,%1%& mov%? %0,%1%&
mov%? %0,%1%& mov%? %0,%1%&
...@@ -713,7 +715,9 @@ core_3, archs4x, archs4xd, archs4xd_slow" ...@@ -713,7 +715,9 @@ core_3, archs4x, archs4xd, archs4xd_slow"
/* Don't use a LIMM that we could load with a single insn - we loose /* Don't use a LIMM that we could load with a single insn - we loose
delay-slot filling opportunities. */ delay-slot filling opportunities. */
&& !satisfies_constraint_I (operands[1]) && !satisfies_constraint_I (operands[1])
&& satisfies_constraint_Usc (operands[0]))" && satisfies_constraint_Usc (operands[0]))
|| (satisfies_constraint_Cm3 (operands[1])
&& memory_operand (operands[0], HImode))"
"@ "@
mov%? %0,%1%& mov%? %0,%1%&
mov%? %0,%1%& mov%? %0,%1%&
......
2019-06-25 Claudiu Zissulescu <claziss@synopsys.com>
* gcc.target/arc/pr89838.c: New file.
2019-06-25 Jozef Lawrynowicz <jozef.l@mittosystems.com> 2019-06-25 Jozef Lawrynowicz <jozef.l@mittosystems.com>
* gcc.target/msp430/mlarge-pedwarns.c: New test. * gcc.target/msp430/mlarge-pedwarns.c: New test.
......
/* { dg-do compile } */
/* { dg-require-effective-target tls } */
/* { dg-options "-O2" } */
extern void foo (void);
extern void bar (void *);
struct {
int __attribute__(()) a;
int __attribute__(()) b;
} __thread c __attribute__((tls_model("initial-exec")));
void foo (void)
{
bar (&c.b);
}
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