[PATCH] [ARC] Fix PR89838
Andrew Burgess
andrew.burgess@embecosm.com
Sun Jun 23 19:03:00 GMT 2019
* Claudiu Zissulescu <claziss@gmail.com> [2019-06-06 10:32:11 +0300]:
> Hi Andrew,
>
> This is a proposed fix for bugzilla PR89838 issue. It also needs to be backported to gcc9 and, eventually, gcc8 branches.
>
> Ok to apply?
> Claudiu
I had a look through the patch and found just one small nit detailed
below. Otherwise this looks fine.
Thanks,
Andrew
>
> 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.
> ---
> gcc/config/arc/arc.c | 215 +++++++------------------
> gcc/config/arc/arc.md | 8 +-
> gcc/testsuite/gcc.target/arc/pr89838.c | 16 ++
> 3 files changed, 77 insertions(+), 162 deletions(-)
> create mode 100644 gcc/testsuite/gcc.target/arc/pr89838.c
>
> diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
> index 20dfae66370..a5ee5c49a8f 100644
> --- a/gcc/config/arc/arc.c
> +++ b/gcc/config/arc/arc.c
> @@ -5986,130 +5986,47 @@ arc_legitimize_tls_address (rtx addr, enum tls_model model)
> }
> }
>
> -/* Legitimize a pic address reference in ORIG.
> - The return value is the legitimated address.
> - If OLDX is non-zero, it is the target to assign the address to first. */
> +/* Return true if SYMBOL_REF X binds locally. */
>
> -static rtx
> -arc_legitimize_pic_address (rtx orig, rtx oldx)
> +static bool
> +arc_symbol_binds_local_p (const_rtx x)
> {
> - rtx addr = orig;
> - rtx pat = orig;
> - rtx base;
> + return (SYMBOL_REF_DECL (x)
> + ? targetm.binds_local_p (SYMBOL_REF_DECL (x))
> + : SYMBOL_REF_LOCAL_P (x));
> +}
> +
> +/* Legitimize a pic address reference in ORIG. The return value is
> + the legitimated address. */
This comment needs updating I think, it references ORIG, but there is
no ORIG in arc_legitimize_pic.
>
> - if (oldx == orig)
> - oldx = NULL;
> +static rtx
> +arc_legitimize_pic_address (rtx addr)
> +{
> + if (!flag_pic)
> + return addr;
>
> - if (GET_CODE (addr) == LABEL_REF)
> - ; /* Do nothing. */
> - else if (GET_CODE (addr) == SYMBOL_REF)
> + switch (GET_CODE (addr))
> {
> - enum tls_model model = SYMBOL_REF_TLS_MODEL (addr);
> - if (model != 0)
> - return arc_legitimize_tls_address (addr, model);
> - else if (!flag_pic)
> - return orig;
> - else if (CONSTANT_POOL_ADDRESS_P (addr) || SYMBOL_REF_LOCAL_P (addr))
> - return arc_unspec_offset (addr, ARC_UNSPEC_GOTOFFPC);
> + case SYMBOL_REF:
> + /* TLS symbols are handled in different place. */
> + if (SYMBOL_REF_TLS_MODEL (addr))
> + return addr;
>
> /* This symbol must be referenced via a load from the Global
> Offset Table (@GOTPC). */
> - pat = arc_unspec_offset (addr, ARC_UNSPEC_GOT);
> - pat = gen_const_mem (Pmode, pat);
> -
> - 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 (!arc_symbol_binds_local_p (addr))
> + return gen_const_mem (Pmode, arc_unspec_offset (addr, ARC_UNSPEC_GOT));
>
> - if (base == op0 && pat == op1)
> - return orig;
> + /* Local symb: use @pcl to access it. */
> + /* Fall through. */
> + case LABEL_REF:
> + return arc_unspec_offset (addr, ARC_UNSPEC_GOTOFFPC);
>
> - if (GET_CODE (pat) == CONST_INT)
> - pat = plus_constant (Pmode, base, INTVAL (pat));
> - 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);
> - }
> - }
> + default:
> + break;
> }
>
> - return pat;
> + return addr;
> }
>
> /* Output address constant X to FILE, taking PIC into account. */
> @@ -6271,28 +6188,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
> argument, must be put in registers. The returned value must be
> zero for arguments that are passed entirely in registers or that
> @@ -9072,30 +8967,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);
> -
> - /* Disable any REG_EQUALs associated with the symref
> - otherwise the optimization pass undoes the work done
> - here and references the variable directly. */
> + enum tls_model model = SYMBOL_REF_TLS_MODEL (operands[1]);
> + if (MEM_P (operands[0]) && flag_pic)
> + operands[1] = force_reg (mode, operands[1]);
> + else if (model)
> + 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])
> - && !(reload_in_progress || reload_completed))
> + && !move_dest_operand (operands[0], mode))
> {
> - operands[1] = force_reg (mode, operands[1]);
> - if (!move_dest_operand (operands[0], mode))
> - {
> - rtx addr = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
> - /* 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;
> - }
> + rtx tmp0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
> + rtx tmp1 = change_address (operands[0], mode, tmp0);
> + MEM_COPY_ATTRIBUTES (tmp1, operands[0]);
> + operands[0] = tmp1;
> }
>
> + /* 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;
> }
>
> @@ -9566,11 +9469,10 @@ arc_legitimize_address_0 (rtx x, rtx oldx ATTRIBUTE_UNUSED,
> {
> rtx addr, inner;
>
> - if (flag_pic && SYMBOLIC_CONST (x))
> - (x) = arc_legitimize_pic_address (x, 0);
> addr = x;
> if (GET_CODE (addr) == CONST)
> addr = XEXP (addr, 0);
> +
> if (GET_CODE (addr) == PLUS
> && CONST_INT_P (XEXP (addr, 1))
> && ((GET_CODE (XEXP (addr, 0)) == SYMBOL_REF
> @@ -9601,13 +9503,6 @@ arc_legitimize_address_0 (rtx x, rtx oldx ATTRIBUTE_UNUSED,
> static rtx
> 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);
>
> if (new_x)
> diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
> index 082b5bba6ec..ed29aa3d06e 100644
> --- a/gcc/config/arc/arc.md
> +++ b/gcc/config/arc/arc.md
> @@ -672,7 +672,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")
> (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[1], QImode)"
> + || register_operand (operands[1], QImode)
> + || (satisfies_constraint_Cm3 (operands[1])
> + && memory_operand (operands[0], QImode))"
> "@
> mov%? %0,%1%&
> mov%? %0,%1%&
> @@ -714,7 +716,9 @@ core_3, archs4x, archs4xd, archs4xd_slow"
> /* Don't use a LIMM that we could load with a single insn - we loose
> delay-slot filling opportunities. */
> && !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%&
> diff --git a/gcc/testsuite/gcc.target/arc/pr89838.c b/gcc/testsuite/gcc.target/arc/pr89838.c
> new file mode 100644
> index 00000000000..559434ac87e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arc/pr89838.c
> @@ -0,0 +1,16 @@
> +/* { 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);
> +}
> --
> 2.21.0
>
More information about the Gcc-patches
mailing list