A few ideas in case you want to generalize the transformation (these are not requirements to get your patch in, and this is not a review):

On Fri, 19 Jul 2024, Eikansh Gupta wrote:

--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4321,6 +4321,32 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    @0
    @2)))

+/* min (a & CST0, a & CST1) -> a & CST0 IFF CST0 & CST1 == CST0 */
+/* max (a & CST0, a & CST1) -> a & CST0 IFF CST0 & CST1 == CST1 */
+/* If signed a, then both the constants should have same sign. */
+(for minmax (min max)
+ (simplify
+  (minmax (bit_and@3 @0 INTEGER_CST@1) (bit_and@4 @0 INTEGER_CST@2))
+   (if (TYPE_UNSIGNED (type)
+        || (tree_int_cst_sgn (@1) == tree_int_cst_sgn (@2)))
+    (with { auto andvalue = wi::to_wide (@1) & wi::to_wide (@2); }
+     (if (andvalue == ((minmax == MIN_EXPR)
+                       ? wi::to_wide (@1) : wi::to_wide (@2)))
+      @3
+      (if (andvalue == ((minmax != MIN_EXPR)
+                        ? wi::to_wide (@1) : wi::to_wide (@2)))
+       @4))))))

Since max(a&1,a&3) is a&3, I think in the signed case we could also replace max(a&N,a&3) with a&3 if N is 1 | sign-bit (i.e. -1u/2+2). Indeed, either a>=0 and a&N is a&1, or a<0 and a&N < 0 <= a&3.

+/* min (a, a & CST) --> a & CST */
+/* max (a, a & CST) --> a */
+(for minmax (min max)
+ (simplify
+  (minmax @0 (bit_and@1 @0 INTEGER_CST@2))

Why do you require that @2 be a constant?

+   (if (TYPE_UNSIGNED(type))
+    (if (minmax == MIN_EXPR)
+     @1
+     @0))))

Do we already have the corresponding transformations for comparisons?

a&b <= a --> true (if unsigned)
etc

Ideally, we would have **1** transformation for max(X,Y) that tries to fold X<=Y and if it folds to true then simplifies to Y. This way the transformations would only need to be written for comparisons, not minmax.

--
Marc Glisse

Reply via email to