This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, V3, #6 of 10], Fix vec_extract breakage


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  <meissner@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: meissner@linux.ibm.com, phone: +1 (978) 899-4797


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]