On Fri, 2021-01-29 at 11:11 +0800, HAO CHEN GUI via Gcc-patches wrote:
> Hi,
>
Hi,
just a couple cosmetic nits below.
Thanks,
> This patch tries to optimize PowerPC 64 bit constant generation
> when
> the constant can be transformed from a 32 bit or 16 bit constant by
> rotating, shifting and mask AND.
Presumably this *does* optimize the constant generation. :-)
s/tries to optimize/optimizes/
>
> The attachments are the patch diff file and change log file.
>
> Bootstrapped and tested on powerpc64le with no regressions. Is
> this
> okay for trunk? Any recommendations? Thanks a lot.
>
> PR target/94395
> * config/rs6000/rs6000.c (rs6000_emit_set_32bit_const,
> rs6000_rotate_long_const, rs6000_peel_long_const): New functions.
> (rs6000_emit_set_long_const, num_insns_constant_gpr): Call new
> functions.
> * testsuite/gcc.target/powerpc/pr94395.c: New test.
ok
On Fri, 2021-01-29 at 11:11 +0800, HAO CHEN GUI via Gcc-patches wrote:
> diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
> index f26fc13484b..bcb867ffe94 100644
> --- a/gcc/config/rs6000/rs6000.c
> +++ b/gcc/config/rs6000/rs6000.c
> @@ -1109,6 +1109,9 @@ static tree rs6000_handle_longcall_attribute (tree *,
> tree, tree, int, bool *);
> static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool
> *);
> static tree rs6000_handle_struct_attribute (tree *, tree, tree, int, bool *);
> static tree rs6000_builtin_vectorized_libmass (combined_fn, tree, tree);
> +static HOST_WIDE_INT rs6000_rotate_long_const (unsigned HOST_WIDE_INT, int
> *);
> +static HOST_WIDE_INT rs6000_peel_long_const (unsigned HOST_WIDE_INT, int *,
> + int *);
> static void rs6000_emit_set_long_const (rtx, HOST_WIDE_INT);
> static int rs6000_memory_move_cost (machine_mode, reg_class_t, bool);
> static bool rs6000_debug_rtx_costs (rtx, machine_mode, int, int, int *,
> bool);
> @@ -5868,12 +5871,28 @@ num_insns_constant_gpr (HOST_WIDE_INT value)
>
> else if (TARGET_POWERPC64)
> {
> + int rotate, head, tail;
> + HOST_WIDE_INT imm1, imm2;
> + unsigned HOST_WIDE_INT uc = value;
> HOST_WIDE_INT low = ((value & 0xffffffff) ^ 0x80000000) - 0x80000000;
> HOST_WIDE_INT high = value >> 31;
>
> if (high == 0 || high == -1)
> return 2;
>
> + /* A long constant can be transformed from both a 16 bit constant and
> + a 32 bit constant. So we first test imm1 and imm2 if they're 16
> + bit. */
> + imm1 = rs6000_rotate_long_const (uc, &rotate);
> + if (SIGNED_INTEGER_16BIT_P (imm1))
> + return 2;
> + imm2 = rs6000_peel_long_const (uc, &head, &tail);
> + if (SIGNED_INTEGER_16BIT_P (imm2))
> + return 2;
> + if (SIGNED_INTEGER_NBIT_P (imm1, 32)
> + || SIGNED_INTEGER_NBIT_P (imm2, 32))
> + return 3;
> +
Ok.
> high >>= 1;
>
> if (low == 0 || low == high)
> @@ -9720,6 +9739,96 @@ rs6000_emit_set_const (rtx dest, rtx source)
> return true;
> }
>
> +/* Function to load 32 a bit constant. */
> +static void
> +rs6000_emit_set_32bit_const (rtx dest, HOST_WIDE_INT c)
> +{
> + gcc_assert (SIGNED_INTEGER_NBIT_P (c, 32));
> +
> + rtx temp = can_create_pseudo_p () ? gen_reg_rtx (DImode) : dest;
> +
> + if (SIGNED_INTEGER_16BIT_P (c))
> + emit_insn (gen_rtx_SET (dest, GEN_INT (c)));
> + else
> + {
> + emit_insn (gen_rtx_SET (copy_rtx (temp),
> + GEN_INT (c & ~(HOST_WIDE_INT) 0xffff)));
> + emit_insn (gen_rtx_SET (dest,
> + gen_rtx_IOR (DImode, copy_rtx (temp),
> + GEN_INT (c & 0xffff))));
> + }
> +}
ok
> +
> +/* Helper function of rs6000_emit_set_long_const to left rotate a long
> + constant. It returns the result immediately when it finds a 32 bit
> + constant. It at most rotates for 31 bits.
> + For instant, the constant 0x1230000000000004 can be transformed to
> + a 32 bit constant 0x0000000000004123 by left rotating 12 bits. */
> +static HOST_WIDE_INT
> +rs6000_rotate_long_const (unsigned HOST_WIDE_INT c, int *rot)
> +{
> + int bitsize = GET_MODE_BITSIZE (DImode);
> + bool found = false;
> + unsigned HOST_WIDE_INT imm = c;
> + unsigned HOST_WIDE_INT m = imm >> (bitsize - 1);
> + int rotate = 0;
> +
> + while (rotate < 31 && !found)
> + {
> + imm = imm << 1 | m;
> + if (clz_hwi (imm) > 32 || clz_hwi (~imm) > 32)
> + found = true;
> + rotate++;
> + m = imm >> (bitsize - 1);
> + }
> +
> + *rot = rotate;
> + return imm;
> +}
ok.
> +
> +/* Helper function of rs6000_emit_set_long_const to reutrn a constant by
return
> + removing consecutive 0s and 1s at the head and tail then setting all high
> + bits.
> + For instance, 0x000000fff2345000 can be transformed to 0xfff2345 by
> + peeling the head and tail, then to 0xffffffffffff234 by setting all
> + high bits.
You lost a trailing 5.
Aside from the nits, comments look good to me.
Nothing else jumped out at me below.
thanks,
-Will