https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126563
--- Comment #5 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Richard Biener <[email protected]>: https://gcc.gnu.org/g:7a3878019f77ec4a41ca31ee8a09f7da6ab92470 commit r17-5023-g7a3878019f77ec4a41ca31ee8a09f7da6ab92470 Author: Richard Biener <[email protected]> Date: Fri Oct 9 12:35:52 2026 +0200 Do not strip conversions on bit test masks in ifcombine In recognize_bits_test, get_name_for_bit_test was unconditionally called on gimple_assign_rhs1 of the BIT_AND_EXPR. Because bitwise AND is commutative, rhs1 is not necessarily the name being tested; when testing a variable against a non-constant mask, rhs1 may be the mask rather than the tested value. When rhs1 was a mask defined by a single-use narrowing conversion (such as m = (int) mm), get_name_for_bit_test stripped the conversion and returned the wider variable (e.g. mm). If the subsequent matching in ifcombine_ifandif then matched the other operand with the other condition's tested variable via a commutativity swap, the stripped operand was swapped into the mask position. Because the mask had a wider type than the tested variable, ifcombine widened the tested variable (e.g. (unsigned long) y) and bitwise-ORed the masks together. This resurrected upper bits from the wider variable that had been explicitly truncated in the original program, leading to wrong code when the tested variable sign-extended into those bit positions. Fix this by having recognize_bits_test return the raw operands of the BIT_AND_EXPR. In ifcombine_ifandif, first attempt to match the operands directly under commutativity. Only if that fails, look through conversions on the two names, so that a stripped operand never becomes part of the combined mask. Looking through conversions of the names is valid for arbitrary masks since the name is truncated and the masks are zero-extended to the common type. PR tree-optimization/126563 * tree-ssa-ifcombine.cc (recognize_bits_test): Do not call get_name_for_bit_test on rhs1. (ifcombine_ifandif): Check all operands for abnormal PHIs. Look through conversions via get_name_for_bit_test on the names only when direct matching fails. * gcc.dg/tree-ssa/ssa-ifcombine-14.c: New test. * gcc.dg/tree-ssa/ssa-ifcombine-15.c: New test.
