]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
MATCH: Simplify min of clz/ctz to clz/ctz of bitwise or [PR123311] master trunk
authorEikansh Gupta <eikansh.gupta@oss.qualcomm.com>
Tue, 19 May 2026 06:50:54 +0000 (12:20 +0530)
committerEikansh Gupta <eikansh.gupta@oss.qualcomm.com>
Thu, 30 Jul 2026 08:04:16 +0000 (13:34 +0530)
This adds match.pd simplifications for min(clz(x), clz(y)) and
min(ctz(x), ctz(y)) to clz(x | y) and ctz(x | y).

Bootstrapped and tested on aarch64-linux-gnu and x86_64-linux-gnu.

PR tree-optimization/123311

gcc/ChangeLog:

* match.pd (min(clz(x), clz(y)) -> clz(x | y)): New pattern.
(min(ctz(x), ctz(y)) -> ctz(x | y)): Likewise.

gcc/testsuite/ChangeLog:

* gcc.dg/tree-ssa/pr123311-1.c: New test.
* gcc.dg/tree-ssa/pr123311-2.c: New test.

Signed-off-by: Eikansh Gupta <eikansh.gupta@oss.qualcomm.com>
gcc/match.pd
gcc/testsuite/gcc.dg/tree-ssa/pr123311-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr123311-2.c [new file with mode: 0644]

index 3658a355c40c5a92df1b3bf7254bd370f2db8530..782cfe7dc557aa3a2aef89f80f41dfef16a32b69 100644 (file)
@@ -10389,6 +10389,23 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (if (!HONOR_SIGN_DEPENDENT_ROUNDING (type) && single_use (@3))
    (IFN_COND_FMA @4 @0 @1 @2 (negate @5)))))
 
   (if (!HONOR_SIGN_DEPENDENT_ROUNDING (type) && single_use (@3))
    (IFN_COND_FMA @4 @0 @1 @2 (negate @5)))))
 
+/* min (clz (x), clz (y)) -> clz (x | y) and
+   min (ctz (x), ctz (y)) -> ctz (x | y).  */
+(for func (CLZ CTZ)
+ (simplify
+  (min (func:s @0) (func:s @1))
+  (if (types_match (@0, @1)
+       && (!sanitize_flags_p (SANITIZE_BUILTIN)
+          || (cfun && (cfun->curr_properties & PROP_ssa) != 0)))
+   (func (bit_ior @0 @1)))))
+(for func (IFN_CLZ IFN_CTZ)
+ (simplify
+  (min (func:s @0 INTEGER_CST@2) (func:s @1 @2))
+  (if (types_match (@0, @1)
+       && wi::geu_p (wi::to_wide (@2),
+                    TYPE_PRECISION (TREE_TYPE (@0))))
+   (func (bit_ior @0 @1) @2))))
+
 /* CLZ simplifications.  */
 (for clz (CLZ)
  (for op (eq ne)
 /* CLZ simplifications.  */
 (for clz (CLZ)
  (for op (eq ne)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr123311-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr123311-1.c
new file mode 100644 (file)
index 0000000..59622e5
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+#define min(x, y) ((x) < (y) ? (x) : (y))
+
+int
+f1 (unsigned int x, unsigned int y)
+{
+  return min (__builtin_ctz (x), __builtin_ctz (y));
+}
+
+int
+f2 (unsigned int x, unsigned int y)
+{
+  return min (__builtin_clz (x), __builtin_clz (y));
+}
+
+/* { dg-final { scan-tree-dump-times " \\\| " 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "__builtin_ctz|\\.CTZ" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "__builtin_clz|\\.CLZ" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-not "MIN_EXPR" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr123311-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr123311-2.c
new file mode 100644 (file)
index 0000000..0f55c32
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-additional-options "-mbmi -mlzcnt" { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-effective-target clz } */
+/* { dg-require-effective-target ctz } */
+
+#define W (__SIZEOF_INT__ * __CHAR_BIT__)
+#define min(x, y) ((x) < (y) ? (x) : (y))
+
+int
+f1 (unsigned int x, unsigned int y)
+{
+  return min (__builtin_ctzg (x, W), __builtin_ctzg (y, W));
+}
+
+int
+f2 (unsigned int x, unsigned int y)
+{
+  return min (__builtin_clzg (x, W), __builtin_clzg (y, W));
+}
+
+/* { dg-final { scan-tree-dump-times " \\\| " 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "__builtin_ctz|\\.CTZ" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "__builtin_clz|\\.CLZ" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-not "MIN_EXPR" "optimized" } } */