[PATCH] match: Combine several patterns into fors.

Kael Andrew Franco <[email protected]> Tue, 4 Aug 2026 07:04:31 -0400
Newsgroups gmane.comp.gcc.patches
Message-ID <CACAb0qez1jDM=5Wcw6b6rLaGRtQLRgZJu4xi1oYJ47RkVdHMnA@mail.gmail.com>
--0000000000002560a20658369fdd
Content-Type: text/plain; charset="UTF-8"

From b4e4cff8815d171242e4df167cd8eef87cb5615d Mon Sep 17 00:00:00 2001
From: Kael Andrew Alonzo Franco <[email protected]>
Date: Mon, 3 Aug 2026 16:19:49 -0400
Subject: [PATCH] match: Combine several patterns into fors.

This reduce genmatch's outputted C++ code.

Bootstrapped and regtested on x86_64-pc-linux-gnu.

gcc/ChangeLog:

	* match.pd: Combine several patterns into fors.

Signed-off-by: Kael Andrew Franco <[email protected]>
---
 gcc/match.pd | 64 +++++++++++++++++++++++-----------------------------
 1 file changed, 28 insertions(+), 36 deletions(-)

diff --git a/gcc/match.pd b/gcc/match.pd
index 293650760e2..6763ab412c0 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1346,8 +1346,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (mult:c @0 (vec_cond (ne @0 integer_zerop) integer_zerop@2 @1))
   @2)

-/* Shifts by precision or greater result in zero.  */
 (for shift (lshift rshift)
+ /* Shifts by precision or greater result in zero.  */
  (simplify
   (shift @0 uniform_integer_cst_p@1)
   (if ((GIMPLE || !sanitize_flags_p (SANITIZE_SHIFT_EXPONENT))
@@ -1358,10 +1358,18 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
        /* Use a signed compare to leave negative shift counts alone.  */
        && wi::ges_p (wi::to_wide (uniform_integer_cst_p (@1)),
 		     element_precision (type)))
-   { build_zero_cst (type); })))
+   { build_zero_cst (type); }))
+ /* Shifts by constants distribute over several binary operations:
+    (X (<<, >>) C) & (Y (<<, >>) C) -> (X & Y) (<<, >>) C.
+    (X (<<, >>) C) | (Y (<<, >>) C) -> (X | Y) (<<, >>) C.
+    (X (<<, >>) C) ^ (Y (<<, >>) C) -> (X ^ Y) (<<, >>) C.  */
+ (for op (bit_and bit_ior bit_xor)
+  (simplify
+   (op (shift:s @0 @1) (shift:s @2 @1))
+   (if (INTEGRAL_TYPE_P (type))
+    (shift (op @0 @2) @1)))))

-/* Shifts by constants distribute over several binary operations,
-   hence (X << C) + (Y << C) can be simplified to (X + Y) << C.  */
+/* (X << C) (+,-) (Y << C) -> (X (+,-) Y) << C.  */
 (for op (plus minus)
   (simplify
     (op (lshift:s @0 @1) (lshift:s @2 @1))
@@ -1370,16 +1378,6 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 	 && !TYPE_SATURATING (type))
       (lshift (op @0 @2) @1))))

-(for op (bit_and bit_ior bit_xor)
-  (simplify
-    (op (lshift:s @0 @1) (lshift:s @2 @1))
-    (if (INTEGRAL_TYPE_P (type))
-      (lshift (op @0 @2) @1)))
-  (simplify
-    (op (rshift:s @0 @1) (rshift:s @2 @1))
-    (if (INTEGRAL_TYPE_P (type))
-      (rshift (op @0 @2) @1))))
-
 /* (y << x) == x -> false and (y << x) != x -> true when y != 0.  */
 (for cmp (eq ne)
  (simplify
@@ -1941,27 +1939,29 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (bit_xor:c (bit_ior:c @0 @1) (bit_ior:c @0 (bit_not @1)))
  (bit_not @0))

-/* (x & y) | ~(x | y) -> ~(x ^ y)
-   (x ^ y) | ~(x | y) -> ~(x & y)  */
-(for lop (bit_and bit_xor)
-     res (bit_xor bit_and)
+(for op (bit_and bit_xor)
+     rop (bit_xor bit_and)
+ /* (x & y) | ~(x | y) -> ~(x ^ y)
+    (x ^ y) | ~(x | y) -> ~(x & y)  */
+ (simplify
+  (bit_ior:c (op:s @0 @1) (bit_not:s (bit_ior:s @0 @1)))
+  (bit_not (rop @0 @1)))
+ /* (x & y) ^ (x | y) -> x ^ y
+    (x ^ y) ^ (x | y) -> x & y  */
+ (simplify
+  (bit_xor:c (op @0 @1) (bit_ior @0 @1))
+  (rop @0 @1))
+ /* (x | y) - (x & y) -> x ^ y
+    (x | y) - (x ^ y) -> x & y  */
  (simplify
-  (bit_ior:c (lop:s @0 @1) (bit_not:s (bit_ior:s @0 @1)))
-  (bit_not (res @0 @1))))
+  (minus (bit_ior @0 @1) (op @0 @1))
+  (rop @0 @1)))

 /* (~x | y) ^ (x ^ y) -> x | ~y */
 (simplify
  (bit_xor:c (bit_ior:cs (bit_not @0) @1) (bit_xor:s @0 @1))
  (bit_ior @0 (bit_not @1)))

-/* (x & y) ^ (x | y) -> x ^ y
-   (x ^ y) ^ (x | y) -> x & y  */
-(for lop (bit_and bit_xor)
-     res (bit_xor bit_and)
- (simplify
-  (bit_xor:c (lop @0 @1) (bit_ior @0 @1))
-  (res @0 @1)))
-
 /* (x & y) + (x ^ y) -> x | y */
 /* (x & y) | (x ^ y) -> x | y */
 /* (x & y) ^ (x ^ y) -> x | y */
@@ -1990,14 +1990,6 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (minus (bit_ior:cs @0 @1) @1)
  (bit_and @0 (bit_not @1)))

-/* (x | y) - (x ^ y) -> x & y
-   (x | y) - (x & y) -> x ^ y  */
-(for rop (bit_xor bit_and)
-     res (bit_and bit_xor)
- (simplify
-  (minus (bit_ior @0 @1) (rop @0 @1))
-  (res @0 @1)))
-
 /* (x | y) & ~(x & y) -> x ^ y */
 (simplify
  (bit_and:c (bit_ior @0 @1) (bit_not (bit_and @0 @1)))
-- 
2.55.0

--0000000000002560a20658369fdd
Content-Type: text/html; charset="UTF-8"

<div dir="ltr"><pre>From b4e4cff8815d171242e4df167cd8eef87cb5615d Mon Sep 17 00:00:00 2001
From: Kael Andrew Alonzo Franco &lt;<a href="mailto:[email protected]">[email protected]</a>&gt;
Date: Mon, 3 Aug 2026 16:19:49 -0400
Subject: [PATCH] match: Combine several patterns into fors.

This reduce genmatch&#39;s outputted C++ code.

Bootstrapped and regtested on x86_64-pc-linux-gnu.

gcc/ChangeLog:

	* match.pd: Combine several patterns into fors.

Signed-off-by: Kael Andrew Franco &lt;<a href="mailto:[email protected]">[email protected]</a>&gt;
---
 gcc/match.pd | 64 +++++++++++++++++++++++-----------------------------
 1 file changed, 28 insertions(+), 36 deletions(-)

diff --git a/gcc/match.pd b/gcc/match.pd
index 293650760e2..6763ab412c0 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1346,8 +1346,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (mult:c @0 (vec_cond (ne @0 integer_zerop) integer_zerop@2 @1))
   @2)
 
-/* Shifts by precision or greater result in zero.  */
 (for shift (lshift rshift)
+ /* Shifts by precision or greater result in zero.  */
  (simplify
   (shift @0 uniform_integer_cst_p@1)
   (if ((GIMPLE || !sanitize_flags_p (SANITIZE_SHIFT_EXPONENT))
@@ -1358,10 +1358,18 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
        /* Use a signed compare to leave negative shift counts alone.  */
        &amp;&amp; wi::ges_p (wi::to_wide (uniform_integer_cst_p (@1)),
 		     element_precision (type)))
-   { build_zero_cst (type); })))
+   { build_zero_cst (type); }))
+ /* Shifts by constants distribute over several binary operations:
+    (X (&lt;&lt;, &gt;&gt;) C) &amp; (Y (&lt;&lt;, &gt;&gt;) C) -&gt; (X &amp; Y) (&lt;&lt;, &gt;&gt;) C.
+    (X (&lt;&lt;, &gt;&gt;) C) | (Y (&lt;&lt;, &gt;&gt;) C) -&gt; (X | Y) (&lt;&lt;, &gt;&gt;) C.
+    (X (&lt;&lt;, &gt;&gt;) C) ^ (Y (&lt;&lt;, &gt;&gt;) C) -&gt; (X ^ Y) (&lt;&lt;, &gt;&gt;) C.  */
+ (for op (bit_and bit_ior bit_xor)
+  (simplify
+   (op (shift:s @0 @1) (shift:s @2 @1))
+   (if (INTEGRAL_TYPE_P (type))
+    (shift (op @0 @2) @1)))))
 
-/* Shifts by constants distribute over several binary operations,
-   hence (X &lt;&lt; C) + (Y &lt;&lt; C) can be simplified to (X + Y) &lt;&lt; C.  */
+/* (X &lt;&lt; C) (+,-) (Y &lt;&lt; C) -&gt; (X (+,-) Y) &lt;&lt; C.  */
 (for op (plus minus)
   (simplify
     (op (lshift:s @0 @1) (lshift:s @2 @1))
@@ -1370,16 +1378,6 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 	 &amp;&amp; !TYPE_SATURATING (type))
       (lshift (op @0 @2) @1))))
 
-(for op (bit_and bit_ior bit_xor)
-  (simplify
-    (op (lshift:s @0 @1) (lshift:s @2 @1))
-    (if (INTEGRAL_TYPE_P (type))
-      (lshift (op @0 @2) @1)))
-  (simplify
-    (op (rshift:s @0 @1) (rshift:s @2 @1))
-    (if (INTEGRAL_TYPE_P (type))
-      (rshift (op @0 @2) @1))))
-
 /* (y &lt;&lt; x) == x -&gt; false and (y &lt;&lt; x) != x -&gt; true when y != 0.  */
 (for cmp (eq ne)
  (simplify
@@ -1941,27 +1939,29 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (bit_xor:c (bit_ior:c @0 @1) (bit_ior:c @0 (bit_not @1)))
  (bit_not @0))
 
-/* (x &amp; y) | ~(x | y) -&gt; ~(x ^ y)
-   (x ^ y) | ~(x | y) -&gt; ~(x &amp; y)  */
-(for lop (bit_and bit_xor)
-     res (bit_xor bit_and)
+(for op (bit_and bit_xor)
+     rop (bit_xor bit_and)
+ /* (x &amp; y) | ~(x | y) -&gt; ~(x ^ y)
+    (x ^ y) | ~(x | y) -&gt; ~(x &amp; y)  */
+ (simplify
+  (bit_ior:c (op:s @0 @1) (bit_not:s (bit_ior:s @0 @1)))
+  (bit_not (rop @0 @1)))
+ /* (x &amp; y) ^ (x | y) -&gt; x ^ y
+    (x ^ y) ^ (x | y) -&gt; x &amp; y  */
+ (simplify
+  (bit_xor:c (op @0 @1) (bit_ior @0 @1))
+  (rop @0 @1))
+ /* (x | y) - (x &amp; y) -&gt; x ^ y
+    (x | y) - (x ^ y) -&gt; x &amp; y  */
  (simplify
-  (bit_ior:c (lop:s @0 @1) (bit_not:s (bit_ior:s @0 @1)))
-  (bit_not (res @0 @1))))
+  (minus (bit_ior @0 @1) (op @0 @1))
+  (rop @0 @1)))
 
 /* (~x | y) ^ (x ^ y) -&gt; x | ~y */
 (simplify
  (bit_xor:c (bit_ior:cs (bit_not @0) @1) (bit_xor:s @0 @1))
  (bit_ior @0 (bit_not @1)))
 
-/* (x &amp; y) ^ (x | y) -&gt; x ^ y
-   (x ^ y) ^ (x | y) -&gt; x &amp; y  */
-(for lop (bit_and bit_xor)
-     res (bit_xor bit_and)
- (simplify
-  (bit_xor:c (lop @0 @1) (bit_ior @0 @1))
-  (res @0 @1)))
-
 /* (x &amp; y) + (x ^ y) -&gt; x | y */
 /* (x &amp; y) | (x ^ y) -&gt; x | y */
 /* (x &amp; y) ^ (x ^ y) -&gt; x | y */
@@ -1990,14 +1990,6 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (minus (bit_ior:cs @0 @1) @1)
  (bit_and @0 (bit_not @1)))
 
-/* (x | y) - (x ^ y) -&gt; x &amp; y
-   (x | y) - (x &amp; y) -&gt; x ^ y  */
-(for rop (bit_xor bit_and)
-     res (bit_and bit_xor)
- (simplify
-  (minus (bit_ior @0 @1) (rop @0 @1))
-  (res @0 @1)))
-
 /* (x | y) &amp; ~(x &amp; y) -&gt; x ^ y */
 (simplify
  (bit_and:c (bit_ior @0 @1) (bit_not (bit_and @0 @1)))
-- 
2.55.0

</pre><br></div>

--0000000000002560a20658369fdd--