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