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