This patch fixes the bug I mentioned in a previous patch, i.e. #include <altivec.h>
static vector double v; // ... double foo (int n) { double x = vec_extract (v, n); return x; } would generate incorrect code because it only has one temporary register, and it needs two temporary registers (one to hold the pc-relative address, and the other to hold the index). In the previous V3 patch #4 that added pc-relative support, I put in an abort for this case. This patch actually fixes it. Originally, I solved it by just adding a predicate/condition to not allow a pc-relative address to combine with the extract directly. But I found the reload pass was joining the two insns, so I added a new constraint (ep) to say this memory insn must not involve a pc-relative address. If you have an unused constraint pair that you would prefer instead of "ep", I can easily switch to use that. I built a boostrap compiler on a little endian power8 system, and there were no regressions in running make check. Can I check this change into the trunk once the previous patches are checked in? 2019-08-26 Michael Meissner <meiss...@linux.ibm.com> * config/rs6000/constraints.md (ep constraint): New constraint. * config/rs6000/predicates.md (non_pcrel_mem_operand): New predicate. (reg_or_non_pcrel_operand): New predicate. * config/rs6000/vsx.md (vsx_extract_<mode>_var, VSX_D iterator): Don't allow pc-relative memory addresses. (vsx_extract_v4sf_var): Don't allow pc-relative memory addresses. (vsx_extract_<mode>_var, VSX_EXTRACT_I iterator): Don't allow pc-relative memory addresses. (vsx_extract_<mode>_<VS_scalar>mode_var): Don't allow pc-relative memory addresses. * doc/md.texi (PowerPC Constraints): Document ep constraint. Index: gcc/config/rs6000/constraints.md =================================================================== --- gcc/config/rs6000/constraints.md (revision 274864) +++ gcc/config/rs6000/constraints.md (working copy) @@ -210,6 +210,11 @@ several times, or that might not access (and (match_code "mem") (match_test "GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) != RTX_AUTOINC"))) +(define_memory_constraint "ep" + "A memory operand that does not contain a pc-relative reference." + (and (match_code "mem") + (match_test "non_pcrel_mem_operand (op, mode)"))) + (define_memory_constraint "Q" "Memory operand that is an offset from a register (it is usually better to use @samp{m} or @samp{es} in @code{asm} statements)" Index: gcc/config/rs6000/predicates.md =================================================================== --- gcc/config/rs6000/predicates.md (revision 274874) +++ gcc/config/rs6000/predicates.md (working copy) @@ -1706,6 +1706,33 @@ (define_predicate "non_prefixed_mem_oper TRAD_INSN_DEFAULT); }) +;; Return 1 if op is a memory operand that does not contain a pc-relative +;; address. +(define_predicate "non_pcrel_mem_operand" + (match_code "mem") +{ + if (!memory_operand (op, mode)) + return false; + + return (!pcrel_local_address (XEXP (op, 0), Pmode) + && !pcrel_ext_address (XEXP (op, 0), Pmode)); +}) + +;; Return 1 if op is a register or a memory operand that does not contain a +;; pc-relatve address. +(define_predicate "reg_or_non_pcrel_operand" + (match_code "reg,subreg,mem") +{ + if (REG_P (op) || SUBREG_P (op)) + return true; + + if (!memory_operand (op, mode)) + return false; + + return (!pcrel_local_address (XEXP (op, 0), Pmode) + && !pcrel_ext_address (XEXP (op, 0), Pmode)); +}) + ;; Match the first insn (addis) in fusing the combination of addis and loads to ;; GPR registers on power8. (define_predicate "fusion_gpr_addis" Index: gcc/config/rs6000/vsx.md =================================================================== --- gcc/config/rs6000/vsx.md (revision 274874) +++ gcc/config/rs6000/vsx.md (working copy) @@ -3249,9 +3249,10 @@ (define_insn "vsx_vslo_<mode>" ;; 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)) + (unspec:<VS_scalar> + [(match_operand:VSX_D 1 "reg_or_non_pcrel_operand" "v,ep,ep") + (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"))] "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT" @@ -3319,9 +3320,10 @@ (define_insn_and_split "*vsx_extract_v4s ;; Variable V4SF extract (define_insn_and_split "vsx_extract_v4sf_var" [(set (match_operand:SF 0 "gpc_reg_operand" "=wa,wa,?r") - (unspec:SF [(match_operand:V4SF 1 "input_operand" "v,m,m") - (match_operand:DI 2 "gpc_reg_operand" "r,r,r")] - UNSPEC_VSX_EXTRACT)) + (unspec:SF + [(match_operand:V4SF 1 "reg_or_non_pcrel_operand" "v,ep,ep") + (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"))] "VECTOR_MEM_VSX_P (V4SFmode) && TARGET_DIRECT_MOVE_64BIT" @@ -3682,7 +3684,7 @@ (define_insn_and_split "*vsx_extract_<mo (define_insn_and_split "vsx_extract_<mode>_var" [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=r,r,r") (unspec:<VS_scalar> - [(match_operand:VSX_EXTRACT_I 1 "input_operand" "v,v,m") + [(match_operand:VSX_EXTRACT_I 1 "reg_or_non_pcrel_operand" "v,v,ep") (match_operand:DI 2 "gpc_reg_operand" "r,r,r")] UNSPEC_VSX_EXTRACT)) (clobber (match_scratch:DI 3 "=r,r,&b")) @@ -3702,7 +3704,7 @@ (define_insn_and_split "*vsx_extract_<mo [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=r,r,r") (zero_extend:<VS_scalar> (unspec:<VSX_EXTRACT_I:VS_scalar> - [(match_operand:VSX_EXTRACT_I 1 "input_operand" "v,v,m") + [(match_operand:VSX_EXTRACT_I 1 "reg_or_non_pcrel_operand" "v,v,ep") (match_operand:DI 2 "gpc_reg_operand" "r,r,r")] UNSPEC_VSX_EXTRACT))) (clobber (match_scratch:DI 3 "=r,r,&b")) Index: gcc/doc/md.texi =================================================================== --- gcc/doc/md.texi (revision 274864) +++ gcc/doc/md.texi (working copy) @@ -3343,6 +3343,9 @@ Constant whose negation is a signed 16-b @item eI Signed 34-bit integer constant if prefixed instructions are supported. +@item ep +A memory operand that does not include a pc-relative address. + @item G Floating point constant that can be loaded into a register with one instruction per word -- Michael Meissner, IBM IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA email: meiss...@linux.ibm.com, phone: +1 (978) 899-4797