aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorliuhongt <hongtao.liu@intel.com>2024-06-18 15:52:02 +0800
committerliuhongt <hongtao.liu@intel.com>2024-07-01 13:20:08 +0800
commit09737d9605521df9232d9990006c44955064f44e (patch)
treeb04aa9f9d2e2f627cd445f09ab07ff6a31330e16
parentb06a108f0fbffe12493b527224f6e4131a72beac (diff)
downloadgcc-09737d9605521df9232d9990006c44955064f44e.zip
gcc-09737d9605521df9232d9990006c44955064f44e.tar.gz
gcc-09737d9605521df9232d9990006c44955064f44e.tar.bz2
Match IEEE min/max with UNSPEC_IEEE_{MIN,MAX}.
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.
-rw-r--r--gcc/config/i386/sse.md63
1 files changed, 63 insertions, 0 deletions
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 3d790af..694b4b8 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -3096,6 +3096,69 @@
(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)