The insn simplification expected by the test, to get a bset
instruction, has been prevented since r15-9239, because we get rotates
for bit clear and shifts for bit flip, and we don't know how to
simplify those.

Teach the rtl simplifier, at the spots where it had been extended to
handle these logical simplifications, to also handle these less
obvious negations.

Regstrapped on x86_64-linux-gnu along with other patches in this batch;
also tested with targets riscv64-elf and riscv32-elf on the same host,
both trunk and gcc-15.  Ok to install?

(I forgot to add the final question in the previous patches in this
batch; please read them as if the question was there ;-)


for  gcc/ChangeLog

        * simplify-rtx.cc (negated_ops_p): New.
        (simpify_context::simplify_binary_operation_1): Use it.
---
 gcc/simplify-rtx.cc |   55 ++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 43 insertions(+), 12 deletions(-)

diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index 72c6bbb7d6713..cb32050d8a4b7 100644
--- a/gcc/simplify-rtx.cc
+++ b/gcc/simplify-rtx.cc
@@ -3074,6 +3074,41 @@ simplify_with_subreg_not (rtx_code binop, machine_mode 
mode, rtx op0, rtx op1)
     return simplify_gen_binary (binop, mode, op0, new_not);
 }
 
+/* Return TRUE iff NOP is a negated form of OP, or vice-versa.  */
+static bool
+negated_ops_p (rtx nop, rtx op)
+{
+  /* Explicit negation.  */
+  if (GET_CODE (nop) == NOT
+      && rtx_equal_p (XEXP (nop, 0), op))
+    return true;
+  if (GET_CODE (op) == NOT
+      && rtx_equal_p (XEXP (op, 0), nop))
+    return true;
+
+  /* (~C <r A) is a negated form of (C << A) if C == 1.  */
+  if (GET_CODE (op) == ASHIFT
+      && GET_CODE (nop) == ROTATE
+      && XEXP (op, 0) == CONST1_RTX (GET_MODE (op))
+      && CONST_INT_P (XEXP (nop, 0))
+      && INTVAL (XEXP (nop, 0)) == -2
+      && rtx_equal_p (XEXP (op, 1), XEXP (nop, 1))
+      )
+    return true;
+  if (GET_CODE (nop) == ASHIFT
+      && GET_CODE (op) == ROTATE
+      && XEXP (nop, 0) == CONST1_RTX (GET_MODE (op))
+      && CONST_INT_P (XEXP (nop, 0))
+      && INTVAL (XEXP (nop, 0)) == -2
+      && rtx_equal_p (XEXP (op, 1), XEXP (nop, 1))
+      )
+    return true;
+
+  /* ??? Should we consider rotations of C and ~C by the same amount?  */
+
+  return false;
+}
+
 /* Subroutine of simplify_binary_operation.  Simplify a binary operation
    CODE with result mode MODE, operating on OP0 and OP1.  If OP0 and/or
    OP1 are constant pool references, TRUEOP0 and TRUEOP1 represent the
@@ -3861,8 +3896,7 @@ simplify_context::simplify_binary_operation_1 (rtx_code 
code,
 
       /* Convert (ior (and (not A) B) A) into A | B.  */
       if (GET_CODE (op0) == AND
-         && GET_CODE (XEXP (op0, 0)) == NOT
-         && rtx_equal_p (XEXP (XEXP (op0, 0), 0), op1))
+         && negated_ops_p (XEXP (op0, 0), op1))
        return simplify_gen_binary (IOR, mode, XEXP (op0, 1), op1);
 
       tem = simplify_with_subreg_not (code, mode, op0, op1);
@@ -4133,8 +4167,7 @@ simplify_context::simplify_binary_operation_1 (rtx_code 
code,
 
       /* Convert (xor (and (not A) B) A) into A | B.  */
       if (GET_CODE (op0) == AND
-         && GET_CODE (XEXP (op0, 0)) == NOT
-         && rtx_equal_p (XEXP (XEXP (op0, 0), 0), op1))
+         && negated_ops_p (XEXP (op0, 0), op1))
        return simplify_gen_binary (IOR, mode, XEXP (op0, 1), op1);
 
       /* Convert (xor (and (rotate (~1) A) B) (ashift 1 A))
@@ -4413,21 +4446,19 @@ simplify_context::simplify_binary_operation_1 (rtx_code 
code,
          && rtx_equal_p (op1, XEXP (XEXP (op0, 1), 0)))
        return simplify_gen_binary (AND, mode, op1, XEXP (op0, 0));
 
-      /* (and (ior/xor (X Y) (not Y)) -> X & ~Y */
+      /* (and (ior/xor X Y) (not Y)) -> X & ~Y */
       if ((GET_CODE (op0) == IOR || GET_CODE (op0) == XOR)
-         && GET_CODE (op1) == NOT
-         && rtx_equal_p (XEXP (op1, 0), XEXP (op0, 1)))
+         && negated_ops_p (op1, XEXP (op0, 1)))
        return simplify_gen_binary (AND, mode, XEXP (op0, 0),
                                    simplify_gen_unary (NOT, mode,
-                                                       XEXP (op1, 0),
+                                                       XEXP (op0, 1),
                                                        mode));
-      /* (and (ior/xor (Y X) (not Y)) -> X & ~Y */
+      /* (and (ior/xor Y X) (not Y)) -> X & ~Y */
       if ((GET_CODE (op0) == IOR || GET_CODE (op0) == XOR)
-         && GET_CODE (op1) == NOT
-         && rtx_equal_p (XEXP (op1, 0), XEXP (op0, 0)))
+         && negated_ops_p (op1, XEXP (op0, 0)))
        return simplify_gen_binary (AND, mode, XEXP (op0, 1),
                                    simplify_gen_unary (NOT, mode,
-                                                       XEXP (op1, 0),
+                                                       XEXP (op0, 0),
                                                        mode));
 
       /* Convert (and (ior A C) (ior B C)) into (ior (and A B) C).  */

-- 
Alexandre Oliva, happy hacker            https://blog.lx.oliva.nom.br/
Free Software Activist     FSFLA co-founder     GNU Toolchain Engineer
More tolerance and less prejudice are key for inclusion and diversity.
Excluding neuro-others for not behaving ""normal"" is *not* inclusive!

Reply via email to