https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126504
--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> --- It is not dup. We have other patterns which have this bug (why 4 of them is unclear to me). 2026-07-30 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 (); +}
