diff mbox series

[3/7,x86] Match IEEE min/max with UNSPEC_IEEE_{MIN,MAX}.

Message ID 20240627082307.1166985-4-hongtao.liu@intel.com
State New
Headers show
Series Remove vcond{,u,eq}<mode> expanders. | expand

Commit Message

liuhongt June 27, 2024, 8:23 a.m. UTC
These versions of the min/max patterns implement exactly the operations
   min = (op1 < op2 ? op1 : op2)
   max = (!(op1 < op2) ? op1 : op2)

gcc/ChangeLog:
	PR target/115517
	* config/i386/sse.md (*minmax<mode>3_1): New pre_reload
	define_insn_and_split.
	(*minmax<mode>3_2): Ditto.
---
 gcc/config/i386/sse.md | 63 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)
diff mbox series

Patch

diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 822159a869b..92f8b74999f 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -3064,6 +3064,69 @@  (define_insn "*<code><mode>3<mask_name><round_saeonly_name>"
    (set_attr "prefix" "<mask_prefix3>")
    (set_attr "mode" "<MODE>")])
 
+(define_insn_and_split "*minmax<mode>3_1"
+  [(set (match_operand:VFH 0 "register_operand")
+	(vec_merge:VFH
+	  (match_operand:VFH 1 "nonimmediate_operand")
+	  (match_operand:VFH 2 "nonimmediate_operand")
+	  (unspec:<avx512fmaskmode>
+	    [(match_operand:VFH 3 "nonimmediate_operand")
+	     (match_operand:VFH 4 "nonimmediate_operand")
+	     (match_operand:SI 5 "const_0_to_31_operand")]
+	     UNSPEC_PCMP)))]
+  "TARGET_SSE && ix86_pre_reload_split ()
+   && ((rtx_equal_p (operands[1], operands[3])
+	&& rtx_equal_p (operands[2], operands[4]))
+       || (rtx_equal_p (operands[1], operands[4])
+	   && rtx_equal_p (operands[2], operands[3])))
+   && (INTVAL (operands[5]) == 1 || INTVAL (operands[5]) == 14)"
+   "#"
+   "&& 1"
+   [(const_int 0)]
+ {
+   int u = UNSPEC_IEEE_MIN;
+   if ((INTVAL (operands[5]) == 1 && rtx_equal_p (operands[1], operands[4]))
+	|| (INTVAL (operands[5]) == 14 && rtx_equal_p (operands[1], operands[3])))
+     u = UNSPEC_IEEE_MAX;
+
+   if (MEM_P (operands[1]))
+     operands[1] = force_reg (<MODE>mode, operands[1]);
+   rtvec v = gen_rtvec (2, operands[1], operands[2]);
+   rtx tmp = gen_rtx_UNSPEC (<MODE>mode, v, u);
+   emit_move_insn (operands[0], tmp);
+   DONE;
+ })
+
+(define_insn_and_split "*minmax<mode>3_2"
+  [(set (match_operand:VF_128_256 0 "register_operand")
+	(unspec:VF_128_256
+	  [(match_operand:VF_128_256 1 "nonimmediate_operand")
+	   (match_operand:VF_128_256 2 "nonimmediate_operand")
+	   (lt:VF_128_256
+	     (match_operand:VF_128_256 3 "nonimmediate_operand")
+	     (match_operand:VF_128_256 4 "nonimmediate_operand"))]
+	     UNSPEC_BLENDV))]
+  "TARGET_SSE && ix86_pre_reload_split ()
+   && ((rtx_equal_p (operands[1], operands[3])
+	&& rtx_equal_p (operands[2], operands[4]))
+       || (rtx_equal_p (operands[1], operands[4])
+	   && rtx_equal_p (operands[2], operands[3])))"
+   "#"
+   "&& 1"
+   [(const_int 0)]
+ {
+   int u = UNSPEC_IEEE_MIN;
+   if (rtx_equal_p (operands[1], operands[3]))
+     u = UNSPEC_IEEE_MAX;
+
+   if (MEM_P (operands[2]))
+     force_reg (<MODE>mode, operands[2]);
+   rtvec v = gen_rtvec (2, operands[2], operands[1]);
+   rtx tmp = gen_rtx_UNSPEC (<MODE>mode, v, u);
+   emit_move_insn (operands[0], tmp);
+   DONE;
+ })
+
 ;; These versions of the min/max patterns implement exactly the operations
 ;;   min = (op1 < op2 ? op1 : op2)
 ;;   max = (!(op1 < op2) ? op1 : op2)