diff options
author | Roger Sayle <roger@nextmovesoftware.com> | 2022-07-09 09:02:14 +0100 |
---|---|---|
committer | Roger Sayle <roger@nextmovesoftware.com> | 2022-07-09 09:04:55 +0100 |
commit | 002d81affa8a4e625993d3c9c7840ca4aba9750c (patch) | |
tree | b5a49fd2bfb45375a80cd4f4eede7f0522a74576 | |
parent | 84ff566c63cde517c7d963a554e338531fb059f1 (diff) | |
download | gcc-002d81affa8a4e625993d3c9c7840ca4aba9750c.zip gcc-002d81affa8a4e625993d3c9c7840ca4aba9750c.tar.gz gcc-002d81affa8a4e625993d3c9c7840ca4aba9750c.tar.bz2 |
Support *testdi_not_doubleword during STV pass on x86.
This patch fixes the current two FAILs of pr65105-5.c on x86 when
compiled with -m32. These (temporary) breakages were fallout from my
patches to improve/upgrade (scalar) double word comparisons.
On mainline, the i386 backend currently represents a critical comparison
using (compare (and (not reg1) reg2) (const_int 0)) which isn't/wasn't
recognized by the STV pass' convertible_comparison_p. This simple STV
patch adds support for this pattern (*testdi_not_doubleword) and
generates the vector pandn and ptest instructions expected in the
existing (failing) test case.
2022-07-09 Roger Sayle <roger@nextmovesoftware.com>
gcc/ChangeLog
* config/i386/i386-features.cc (convert_compare): Add support
for *testdi_not_doubleword pattern, "(compare (and (not ...)))"
by generating a pandn followed by ptest.
(convertible_comparison_p): Recognize both *cmpdi_doubleword and
recent *testdi_not_doubleword comparison patterns.
-rw-r--r-- | gcc/config/i386/i386-features.cc | 53 |
1 files changed, 41 insertions, 12 deletions
diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc index be38586..a7bd172 100644 --- a/gcc/config/i386/i386-features.cc +++ b/gcc/config/i386/i386-features.cc @@ -938,10 +938,10 @@ general_scalar_chain::convert_compare (rtx op1, rtx op2, rtx_insn *insn) { rtx tmp = gen_reg_rtx (vmode); rtx src; - convert_op (&op1, insn); /* Comparison against anything other than zero, requires an XOR. */ if (op2 != const0_rtx) { + convert_op (&op1, insn); convert_op (&op2, insn); /* If both operands are MEMs, explicitly load the OP1 into TMP. */ if (MEM_P (op1) && MEM_P (op2)) @@ -953,8 +953,25 @@ general_scalar_chain::convert_compare (rtx op1, rtx op2, rtx_insn *insn) src = op1; src = gen_rtx_XOR (vmode, src, op2); } + else if (GET_CODE (op1) == AND + && GET_CODE (XEXP (op1, 0)) == NOT) + { + rtx op11 = XEXP (XEXP (op1, 0), 0); + rtx op12 = XEXP (op1, 1); + convert_op (&op11, insn); + convert_op (&op12, insn); + if (MEM_P (op11)) + { + emit_insn_before (gen_rtx_SET (tmp, op11), insn); + op11 = tmp; + } + src = gen_rtx_AND (vmode, gen_rtx_NOT (vmode, op11), op12); + } else - src = op1; + { + convert_op (&op1, insn); + src = op1; + } emit_insn_before (gen_rtx_SET (tmp, src), insn); if (vmode == V2DImode) @@ -1399,17 +1416,29 @@ convertible_comparison_p (rtx_insn *insn, enum machine_mode mode) rtx op1 = XEXP (src, 0); rtx op2 = XEXP (src, 1); - if (!CONST_INT_P (op1) - && ((!REG_P (op1) && !MEM_P (op1)) - || GET_MODE (op1) != mode)) - return false; - - if (!CONST_INT_P (op2) - && ((!REG_P (op2) && !MEM_P (op2)) - || GET_MODE (op2) != mode)) - return false; + /* *cmp<dwi>_doubleword. */ + if ((CONST_INT_P (op1) + || ((REG_P (op1) || MEM_P (op1)) + && GET_MODE (op1) == mode)) + && (CONST_INT_P (op2) + || ((REG_P (op2) || MEM_P (op2)) + && GET_MODE (op2) == mode))) + return true; + + /* *test<dwi>_not_doubleword. */ + if (op2 == const0_rtx + && GET_CODE (op1) == AND + && GET_CODE (XEXP (op1, 0)) == NOT) + { + rtx op11 = XEXP (XEXP (op1, 0), 0); + rtx op12 = XEXP (op1, 1); + return (REG_P (op11) || MEM_P (op11)) + && (REG_P (op12) || MEM_P (op12)) + && GET_MODE (op11) == mode + && GET_MODE (op12) == mode; + } - return true; + return false; } /* The general version of scalar_to_vector_candidate_p. */ |