[committed] match.pd: Fix 2 further problems with narrow shift count types [PR126504]

Jakub Jelinek <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <amxMgIgowTLaUyti@tucnak>
Hi!

This is the same problem as in just fixed PR126476, we have patterns
which simplify something involving a shift to comparison of the shift
count against a compile time determined value.
Like in PR126476, if the shift count has a very narrow type like
unsigned _BitInt(4) in the example and we want to compare it against
something that doesn't fit into that type (like 20), then we miscompile
it as comparison against something else (like 4), even when actually
it just means that for no valid value the original will ever be true
(resp. false), depending on what comparison it is.

Now, why we have 4 very similar simplifiers is weird, sure, the first
two changed in the last PR were one left shift and one right shift
and in both cases powers of two, but here we have two others which
look very similar, especially the last one to the first one.

Bootstrapped/regtested on x86_64-linux, i686-linux, aarch64-linux
on trunk and 16 branch on x86_64-linux, i686-linux, aarch64-linux
and powerpc64le-linux, committed to trunk as obvious given the
PR126476 approval.

2026-07-31  Jakub Jelinek  <[email protected]>

	PR tree-optimization/126504
	* match.pd ((CST1 << A) == CST2 -> A == ctz (CST2) - ctz (CST1)):
	If cand isn't representable in TREE_TYPE (@1), simplify to
	cmp == NE_EXPR.
	(((1 << n) & M) != 0 -> n == log2 (M)): Don't simplify if
	log2 doesn't fit into TREE_TYPE (@0).

	* gcc.dg/torture/bitint-105.c: New test.

--- gcc/match.pd.jj	2026-07-30 18:03:24.184957827 +0200
+++ gcc/match.pd	2026-07-30 17:58:00.083878442 +0200
@@ -5296,7 +5296,9 @@ (define_operator_list SYNC_FETCH_AND_AND
   (with { int cand = wi::ctz (wi::to_wide (@2)) - wi::ctz (wi::to_wide (@0)); }
    (if (cand < 0
 	|| (!integer_zerop (@2)
-	    && wi::lshift (wi::to_wide (@0), cand) != wi::to_wide (@2)))
+	    && wi::lshift (wi::to_wide (@0), cand) != wi::to_wide (@2))
+	|| !wi::fits_to_tree_p (wi::shwi (cand, HOST_BITS_PER_INT),
+				TREE_TYPE (@1)))
     { constant_boolean_node (cmp == NE_EXPR, type); }
     (if (!integer_zerop (@2)
 	 && wi::lshift (wi::to_wide (@0), cand) == wi::to_wide (@2))
@@ -5444,8 +5446,9 @@ (define_operator_list SYNC_FETCH_AND_AND
    (bit_and
     (nop_convert? (lshift integer_onep @0)) integer_pow2p@1) integer_zerop)
   (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))
-   (icmp @0 { wide_int_to_tree (TREE_TYPE (@0),
-				wi::exact_log2 (wi::to_wide (@1))); }))))
+   (with { int c = wi::exact_log2 (wi::to_wide (@1)); }
+    (if (wi::fits_to_tree_p (wi::shwi (c, HOST_BITS_PER_INT), TREE_TYPE (@0)))
+     (icmp @0 { wide_int_to_tree (TREE_TYPE (@0), c); }))))))
 
 /* Fold (X {&,^,|} C2) << C1 into (X << C1) {&,^,|} (C2 << C1)
    (X {&,^,|} C2) >> C1 into (X >> C1) & (C2 >> C1).  */
--- gcc/testsuite/gcc.dg/torture/bitint-105.c.jj	2026-07-30 18:03:55.416580020 +0200
+++ gcc/testsuite/gcc.dg/torture/bitint-105.c	2026-07-30 18:01:55.022036419 +0200
@@ -0,0 +1,24 @@
+/* PR tree-optimization/126504 */
+/* { dg-do run { target bitint } } */
+
+typedef unsigned _BitInt(4) U;
+
+[[gnu::noipa]] int
+foo (U n)
+{
+  return ((1 << n) & (1 << 20)) != 0;
+}
+
+[[gnu::noipa]] int
+bar (U n)
+{
+  return ((unsigned) (1 << n) & (1u << 20)) != 0;
+}
+
+int
+main ()
+{
+  for (unsigned i = 0; i < 16; i++)
+    if (foo (i) || bar (i))
+      __builtin_abort ();
+}

	Jakub
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.