On Fri, Dec 4, 2020 at 6:32 PM Jakub Jelinek <ja...@redhat.com> wrote:
>
> Hi!
>
> As mentioned in the PR, we can combine ~(1 << x) into -2 r<< x, but we give
> up in the ~(1 << (x & 31)) cases, as *<rotate_insn><mode>3_mask* don't allow
> immediate operand 1 and find_split_point prefers to split (x & 31) instead
> of the constant.
>
> With these combine splitters we help combine decide how to split those
> insns.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2020-12-04  Jakub Jelinek  <ja...@redhat.com>
>
>         PR target/96226
>         * config/i386/i386.md (splitter after *<rotate_insn><mode>3_mask,
>         splitter after *<rotate_insn><mode>3_mask_1): New combine splitters.
>
>         * gcc.target/i386/pr96226.c: New test.
>
> --- gcc/config/i386/i386.md.jj  2020-12-02 11:20:24.729487245 +0100
> +++ gcc/config/i386/i386.md     2020-12-04 15:39:17.481148449 +0100
> @@ -11975,6 +11975,23 @@ (define_insn_and_split "*<rotate_insn><m
>        (clobber (reg:CC FLAGS_REG))])]
>    "operands[2] = gen_lowpart (QImode, operands[2]);")
>
> +(define_split
> +  [(set (match_operand:SWI48 0 "register_operand")
> +       (any_rotate:SWI48
> +         (match_operand:SWI48 1 "const_int_operand")
> +         (subreg:QI
> +           (and:SI
> +             (match_operand:SI 2 "register_operand")
> +             (match_operand:SI 3 "const_int_operand")) 0)))]
> + "(INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1))
> +   == GET_MODE_BITSIZE (<MODE>mode) - 1"
> + [(set (match_dup 4) (match_dup 1))
> +  (set (match_dup 0)
> +       (any_rotate:SWI48 (match_dup 4)
> +                        (subreg:QI
> +                          (and:SI (match_dup 2) (match_dup 3)) 0)))]

Don't we need

   (clobber (reg:CC FLAGS_REG))]

here? (or is this one of the combine splitter peculiarities?)

Uros.

> + "operands[4] = gen_reg_rtx (<MODE>mode);")
> +
>  (define_insn_and_split "*<rotate_insn><mode>3_mask_1"
>    [(set (match_operand:SWI48 0 "nonimmediate_operand")
>         (any_rotate:SWI48
> @@ -11995,6 +12012,21 @@ (define_insn_and_split "*<rotate_insn><m
>                              (match_dup 2)))
>        (clobber (reg:CC FLAGS_REG))])])
>
> +(define_split
> +  [(set (match_operand:SWI48 0 "register_operand")
> +       (any_rotate:SWI48
> +         (match_operand:SWI48 1 "const_int_operand")
> +         (and:QI
> +           (match_operand:QI 2 "register_operand")
> +           (match_operand:QI 3 "const_int_operand"))))]
> + "(INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1))
> +  == GET_MODE_BITSIZE (<MODE>mode) - 1"
> + [(set (match_dup 4) (match_dup 1))
> +  (set (match_dup 0)
> +       (any_rotate:SWI48 (match_dup 4)
> +                        (and:QI (match_dup 2) (match_dup 3))))]
> + "operands[4] = gen_reg_rtx (<MODE>mode);")
> +
>  ;; Implement rotation using two double-precision
>  ;; shift instructions and a scratch register.
>
> --- gcc/testsuite/gcc.target/i386/pr96226.c.jj  2020-12-04 15:45:35.437890237 
> +0100
> +++ gcc/testsuite/gcc.target/i386/pr96226.c     2020-12-04 15:46:09.408507488 
> +0100
> @@ -0,0 +1,16 @@
> +/* PR target/96226 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +/* { dg-final { scan-assembler-times "\troll\t" 4 } } */
> +/* { dg-final { scan-assembler-times "\trolq\t" 4 { target { ! ia32 } } } } 
> */
> +
> +int f1 (int x) { return ~(1U << (x & 0x1f)); }
> +int f2 (int x) { return ~(1U << x); }
> +int f3 (unsigned char *x) { return ~(1U << (x[0] & 0x1f)); }
> +int f4 (unsigned char *x) { return ~(1U << x[0]); }
> +#ifdef __x86_64__
> +long int f5 (int x) { return ~(1ULL << (x & 0x3f)); }
> +long int f6 (int x) { return ~(1ULL << x); }
> +long int f7 (unsigned char *x) { return ~(1ULL << (x[0] & 0x3f)); }
> +long int f8 (unsigned char *x) { return ~(1ULL << x[0]); }
> +#endif
>
>         Jakub
>

Reply via email to