[PATCH][AArch64] Add BIC-imm and ORR-imm SIMD pattern

Sudi Das Sudi.Das@arm.com
Mon Aug 7 13:56:00 GMT 2017


Hi Richard

I have updated the patch according to your comments. Thanks for pointing it out and sorry for the delay!

Sudi

2017-08-07 Sudakshina Das  <sudi.das@arm.com>

	* config/aarch64/aarch64-protos.h (enum simd_immediate_check): New check type
	for aarch64_simd_valid_immediate.
	(aarch64_output_simd_general_immediate): New declaration.
	(aarch64_simd_valid_immediate): Update prototype.

	* config/aarch64/aarch64-simd.md (orr<mode>3): modified pattern to add
	support for ORR-immediate.
	(and<mode>3): modified pattern to add support for BIC-immediate.

	* config/aarch64/aarch64.c (aarch64_simd_valid_immediate): Function now checks
	for valid immediate for BIC and ORR based on new enum argument.
	(aarch64_output_simd_general_immediate): New function to output new BIC/ORR.
 
	* config/aarch64/constraints.md (Do): New vector immediate constraint.
	(Db): Likewise.

2017-08-07 Sudakshina Das  <sudi.das@arm.com>

	* gcc.target/aarch64/bic_imm_1.c: New test.
	* gcc.target/aarch64/orr_imm_1.c: Likewise.





From: Richard Earnshaw (lists) <Richard.Earnshaw@arm.com>
Sent: Friday, May 5, 2017 2:30 PM
To: Sudi Das; gcc-patches@gcc.gnu.org
Cc: nd; Marcus Shawcroft; James Greenhalgh
Subject: Re: [PATCH][AArch64] Add BIC-imm and ORR-imm SIMD pattern
    
On 18/04/17 17:39, Sudi Das wrote:
> 
> Hello all
> 
> This patch adds the support for BIC (vector, immediate) and ORR (vector, immediate) SIMD patterns to the AArch64 backend.
> One of the examples of this is : (with -O2 -ftree-vectorize)
> 
> void
> bic_s (short *a)
> {
>   for (int i = 0; i < 1024; i++)
>     a[i] &= ~(0xff);
> }
> 
> which now produces :
> bic_s:
>        add     x1, x0, 2048
>        .p2align 2
> .L2:
>        ldr     q0, [x0]
>        bic     v0.8h, #255
>        str     q0, [x0], 16
>        cmp     x1, x0
>        bne     .L2
>        ret
> 
> instead of
> bic_s:
>        movi    v1.8h, 0xff, lsl 8
>        add     x1, x0, 2048
>        .p2align 2
> .L2:
>        ldr     q0, [x0]
>        and     v0.16b, v0.16b, v1.16b
>        str     q0, [x0], 16
>        cmp     x1, x0
>        bne     .L2
>        ret
> 
> Added new tests and checked for regressions on bootstrapped aarch64-none-linux-gnu
> Ok for stage 1?
> 
> Thanks 
> Sudi
> 
> 2017-04-04 Sudakshina Das  <sudi.das@arm.com>
> 
>        * config/aarch64/aarch64-protos.h (enum simd_immediate_check): New check type
>        for aarch64_simd_valid_immediate.
>        (aarch64_output_simd_general_immediate): New declaration.
>        (aarch64_simd_valid_immediate): Update prototype.
> 
>        * config/aarch64/aarch64-simd.md (*bic_imm_<mode>3): New pattern.
>        (*ior_imm_<mode>3): Likewise.
> 
>        * config/aarch64/aarch64.c (aarch64_simd_valid_immediate): Function now checks
>        for valid immediate for BIC and ORR based on new enum argument.
>        (aarch64_output_simd_general_immediate): New function to output new BIC/ORR.
>  
>        * config/aarch64/predicates.md (aarch64_simd_valid_bic_imm_p) : New.
>        (aarch64_simd_valid_orr_imm_p) : Likewise.
> 
> 2017-04-04 Sudakshina Das  <sudi.das@arm.com>
> 
>        * gcc.target/aarch64/bic_imm_1.c: New test.
>        * gcc.target/aarch64/orr_imm_1.c: Likewise.
> 
> 
> patch-7260-2.diff
> 
> 
> diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
> index 9543f8c..89cc455 100644
> --- a/gcc/config/aarch64/aarch64-protos.h
> +++ b/gcc/config/aarch64/aarch64-protos.h
> @@ -297,6 +297,15 @@ enum aarch64_parse_opt_result
>    AARCH64_PARSE_INVALID_ARG          /* Invalid arch, tune, cpu arg.  */
>  };
>  
> +/* Enum to distinguish which type of check is to be done in
> +   aarch64_simd_valid_immediate.  This is used as a bitmask where CHECK_ALL
> +   has both bits set.  Adding new types would require changes accordingly.  */
> +enum simd_immediate_check {
> +  CHECK_I   = 1,     /* Perform only non-inverted immediate checks (ORR).  */
> +  CHECK_NI  = 2,     /* Perform only inverted immediate checks (BIC).  */
> +  CHECK_ALL = 3              /* Perform all checks (MOVI/MNVI).  */
> +};
> +
>  extern struct tune_params aarch64_tune_params;
>  
>  HOST_WIDE_INT aarch64_initial_elimination_offset (unsigned, unsigned);
> @@ -334,6 +343,8 @@ rtx aarch64_reverse_mask (enum machine_mode);
>  bool aarch64_offset_7bit_signed_scaled_p (machine_mode, HOST_WIDE_INT);
>  char *aarch64_output_scalar_simd_mov_immediate (rtx, machine_mode);
>  char *aarch64_output_simd_mov_immediate (rtx, machine_mode, unsigned);
> +char *aarch64_output_simd_general_immediate (rtx, machine_mode, unsigned,
> +                                          const char*);
>  bool aarch64_pad_arg_upward (machine_mode, const_tree);
>  bool aarch64_pad_reg_upward (machine_mode, const_tree, bool);
>  bool aarch64_regno_ok_for_base_p (int, bool);
> @@ -345,7 +356,8 @@ bool aarch64_simd_imm_zero_p (rtx, machine_mode);
>  bool aarch64_simd_scalar_immediate_valid_for_move (rtx, machine_mode);
>  bool aarch64_simd_shift_imm_p (rtx, machine_mode, bool);
>  bool aarch64_simd_valid_immediate (rtx, machine_mode, bool,
> -                                struct simd_immediate_info *);
> +                                struct simd_immediate_info *,
> +                                enum simd_immediate_check w = CHECK_ALL);
>  bool aarch64_split_dimode_const_store (rtx, rtx);
>  bool aarch64_symbolic_address_p (rtx);
>  bool aarch64_uimm12_shift (HOST_WIDE_INT);
> diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
> index c462164..92275dc 100644
> --- a/gcc/config/aarch64/aarch64-simd.md
> +++ b/gcc/config/aarch64/aarch64-simd.md
> @@ -280,6 +280,26 @@
>    [(set_attr "type" "neon_logic<q>")]
>  )
>  
> +(define_insn "*bic_imm_<mode>3"
> + [(set (match_operand:VDQ_I 0 "register_operand" "=w")
> +       (and:VDQ_I (match_operand:VDQ_I 1 "register_operand" "0")
> +             (match_operand:VDQ_I 2 "aarch64_simd_valid_bic_imm_p" "")))]
> + "TARGET_SIMD"
> + { return aarch64_output_simd_general_immediate (operands[2],
> +                     <MODE>mode, GET_MODE_BITSIZE (<MODE>mode), "bic"); }
> +  [(set_attr "type" "neon_logic<q>")]
> +)
> +
> +(define_insn "*ior_imm_<mode>3"
> + [(set (match_operand:VDQ_I 0 "register_operand" "=w")
> +       (ior:VDQ_I (match_operand:VDQ_I 1 "register_operand" "0")
> +             (match_operand:VDQ_I 2 "aarch64_simd_valid_orr_imm_p" "")))]
> + "TARGET_SIMD"
> + { return aarch64_output_simd_general_immediate (operands[2],
> +                     <MODE>mode, GET_MODE_BITSIZE (<MODE>mode), "orr"); }
> +  [(set_attr "type" "neon_logic<q>")]
> +)

Both of these generate the same RTL constructs as the simd ior<mode>3
and and<mode>3 patterns, so should be merged as subcases of those
patterns (and handled with suitable constraint alternatives).

R.

> +
>  (define_insn "add<mode>3"
>    [(set (match_operand:VDQ_I 0 "register_operand" "=w")
>          (plus:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w")
> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
> index 4f769a4..450c42d 100644
> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -11066,7 +11066,8 @@ aarch64_vect_float_const_representable_p (rtx x)
>  /* Return true for valid and false for invalid.  */
>  bool
>  aarch64_simd_valid_immediate (rtx op, machine_mode mode, bool inverse,
> -                           struct simd_immediate_info *info)
> +                           struct simd_immediate_info *info,
> +                           enum simd_immediate_check which)
>  {
>  #define CHECK(STRIDE, ELSIZE, CLASS, TEST, SHIFT, NEG)       \
>    matches = 1;                                               \
> @@ -11130,54 +11131,65 @@ aarch64_simd_valid_immediate (rtx op, machine_mode mode, bool inverse,
>  
>    do
>      {
> -      CHECK (4, 32, 0, bytes[i] == bytes[0] && bytes[i + 1] == 0
> -          && bytes[i + 2] == 0 && bytes[i + 3] == 0, 0, 0);
> +      if (which & CHECK_I)
> +     {
> +       CHECK (4, 32, 0, bytes[i] == bytes[0] && bytes[i + 1] == 0
> +              && bytes[i + 2] == 0 && bytes[i + 3] == 0, 0, 0);
>  
> -      CHECK (4, 32, 1, bytes[i] == 0 && bytes[i + 1] == bytes[1]
> -          && bytes[i + 2] == 0 && bytes[i + 3] == 0, 8, 0);
> +       CHECK (4, 32, 1, bytes[i] == 0 && bytes[i + 1] == bytes[1]
> +              && bytes[i + 2] == 0 && bytes[i + 3] == 0, 8, 0);
>  
> -      CHECK (4, 32, 2, bytes[i] == 0 && bytes[i + 1] == 0
> -          && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0, 16, 0);
> +       CHECK (4, 32, 2, bytes[i] == 0 && bytes[i + 1] == 0
> +              && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0, 16, 0);
>  
> -      CHECK (4, 32, 3, bytes[i] == 0 && bytes[i + 1] == 0
> -          && bytes[i + 2] == 0 && bytes[i + 3] == bytes[3], 24, 0);
> +       CHECK (4, 32, 3, bytes[i] == 0 && bytes[i + 1] == 0
> +              && bytes[i + 2] == 0 && bytes[i + 3] == bytes[3], 24, 0);
>  
> -      CHECK (2, 16, 4, bytes[i] == bytes[0] && bytes[i + 1] == 0, 0, 0);
> +       CHECK (2, 16, 4, bytes[i] == bytes[0] && bytes[i + 1] == 0, 0, 0);
>  
> -      CHECK (2, 16, 5, bytes[i] == 0 && bytes[i + 1] == bytes[1], 8, 0);
> +       CHECK (2, 16, 5, bytes[i] == 0 && bytes[i + 1] == bytes[1], 8, 0);
> +     }
>  
> -      CHECK (4, 32, 6, bytes[i] == bytes[0] && bytes[i + 1] == 0xff
> -          && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 0, 1);
> +      if (which & CHECK_NI)
> +     {
> +       CHECK (4, 32, 6, bytes[i] == bytes[0] && bytes[i + 1] == 0xff
> +              && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 0, 1);
>  
> -      CHECK (4, 32, 7, bytes[i] == 0xff && bytes[i + 1] == bytes[1]
> -          && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 8, 1);
> +       CHECK (4, 32, 7, bytes[i] == 0xff && bytes[i + 1] == bytes[1]
> +              && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 8, 1);
>  
> -      CHECK (4, 32, 8, bytes[i] == 0xff && bytes[i + 1] == 0xff
> -          && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0xff, 16, 1);
> +       CHECK (4, 32, 8, bytes[i] == 0xff && bytes[i + 1] == 0xff
> +              && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0xff, 16, 1);
>  
> -      CHECK (4, 32, 9, bytes[i] == 0xff && bytes[i + 1] == 0xff
> -          && bytes[i + 2] == 0xff && bytes[i + 3] == bytes[3], 24, 1);
> +       CHECK (4, 32, 9, bytes[i] == 0xff && bytes[i + 1] == 0xff
> +              && bytes[i + 2] == 0xff && bytes[i + 3] == bytes[3], 24, 1);
>  
> -      CHECK (2, 16, 10, bytes[i] == bytes[0] && bytes[i + 1] == 0xff, 0, 1);
> +       CHECK (2, 16, 10, bytes[i] == bytes[0] && bytes[i + 1] == 0xff, 0, 1);
>  
> -      CHECK (2, 16, 11, bytes[i] == 0xff && bytes[i + 1] == bytes[1], 8, 1);
> +       CHECK (2, 16, 11, bytes[i] == 0xff && bytes[i + 1] == bytes[1], 8, 1);
> +     }
>  
> -      CHECK (4, 32, 12, bytes[i] == 0xff && bytes[i + 1] == bytes[1]
> -          && bytes[i + 2] == 0 && bytes[i + 3] == 0, 8, 0);
> +      /* Shifting ones / 8-bit / 64-bit variants only checked
> +      for 'ALL' (MOVI/MVNI).  */
> +      if (which == CHECK_ALL)
> +     {
> +       CHECK (4, 32, 12, bytes[i] == 0xff && bytes[i + 1] == bytes[1]
> +              && bytes[i + 2] == 0 && bytes[i + 3] == 0, 8, 0);
>  
> -      CHECK (4, 32, 13, bytes[i] == 0 && bytes[i + 1] == bytes[1]
> -          && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 8, 1);
> +       CHECK (4, 32, 13, bytes[i] == 0 && bytes[i + 1] == bytes[1]
> +              && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 8, 1);
>  
> -      CHECK (4, 32, 14, bytes[i] == 0xff && bytes[i + 1] == 0xff
> -          && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0, 16, 0);
> +       CHECK (4, 32, 14, bytes[i] == 0xff && bytes[i + 1] == 0xff
> +              && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0, 16, 0);
>  
> -      CHECK (4, 32, 15, bytes[i] == 0 && bytes[i + 1] == 0
> -          && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0xff, 16, 1);
> +       CHECK (4, 32, 15, bytes[i] == 0 && bytes[i + 1] == 0
> +              && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0xff, 16, 1);
>  
> -      CHECK (1, 8, 16, bytes[i] == bytes[0], 0, 0);
> +       CHECK (1, 8, 16, bytes[i] == bytes[0], 0, 0);
>  
> -      CHECK (1, 64, 17, (bytes[i] == 0 || bytes[i] == 0xff)
> -          && bytes[i] == bytes[(i + 8) % idx], 0, 0);
> +       CHECK (1, 64, 17, (bytes[i] == 0 || bytes[i] == 0xff)
> +              && bytes[i] == bytes[(i + 8) % idx], 0, 0);
> +     }
>      }
>    while (0);
>  
> @@ -12598,6 +12610,47 @@ aarch64_output_simd_mov_immediate (rtx const_vector,
>    return templ;
>  }
>  
> +/* This function is similar to aarch64_output_simd_mov_immediate, used for
> +   immediate versions of 'bic' or 'orr'.  */
> +char*
> +aarch64_output_simd_general_immediate (rtx const_vector,
> +                                    machine_mode mode,
> +                                    unsigned width,
> +                                    const char *mnemonic)
> +{
> +  bool is_valid;
> +  static char templ[40];
> +  unsigned int lane_count = 0;
> +  char element_char;
> +
> +  struct simd_immediate_info info = { NULL_RTX, 0, 0, false, false };
> +
> +  if (strcmp (mnemonic, "orr") == 0)
> +    is_valid = aarch64_simd_valid_immediate (const_vector, mode, false,
> +                                          &info, CHECK_I);
> +  else
> +    is_valid = aarch64_simd_valid_immediate (const_vector, mode, false,
> +                                          &info, CHECK_NI);
> +
> +  gcc_assert (is_valid);
> +  gcc_assert (CONST_INT_P (info.value));
> +
> +  element_char = sizetochar (info.element_width);
> +  lane_count = width / info.element_width;
> +
> +  if (lane_count == 1)
> +    sprintf (templ, "%s\t%%d0, #" HOST_WIDE_INT_PRINT_DEC,
> +           mnemonic, UINTVAL (info.value));
> +  else if (info.shift)
> +    sprintf (templ, "%s\t%%0.%d%c, #" HOST_WIDE_INT_PRINT_DEC
> +           ", %s #%d", mnemonic, lane_count, element_char,
> +           UINTVAL (info.value), "lsl", info.shift);
> +  else
> +    sprintf (templ, "%s\t%%0.%d%c, #" HOST_WIDE_INT_PRINT_DEC,
> +           mnemonic, lane_count, element_char, UINTVAL (info.value));
> +  return templ;
> +}
> +
>  char*
>  aarch64_output_scalar_simd_mov_immediate (rtx immediate,
>                                          machine_mode mode)
> diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
> index e83d45b..fe65f2b 100644
> --- a/gcc/config/aarch64/predicates.md
> +++ b/gcc/config/aarch64/predicates.md
> @@ -307,6 +307,18 @@
>    return aarch64_simd_shift_imm_p (op, mode, false);
>  })
>  
> +(define_special_predicate "aarch64_simd_valid_bic_imm_p"
> +  (match_code "const_vector")
> +{
> +  return aarch64_simd_valid_immediate (op, mode, false, NULL, CHECK_NI);
> +})
> +
> +(define_special_predicate "aarch64_simd_valid_orr_imm_p"
> +  (match_code "const_vector")
> +{
> +  return aarch64_simd_valid_immediate (op, mode, false, NULL, CHECK_I);
> +})
> +
>  (define_predicate "aarch64_simd_reg_or_zero"
>    (and (match_code "reg,subreg,const_int,const_double,const_vector")
>         (ior (match_operand 0 "register_operand")
> diff --git a/gcc/testsuite/gcc.target/aarch64/bic_imm_1.c b/gcc/testsuite/gcc.target/aarch64/bic_imm_1.c
> new file mode 100644
> index 0000000..d94dd90
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/bic_imm_1.c
> @@ -0,0 +1,26 @@
> +/* { dg-options "-O2 -ftree-vectorize" } */
> +
> +void
> +bic_s (short *a)
> +{
> +  for (int i = 0; i < 1024; i++)
> +    a[i] &= ~(0xff);
> +}
> +
> +void
> +bic_ss (short *a)
> +{
> +  for (int i = 0; i < 1024; i++)
> +    a[i] &= ~(0xff00);
> +}
> +
> +void
> +bic_int (int *a)
> +{
> +  for (int i = 0; i < 1024; i++)
> +    a[i] &= ~(0xff);
> +}
> +
> +/* { dg-final { scan-assembler "bic\\tv\[0-9\]+.8h, #255" } } */
> +/* { dg-final { scan-assembler "bic\\tv\[0-9\]+.8h, #255, lsl #8" } } */
> +/* { dg-final { scan-assembler "bic\\tv\[0-9\]+.4s, #255" } } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/orr_imm_1.c b/gcc/testsuite/gcc.target/aarch64/orr_imm_1.c
> new file mode 100644
> index 0000000..919a6ef
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/orr_imm_1.c
> @@ -0,0 +1,18 @@
> +/* { dg-options "-O2 -ftree-vectorize" } */
> +
> +void
> +orr_s (short *a)
> +{
> +  for (int i = 0; i < 1024; i++)
> +    a[i] |= 0xab;
> +}
> +
> +void
> +orr_int (int *a)
> +{
> +  for (int i = 0; i < 1024; i++)
> +    a[i] |= 0xab;
> +}
> +
> +/* { dg-final { scan-assembler "orr\\tv\[0-9\]+.8h, #171" } } */
> +/* { dg-final { scan-assembler "orr\\tv\[0-9\]+.4s, #171" } } */
> 

    
-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch-7260-3.diff
Type: text/x-patch
Size: 12555 bytes
Desc: patch-7260-3.diff
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20170807/7b63278c/attachment.bin>


More information about the Gcc-patches mailing list