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]

Re: [PATCH] Allow all 1s of integer as standard SSE constants


On Thu, Apr 21, 2016 at 9:37 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Thu, Apr 21, 2016 at 9:31 AM, Uros Bizjak <ubizjak@gmail.com> wrote:
>> On Thu, Apr 21, 2016 at 4:50 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>>
>>>>> I tried and it doesn't work since the correct mode may not be always
>>>>> available in predicates.  Yes, they pass mode.  But they just do
>>>>>
>>>>> mode = GET_MODE (op);
>>>>>
>>>>> which returns VOIDmode for -1.
>>>>
>>>> Well, looking at generated gcc/insns-preds.c, the predicates do:
>>>>
>>>> (mode == VOIDmode || GET_MODE (op) == mode).
>>>>
>>>> They *check* and don't *assign* "mode" variable.
>>>>
>>>> So, I see no problem checking "mode" variable (that gets the value
>>>> from the pattern) in the predicates.
>>>
>>> This is an incomplete list:
>>>
>>> combine.c:   && ! push_operand (dest, GET_MODE (dest)))
>>> expr.c:  if (push_operand (x, GET_MODE (x)))
>>> expr.c:  && ! push_operand (x, GET_MODE (x))))
>>> gcse.c:   && ! push_operand (dest, GET_MODE (dest)))
>>> gcse.c:  if (general_operand (exp, GET_MODE (reg)))
>>> ifcvt.c:  if (! general_operand (cmp_a, GET_MODE (cmp_a))
>>> ifcvt.c:      || ! general_operand (cmp_b, GET_MODE (cmp_b)))
>>> ifcvt.c:      else if (general_operand (b, GET_MODE (b)))
>>> ifcvt.c:  if (! general_operand (a, GET_MODE (a)) || tmp_a)
>>> ifcvt.c:  if (! general_operand (b, GET_MODE (b)) || tmp_b)
>>> ira-costs.c:      if (address_operand (op, GET_MODE (op))
>>> ira-costs.c:      && general_operand (SET_SRC (set), GET_MODE (SET_SRC (set))))
>>> lower-subreg.c:      if (GET_MODE (op_operand) != word_mode
>>> lower-subreg.c:      && GET_MODE_SIZE (GET_MODE (op_operand)) > UNITS_PER_WORD)
>>> lower-subreg.c:                                         GET_MODE (op_operand),
>>> lra-constraints.c: if (simplify_operand_subreg (i, GET_MODE (old)) ||
>>> op_change_p)
>>> optabs.c:  create_output_operand (&ops[0], target, GET_MODE (target));
>>> optabs.c:  create_input_operand (&ops[1], op0, GET_MODE (op0));
>>> postreload-gcse.c:      if (! push_operand (dest, GET_MODE (dest)))
>>> postreload-gcse.c:  && general_operand (src, GET_MODE (src))
>>> postreload-gcse.c:  && general_operand (dest, GET_MODE (dest))
>>> postreload-gcse.c:  && general_operand (src, GET_MODE (src))
>>>
>>> IRA and LRA use GET_MODE and pass it to predicates.
>>
>> I don't know what are you trying to prove here ...
>
> The "mode" argument passed to predates can't be used to determine if
> -1 is a valid SSE constant.
>

Hi Uros,

Here is the updated patch with my standard_sse_constant_p change and
your SSE/AVX pattern change.  I didn't include your
standard_sse_constant_opcode since it didn't compile nor is needed
for this purpose.

-- 
H.J.
From 57c811f25e0735e744d255b3d66a86dbb131749c Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Sun, 6 Mar 2016 06:40:31 -0800
Subject: [PATCH] Allow all 1s of integer as standard SSE constants

Since all 1s in TImode is standard SSE2 constants, all 1s in OImode is
standard AVX2 constants and all 1s in XImode is standard AVX512F constants,
pass mode to standard_sse_constant_p and standard_sse_constant_opcode
to check if all 1s is available for target.

	* config/i386/i386-protos.h (standard_sse_constant_p): Take
	machine_mode with VOIDmode as default.
	* config/i386/i386.c (standard_sse_constant_p): Get mode if
	it is VOIDmode.  Return 2 for all 1s of integer in supported
	modes.
	(ix86_expand_vector_move): Pass mode to standard_sse_constant_p.
	* config/i386/i386.md (*movxi_internal_avx512f): Replace
	vector_move_operand with nonimmediate_or_sse_const_operand and
	use BC instead of C in constraint.  Check register_operand
	instead of MEM_P.
	(*movoi_internal_avx): Add a "BC" alternative for AVX2.  Check
	register_operand instead of MEM_P.
	(*movti_internal): Add a "BC" alternative for SSE2.  Check
	register_operand instead of MEM_P for SSE.
---
 gcc/config/i386/i386-protos.h |  2 +-
 gcc/config/i386/i386.c        | 27 ++++++++++++++++++++-------
 gcc/config/i386/i386.md       | 39 ++++++++++++++++++++++++---------------
 3 files changed, 45 insertions(+), 23 deletions(-)

diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index ff47bc1..cf54189 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -50,7 +50,7 @@ extern bool ix86_using_red_zone (void);
 extern int standard_80387_constant_p (rtx);
 extern const char *standard_80387_constant_opcode (rtx);
 extern rtx standard_80387_constant_rtx (int);
-extern int standard_sse_constant_p (rtx);
+extern int standard_sse_constant_p (rtx, machine_mode = VOIDmode);
 extern const char *standard_sse_constant_opcode (rtx_insn *, rtx);
 extern bool symbolic_reference_mentioned_p (rtx);
 extern bool extended_reg_mentioned_p (rtx);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 6379313..dd951c2 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -10766,18 +10766,31 @@ standard_80387_constant_rtx (int idx)
    in supported SSE/AVX vector mode.  */
 
 int
-standard_sse_constant_p (rtx x)
+standard_sse_constant_p (rtx x, machine_mode mode)
 {
-  machine_mode mode;
-
   if (!TARGET_SSE)
     return 0;
 
-  mode = GET_MODE (x);
-  
+  if (mode == VOIDmode)
+    mode = GET_MODE (x);
+
   if (x == const0_rtx || x == CONST0_RTX (mode))
     return 1;
-  if (vector_all_ones_operand (x, mode))
+  if (CONST_INT_P (x))
+    {
+      /* If mode != VOIDmode, standard_sse_constant_p must be called:
+	 1. On TImode with SSE2.
+	 2. On OImode with AVX2.
+	 3. On XImode with AVX512F.
+       */
+      if ((HOST_WIDE_INT) INTVAL (x) == HOST_WIDE_INT_M1
+	  && (mode == VOIDmode
+	      || (mode == TImode && TARGET_SSE2)
+	      || (mode == OImode && TARGET_AVX2)
+	      || (mode == XImode && TARGET_AVX512F)))
+	return 2;
+    }
+  else if (vector_all_ones_operand (x, mode))
     switch (mode)
       {
       case V16QImode:
@@ -18758,7 +18771,7 @@ ix86_expand_vector_move (machine_mode mode, rtx operands[])
       && (CONSTANT_P (op1)
 	  || (SUBREG_P (op1)
 	      && CONSTANT_P (SUBREG_REG (op1))))
-      && !standard_sse_constant_p (op1))
+      && !standard_sse_constant_p (op1, mode))
     op1 = validize_mem (force_const_mem (mode, op1));
 
   /* We need to check memory alignment for SSE mode since attribute
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index babd0a4..716c4ba 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -1970,9 +1970,11 @@
    (set_attr "length_immediate" "1")])
 
 (define_insn "*movxi_internal_avx512f"
-  [(set (match_operand:XI 0 "nonimmediate_operand" "=v,v ,m")
-	(match_operand:XI 1 "vector_move_operand"  "C ,vm,v"))]
-  "TARGET_AVX512F && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+  [(set (match_operand:XI 0 "nonimmediate_operand"		"=v,v ,m")
+	(match_operand:XI 1 "nonimmediate_or_sse_const_operand" "BC,vm,v"))]
+  "TARGET_AVX512F
+   && (register_operand (operands[0], XImode)
+       || register_operand (operands[1], XImode))"
 {
   switch (which_alternative)
     {
@@ -1994,9 +1996,11 @@
    (set_attr "mode" "XI")])
 
 (define_insn "*movoi_internal_avx"
-  [(set (match_operand:OI 0 "nonimmediate_operand" "=v,v ,m")
-	(match_operand:OI 1 "vector_move_operand"  "C ,vm,v"))]
-  "TARGET_AVX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+  [(set (match_operand:OI 0 "nonimmediate_operand"		"=v,v,v ,m")
+	(match_operand:OI 1 "nonimmediate_or_sse_const_operand" "BC,C,vm,v"))]
+  "TARGET_AVX
+   && (register_operand (operands[0], OImode)
+       || register_operand (operands[1], OImode))"
 {
   switch (get_attr_type (insn))
     {
@@ -2028,7 +2032,8 @@
       gcc_unreachable ();
     }
 }
-  [(set_attr "type" "sselog1,ssemov,ssemov")
+  [(set_attr "isa" "avx2,*,*,*")
+   (set_attr "type" "sselog1,sselog1,ssemov,ssemov")
    (set_attr "prefix" "vex")
    (set (attr "mode")
 	(cond [(ior (match_operand 0 "ext_sse_reg_operand")
@@ -2036,17 +2041,21 @@
 		 (const_string "XI")
 	       (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")
 		 (const_string "V8SF")
-	       (and (eq_attr "alternative" "2")
+	       (and (eq_attr "alternative" "3")
 		    (match_test "TARGET_SSE_TYPELESS_STORES"))
 		 (const_string "V8SF")
 	      ]
 	      (const_string "OI")))])
 
 (define_insn "*movti_internal"
-  [(set (match_operand:TI 0 "nonimmediate_operand" "=!r ,o ,v,v ,m")
-	(match_operand:TI 1 "general_operand"      "riFo,re,C,vm,v"))]
-  "(TARGET_64BIT || TARGET_SSE)
-   && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+  [(set (match_operand:TI 0 "nonimmediate_operand" "=!r ,o ,v ,v,v ,m")
+	(match_operand:TI 1 "general_operand"	   "riFo,re,BC,C,vm,v"))]
+  "(TARGET_64BIT
+    && !(MEM_P (operands[0]) && MEM_P (operands[1])))
+   || (TARGET_SSE
+       && nonimmediate_or_sse_const_operand (operands[1], TImode)
+       && (register_operand (operands[0], TImode)
+	   || register_operand (operands[1], TImode)))"
 {
   switch (get_attr_type (insn))
     {
@@ -2083,8 +2092,8 @@
       gcc_unreachable ();
     }
 }
-  [(set_attr "isa" "x64,x64,*,*,*")
-   (set_attr "type" "multi,multi,sselog1,ssemov,ssemov")
+  [(set_attr "isa" "x64,x64,sse2,*,*,*")
+   (set_attr "type" "multi,multi,sselog1,sselog1,ssemov,ssemov")
    (set (attr "prefix")
      (if_then_else (eq_attr "type" "sselog1,ssemov")
        (const_string "maybe_vex")
@@ -2098,7 +2107,7 @@
 	       (ior (not (match_test "TARGET_SSE2"))
 		    (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL"))
 		 (const_string "V4SF")
-	       (and (eq_attr "alternative" "4")
+	       (and (eq_attr "alternative" "5")
 		    (match_test "TARGET_SSE_TYPELESS_STORES"))
 		 (const_string "V4SF")
 	       (match_test "TARGET_AVX")
-- 
2.5.5


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