From: Andrew Pinski <apin...@marvell.com> So it turns out this is kinda of a latent bug but not really latent. In GCC 9 and 10, phi-opt would transform a?-1:0 (even for signed 1-bit integer) to -(type)a but the type is an one bit integer which means the negation is undefined. GCC 11 fixed the problem by checking for a?pow2cst:0 transformation before a?-1:0 transformation.
When I added the transformations to match.pd, I had swapped the order not paying attention and I didn't expect anything of it. Because there was no testcase failing due to this. Anyways this fixes the problem on the trunk by swapping the order in match.pd and adding a comment of why the order is this way. I will try to come up with a patch for GCC 9 and 10 series later on which fixes the problem there too. Note I didn't include the original testcase which requires the vectorizer and AVX-512f as I can't figure out the right dg options to restrict it to avx-512f but I did come up with a testcase which shows the problem and even more shows the problem with the 9/10 series as mentioned. OK? Bootstrapped and tested on x86_64-linux-gnu. PR tree-optimization/102622 gcc/ChangeLog: * match.pd: Swap the order of a?pow2cst:0 and a?-1:0 transformations. Swap the order of a?0:pow2cst and a?0:-1 transformations. gcc/testsuite/ChangeLog: * gcc.c-torture/execute/bitfld-10.c: New test. --- gcc/match.pd | 26 ++++++++++++------- .../gcc.c-torture/execute/bitfld-10.c | 24 +++++++++++++++++ 2 files changed, 41 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/bitfld-10.c diff --git a/gcc/match.pd b/gcc/match.pd index 9d7c1ac637f..c153e9a6e98 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3949,15 +3949,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* a ? 1 : 0 -> a if 0 and 1 are integral types. */ (if (integer_onep (@1)) (convert (convert:boolean_type_node @0))) - /* a ? -1 : 0 -> -a. */ - (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@1)) - (negate (convert (convert:boolean_type_node @0)))) /* a ? powerof2cst : 0 -> a << (log2(powerof2cst)) */ (if (INTEGRAL_TYPE_P (type) && integer_pow2p (@1)) (with { tree shift = build_int_cst (integer_type_node, tree_log2 (@1)); } - (lshift (convert (convert:boolean_type_node @0)) { shift; }))))) + (lshift (convert (convert:boolean_type_node @0)) { shift; }))) + /* a ? -1 : 0 -> -a. No need to check the TYPE_PRECISION not being 1 + here as the powerof2cst case above will handle that case correctly. */ + (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@1)) + (negate (convert (convert:boolean_type_node @0)))))) (if (integer_zerop (@1)) (with { tree booltrue = constant_boolean_node (true, boolean_type_node); @@ -3966,16 +3967,23 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* a ? 0 : 1 -> !a. */ (if (integer_onep (@2)) (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } ))) - /* a ? -1 : 0 -> -(!a). */ - (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@2)) - (negate (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } )))) /* a ? powerof2cst : 0 -> (!a) << (log2(powerof2cst)) */ - (if (INTEGRAL_TYPE_P (type) && integer_pow2p (@2)) + (if (INTEGRAL_TYPE_P (type) && integer_pow2p (@2) + && TYPE_PRECISION (type) != 1) (with { tree shift = build_int_cst (integer_type_node, tree_log2 (@2)); } (lshift (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } )) - { shift; })))))))) + { shift; }))) + /* a ? -1 : 0 -> -(!a). No need to check the TYPE_PRECISION not being 1 + here as the powerof2cst case above will handle that case correctly. */ + (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@2)) + (negate (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } )))) + ) + ) + ) + ) +) #endif /* Simplification moved from fold_cond_expr_with_comparison. It may also diff --git a/gcc/testsuite/gcc.c-torture/execute/bitfld-10.c b/gcc/testsuite/gcc.c-torture/execute/bitfld-10.c new file mode 100644 index 00000000000..bdbf5733ce7 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/bitfld-10.c @@ -0,0 +1,24 @@ +/* PR tree-optimization/102622 */ +/* Wrong code introduced due to phi-opt + introducing undefined signed interger overflow + with one bit signed integer negation. */ + +struct f{signed t:1;}; +int g(struct f *a, int t) __attribute__((noipa)); +int g(struct f *a, int t) +{ + if (t) + a->t = -1; + else + a->t = 0; + int t1 = a->t; + if (t1) return 1; + return t1; +} + +int main(void) +{ + struct f a; + if (!g(&a, 1)) __builtin_abort(); + return 0; +} -- 2.17.1