diff options
author | liuhongt <hongtao.liu@intel.com> | 2024-06-18 15:52:02 +0800 |
---|---|---|
committer | liuhongt <hongtao.liu@intel.com> | 2024-07-01 13:20:08 +0800 |
commit | 09737d9605521df9232d9990006c44955064f44e (patch) | |
tree | b04aa9f9d2e2f627cd445f09ab07ff6a31330e16 | |
parent | b06a108f0fbffe12493b527224f6e4131a72beac (diff) | |
download | gcc-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.md | 63 |
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) |