]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[PATCH v3] match.pd: (A>>C) != (B>>C) -> (A^B) >= (1<<C) [PR110010]
authorDaniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Fri, 1 May 2026 20:13:51 +0000 (14:13 -0600)
committerJeff Law <jeffrey.law@oss.qualcomm.com>
Fri, 1 May 2026 20:14:40 +0000 (14:14 -0600)
Also adding the variant "(A>>C) == (B>>C) -> (A^B) < (1<<C)"

Bootstrapped on x86, aarch64 and rv64.
Regression tested on x86 and aarch64.

Changes from v2:
- add type_has_mode_precision_p () check
- add types_match() to simplify types comparison
- add rshift operand checks (must not be negative, must not
  surpass type size)
link: https://gcc.gnu.org/pipermail/gcc-patches/2026-March/711284.html
PR tree-optimization/110010

gcc/ChangeLog:

* match.pd (`(A>>C) NE|EQ (B>>C) -> (A^B) GE|LT (1<<C)`): New
pattern.

gcc/testsuite/ChangeLog:

* gcc.dg/tree-ssa/pr110010.c: New test.

gcc/match.pd
gcc/testsuite/gcc.dg/tree-ssa/pr110010.c [new file with mode: 0644]

index 62c43b31117a660636201092e7b065d8357fa408..9e450f3985fbe1914f95ab7d60d8f9458c393aca 100644 (file)
@@ -2615,6 +2615,25 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
        && tree_to_shwi (@1) < TYPE_PRECISION (TREE_TYPE (@0)))
     (eq @0 @2)))
 
+/* PR110010: (A >> C) != (B >> C) -> (A ^ B) >= (1 << C)
+   and likewise (A >> C) == (B >> C) -> (A ^ B) < (1 << C).
+
+   Note that maybe_canonicalize_comparison_1 related patterns
+   might change ">= (1 << C)" to "> (1 << C - 1)" and
+   "< (1 << C)" to "<= (1 << C - 1)".  */
+(for cmp (ne eq)
+     icmp (ge lt)
+ (simplify
+  (cmp (rshift @0 INTEGER_CST@2) (rshift @1 INTEGER_CST@2))
+   (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+       && TYPE_UNSIGNED (TREE_TYPE (@0))
+       && type_has_mode_precision_p (TREE_TYPE (@0))
+       && types_match (@0, @1)
+       && tree_fits_shwi_p (@2)
+       && tree_to_shwi (@2) > 0
+       && tree_to_shwi (@2) < TYPE_PRECISION (TREE_TYPE (@0)))
+  (icmp (bit_xor @0 @1) (lshift { build_one_cst (TREE_TYPE (@0)); } @2)))))
+
 /* Convert ~ (-A) to A - 1.  */
 (simplify
  (bit_not (convert? (negate @0)))
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr110010.c b/gcc/testsuite/gcc.dg/tree-ssa/pr110010.c
new file mode 100644 (file)
index 0000000..bda6f11
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-additional-options -O1 } */
+/* { dg-additional-options -fdump-tree-gimple } */
+#define N 5
+
+unsigned f(unsigned a, unsigned b)
+{
+  return (a>>N) != (b>>N);
+}
+
+unsigned f2(unsigned a, unsigned b)
+{
+  return (a>>N) == (b>>N);
+}
+/* { dg-final { scan-tree-dump-times " >> " 0 gimple } } */