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