https://gcc.gnu.org/g:cc2aaa9ac0d31f8f4098c4276e0695afb7f63fcf
commit cc2aaa9ac0d31f8f4098c4276e0695afb7f63fcf Author: Alexandre Oliva <ol...@gnu.org> Date: Sun Jan 12 22:16:21 2025 -0300 [ifcombine] propagate signbit mask to xor right-hand operand Diff: --- gcc/gimple-fold.cc | 20 ++++++++++++++++ gcc/testsuite/gcc.dg/field-merge-20.c | 44 +++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index a3987c4590ae..93ed8b3abb05 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -8270,6 +8270,16 @@ fold_truth_andor_for_ifcombine (enum tree_code code, tree truth_type, ll_and_mask = sign; else ll_and_mask &= sign; + if (l_xor) + { + if (!lr_and_mask.get_precision ()) + lr_and_mask = sign; + else + lr_and_mask &= sign; + if (l_const.get_precision ()) + l_const &= wide_int::from (lr_and_mask, + l_const.get_precision (), UNSIGNED); + } } if (rsignbit) @@ -8279,6 +8289,16 @@ fold_truth_andor_for_ifcombine (enum tree_code code, tree truth_type, rl_and_mask = sign; else rl_and_mask &= sign; + if (r_xor) + { + if (!rr_and_mask.get_precision ()) + rr_and_mask = sign; + else + rr_and_mask &= sign; + if (r_const.get_precision ()) + r_const &= wide_int::from (rr_and_mask, + r_const.get_precision (), UNSIGNED); + } } /* If either comparison code is not correct for our logical operation, diff --git a/gcc/testsuite/gcc.dg/field-merge-20.c b/gcc/testsuite/gcc.dg/field-merge-20.c new file mode 100644 index 000000000000..3c1ec0cbd80f --- /dev/null +++ b/gcc/testsuite/gcc.dg/field-merge-20.c @@ -0,0 +1,44 @@ +/* { dg-do run } */ +/* { dg-options "-O1" } */ + +/* tree-optimization/118409 */ + +/* Check that tests involving a sign bit of a storage unit are handled + correctly. The compares are turned into xor tests by earlier passes, and ifcombine has to propagate the sign bit mask to the right hand of the compare extracted from the */ + +typedef struct { + int p : __CHAR_BIT__; + int d : 1; + int b : __CHAR_BIT__ - 2; + int e : 1; + int f; +} g; + +g a = {.d = 1, .e = 1}, c = {.b = 1, .d = 1, .e = 1}; + +__attribute__((noipa)) +int f1 () +{ + if (a.d == c.d + && a.e == c.e + && a.f == 0) + return 0; + return -1; +} + +__attribute__((noipa)) +int f2 () +{ + if (a.d != c.d + || a.e != c.e + || a.f != 0) + return -1; + return 0; +} + +int main() { + if (f1 () < 0 + || f2 () < 0) + __builtin_abort(); + return 0; +}