Similar like we did for cmpxchg, but extended to all
ix86_comparison_int_operator since cmpccxadd set EFLAGS exactly same
as CMP.
Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,},
Ok for trunk?
gcc/ChangeLog:
PR target/110591
* config/i386/sync.md (cmpccxadd_<mode>): Add a new
define_peephole2 after the pattern.
gcc/testsuite/ChangeLog:
* gcc.target/i386/pr110591.c: New test.
---
gcc/config/i386/sync.md | 56 ++++++++++++++++++++
gcc/testsuite/gcc.target/i386/pr110591.c | 66 ++++++++++++++++++++++++
2 files changed, 122 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/i386/pr110591.c
diff --git a/gcc/config/i386/sync.md b/gcc/config/i386/sync.md
index e1fa1504deb..43f6421bcb8 100644
--- a/gcc/config/i386/sync.md
+++ b/gcc/config/i386/sync.md
@@ -1105,3 +1105,59 @@ (define_insn "cmpccxadd_<mode>"
output_asm_insn (buf, operands);
return "";
})
+
+(define_peephole2
+ [(set (match_operand:SWI48x 0 "register_operand")
+ (match_operand:SWI48x 1 "x86_64_general_operand"))
+ (parallel [(set (match_dup 0)
+ (unspec_volatile:SWI48x
+ [(match_operand:SWI48x 2 "memory_operand")
+ (match_dup 0)
+ (match_operand:SWI48x 3 "register_operand")
+ (match_operand:SI 4 "const_int_operand")]
+ UNSPECV_CMPCCXADD))
+ (set (match_dup 2)
+ (unspec_volatile:SWI48x [(const_int 0)] UNSPECV_CMPCCXADD))
+ (clobber (reg:CC FLAGS_REG))])
+ (set (reg FLAGS_REG)
+ (compare (match_operand:SWI48x 5 "register_operand")
+ (match_operand:SWI48x 6 "x86_64_general_operand")))
+ (set (match_operand:QI 7 "nonimmediate_operand")
+ (match_operator:QI 8 "ix86_comparison_int_operator"
+ [(reg FLAGS_REG) (const_int 0)]))]
+ "TARGET_CMPCCXADD && TARGET_64BIT
+ && ((rtx_equal_p (operands[0], operands[5])
+ && rtx_equal_p (operands[1], operands[6]))
+ || ((rtx_equal_p (operands[0], operands[6])
+ && rtx_equal_p (operands[1], operands[5]))
+ && peep2_regno_dead_p (4, FLAGS_REG)))"
+ [(set (match_dup 0)
+ (match_dup 1))
+ (parallel [(set (match_dup 0)
+ (unspec_volatile:SWI48x
+ [(match_dup 2)
+ (match_dup 0)
+ (match_dup 3)
+ (match_dup 4)]
+ UNSPECV_CMPCCXADD))
+ (set (match_dup 2)
+ (unspec_volatile:SWI48x [(const_int 0)] UNSPECV_CMPCCXADD))
+ (clobber (reg:CC FLAGS_REG))])
+ (set (match_dup 7)
+ (match_op_dup 8
+ [(match_dup 9) (const_int 0)]))]
+{
+ operands[9] = gen_rtx_REG (GET_MODE (XEXP (operands[8], 0)), FLAGS_REG);
+ if (rtx_equal_p (operands[0], operands[6])
+ && rtx_equal_p (operands[1], operands[5])
+ && swap_condition (GET_CODE (operands[8])) != GET_CODE (operands[8]))
+ {
+ operands[8] = shallow_copy_rtx (operands[8]);
+ enum rtx_code ccode = swap_condition (GET_CODE (operands[8]));
+ PUT_CODE (operands[8], ccode);
+ operands[9] = gen_rtx_REG (SELECT_CC_MODE (ccode,
+ operands[6],
+ operands[5]),
+ FLAGS_REG);
+ }
+})
diff --git a/gcc/testsuite/gcc.target/i386/pr110591.c
b/gcc/testsuite/gcc.target/i386/pr110591.c
new file mode 100644
index 00000000000..32a515b429e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr110591.c
@@ -0,0 +1,66 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-mcmpccxadd -O2" } */
+/* { dg-final { scan-assembler-not {cmp[lq]?[ \t]+} } } */
+/* { dg-final { scan-assembler-times {cmpoxadd[ \t]+} 12 } } */
+
+#include <immintrin.h>
+
+_Bool foo_setg (int *ptr, int v)
+{
+ return _cmpccxadd_epi32(ptr, v, 1, _CMPCCX_O) > v;
+}
+
+_Bool foo_setl (int *ptr, int v)
+{
+ return _cmpccxadd_epi32(ptr, v, 1, _CMPCCX_O) < v;
+}
+
+_Bool foo_sete(int *ptr, int v)
+{
+ return _cmpccxadd_epi32(ptr, v, 1, _CMPCCX_O) == v;
+}
+
+_Bool foo_setne(int *ptr, int v)
+{
+ return _cmpccxadd_epi32(ptr, v, 1, _CMPCCX_O) != v;
+}
+
+_Bool foo_setge(int *ptr, int v)
+{
+ return _cmpccxadd_epi32(ptr, v, 1, _CMPCCX_O) >= v;
+}
+
+_Bool foo_setle(int *ptr, int v)
+{
+ return _cmpccxadd_epi32(ptr, v, 1, _CMPCCX_O) <= v;
+}
+
+_Bool fooq_setg (long long *ptr, long long v)
+{
+ return _cmpccxadd_epi64(ptr, v, 1, _CMPCCX_O) > v;
+}
+
+_Bool fooq_setl (long long *ptr, long long v)
+{
+ return _cmpccxadd_epi64(ptr, v, 1, _CMPCCX_O) < v;
+}
+
+_Bool fooq_sete(long long *ptr, long long v)
+{
+ return _cmpccxadd_epi64(ptr, v, 1, _CMPCCX_O) == v;
+}
+
+_Bool fooq_setne(long long *ptr, long long v)
+{
+ return _cmpccxadd_epi64(ptr, v, 1, _CMPCCX_O) != v;
+}
+
+_Bool fooq_setge(long long *ptr, long long v)
+{
+ return _cmpccxadd_epi64(ptr, v, 1, _CMPCCX_O) >= v;
+}
+
+_Bool fooq_setle(long long *ptr, long long v)
+{
+ return _cmpccxadd_epi64(ptr, v, 1, _CMPCCX_O) <= v;
+}
--
2.39.1.388.g2fc9e9ca3c