Hi!

On Wed, Dec 11, 2019 at 07:48:39PM -0500, Michael Meissner wrote:
> This patch fixes a bug with vector extracts using a PC-relative address and a
> variable offset with using -mcpu=future.
> 
> Consider the code:
> 
>       #include <altivec.h>
> 
>       static vector double vd;
>       vector double *p = &vd;
> 
>       double get (unsigned int n)
>       {
>         return vec_extract (vd, n);
>       }
> 
> If you compile this code with -O2 -mcpu=future -mpcrel you get:
> 
>       get:
>               pla 9,.LANCHOR0@pcrel
>               lfdx 1,9,9
>               blr
> 
> This is because there is only one base register temporary, and the current 
> code
> tries to first create the offset and then use the same temporary to hold the
> address of the PC-relative value.
> 
> After combine the insn is:
> 
> (insn 14 9 15 2 (parallel [
>             (set (reg/i:DF 33 1)
>                 (unspec:DF [
>                         (mem/c:V2DF (symbol_ref:DI ("*.LANCHOR0") [flags 
> 0x182]) [1 vd+0 S16 A128])
>                         (reg:DI 123 [ n ])
>                     ] UNSPEC_VSX_EXTRACT))
>             (clobber (scratch:DI))
>             (clobber (scratch:V2DI))
>         ]) "foo.c":9:1 1314 {vsx_extract_v2df_var}

(After postreload as well, more to the point -- well, it has hard regs
there, of course).

> Split2 changes this to:

The vsx_extract_<mode>_var splitter dooes, yeah.

> (insn 20 8 21 2 (set (reg:DI 3 3 [orig:123 n ] [123])
>         (and:DI (reg:DI 3 3 [orig:123 n ] [123])
>             (const_int 1 [0x1]))) "foo.c":9:1 193 {anddi3_mask}
>      (nil))
> (insn 21 20 22 2 (set (reg:DI 9 9 [126])
>         (ashift:DI (reg:DI 3 3 [orig:123 n ] [123])
>             (const_int 3 [0x3]))) "foo.c":9:1 256 {ashldi3}
>      (nil))

These two are just  rlwinm 3,3,3,8  together, btw.  A good example why
splitters after reload are not great.

>  ;; Variable V2DI/V2DF extract
>  (define_insn_and_split "vsx_extract_<mode>_var"
> -  [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=v,wa,r")
> -     (unspec:<VS_scalar> [(match_operand:VSX_D 1 "input_operand" "v,m,m")
> -                          (match_operand:DI 2 "gpc_reg_operand" "r,r,r")]
> -                         UNSPEC_VSX_EXTRACT))
> -   (clobber (match_scratch:DI 3 "=r,&b,&b"))
> -   (clobber (match_scratch:V2DI 4 "=&v,X,X"))]
> +  [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=v,wa,r,wa,r")
> +     (unspec:<VS_scalar>
> +      [(match_operand:VSX_D 1 "input_operand" "v,em,em,ep,ep")
> +       (match_operand:DI 2 "gpc_reg_operand" "r,r,r,r,r")]
> +      UNSPEC_VSX_EXTRACT))
> +   (clobber (match_scratch:DI 3 "=r,&b,&b,&b,&b"))
> +   (clobber (match_scratch:V2DI 4 "=&v,X,X,X,X"))
> +   (clobber (match_scratch:DI 5 "=X,X,X,&b,&b"))]
>    "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
>    "#"
>    "&& reload_completed"
>    [(const_int 0)]
>  {
>    rs6000_split_vec_extract_var (operands[0], operands[1], operands[2],
> -                             operands[3], operands[4]);
> +                             operands[3], operands[4], operands[5]);

This writes to operands[2], which does not match its constraint.

Same in the other splitters.


Segher

Reply via email to