[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