> Am 31.08.2024 um 02:27 schrieb Andrew Pinski <quic_apin...@quicinc.com>:
>
> The heurstics that was added for PR71016, try to search to see
> if the conversion was being moved away from its definition. The problem
> is the heurstics would stop if there was a non GIMPLE_ASSIGN (and already
> ignores
> debug statements) and in this case we would have a GIMPLE_LABEL that was not
> being ignored. So we should need to ignore GIMPLE_NOP, GIMPLE_LABEL and
> GIMPLE_PREDICT.
> Note this is now similar to how gimple_empty_block_p behaves.
>
> Note this fixes the wrong code that was reported by moving the VCE
> (conversion) out before
> the phiopt/match could convert it into an bit_ior and move the VCE out with
> the VCE being
> conditionally valid.
>
> Bootstrapped and tested on x86_64-linux-gnu.
> Also built and tested for aarch64-linux-gnu.
Ok, also for the testcase adjustment
Richard
> PR tree-optimization/116098
>
> gcc/ChangeLog:
>
> * tree-ssa-phiopt.cc (factor_out_conditional_operation): Ignore
> nops, labels and predicts for heuristic for conversion with a constant.
>
> gcc/testsuite/ChangeLog:
>
> * c-c++-common/torture/pr116098-1.c: New test.
> * gcc.target/aarch64/csel-1.c: New test.
>
> Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
> ---
> .../c-c++-common/torture/pr116098-1.c | 84 +++++++++++++++++++
> gcc/testsuite/gcc.target/aarch64/csel-1.c | 28 +++++++
> gcc/tree-ssa-phiopt.cc | 9 +-
> 3 files changed, 119 insertions(+), 2 deletions(-)
> create mode 100644 gcc/testsuite/c-c++-common/torture/pr116098-1.c
> create mode 100644 gcc/testsuite/gcc.target/aarch64/csel-1.c
>
> diff --git a/gcc/testsuite/c-c++-common/torture/pr116098-1.c
> b/gcc/testsuite/c-c++-common/torture/pr116098-1.c
> new file mode 100644
> index 00000000000..b9d9a342305
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/torture/pr116098-1.c
> @@ -0,0 +1,84 @@
> +/* { dg-do run } */
> +/* PR tree-optimization/116098 */
> +/* truthy was being miscompiled where the VCE was not being pulled out
> + of the if statement by factor_out_conditional_operation before the rest of
> + phiopt would happen which assumed VCE would be correct. */
> +/* The unused label was causing truthy to have different code generation
> than truthy_1. */
> +
> +
> +#ifndef __cplusplus
> +#define bool _Bool
> +#endif
> +
> +enum ValueType {
> + VALUE_BOOLEAN,
> + VALUE_NUM,
> +};
> +
> +struct Value {
> + enum ValueType type;
> + union {
> + bool boolean;
> + int num;
> + };
> +};
> +
> +static struct Value s_value;
> +static bool s_b;
> +
> +
> +bool truthy_1(void) __attribute__((noinline));
> +bool
> +truthy_1(void)
> +{
> + struct Value value = s_value;
> + if (s_b) s_b = 0;
> + enum ValueType t = value.type;
> + if (t != VALUE_BOOLEAN)
> + return 1;
> + return value.boolean;
> +}
> +bool truthy(void) __attribute__((noinline));
> +bool
> +truthy(void)
> +{
> + struct Value value = s_value;
> + if (s_b) s_b = 0;
> + enum ValueType t = value.type;
> + if (t != VALUE_BOOLEAN)
> + return 1;
> + /* This unused label should not cause any difference in code generation. */
> +a: __attribute__((unused));
> + return value.boolean;
> +}
> +
> +int
> +main(void)
> +{
> + s_b = 0;
> + s_value = (struct Value) {
> + .type = VALUE_NUM,
> + .num = 2,
> + };
> + s_value = (struct Value) {
> + .type = VALUE_BOOLEAN,
> + .boolean = !truthy_1(),
> + };
> + bool b = truthy_1();
> + if (b)
> + __builtin_abort();
> +
> + s_b = 0;
> + s_value = (struct Value) {
> + .type = VALUE_NUM,
> + .num = 2,
> + };
> + s_value = (struct Value) {
> + .type = VALUE_BOOLEAN,
> + .boolean = !truthy(),
> + };
> + b = truthy();
> + if (b)
> + __builtin_abort();
> +}
> +
> diff --git a/gcc/testsuite/gcc.target/aarch64/csel-1.c
> b/gcc/testsuite/gcc.target/aarch64/csel-1.c
> new file mode 100644
> index 00000000000..a20d39ea375
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/csel-1.c
> @@ -0,0 +1,28 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +/* These 2 functions should be the same; even though there is a label in f1.
> + The label should not make a difference in code generation.
> + There sign extend should be removed as it is not needed. */
> +void f(int t, int a, short *b)
> +{
> + short t1 = 1;
> + if (a)
> + {
> + t1 = t;
> + }
> + *b = t1;
> +}
> +
> +void f1(int t, int a, short *b)
> +{
> + short t1 = 1;
> + if (a)
> + {
> + label1: __attribute__((unused))
> + t1 = t;
> + }
> + *b = t1;
> +}
> +
> +/* { dg-final { scan-assembler-not "sxth\t" } } */
> diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
> index 9a009e187ee..271a5d51f09 100644
> --- a/gcc/tree-ssa-phiopt.cc
> +++ b/gcc/tree-ssa-phiopt.cc
> @@ -324,8 +324,13 @@ factor_out_conditional_operation (edge e0, edge e1, gphi
> *phi,
> gsi_prev_nondebug (&gsi);
> if (!gsi_end_p (gsi))
> {
> - if (gassign *assign
> - = dyn_cast <gassign *> (gsi_stmt (gsi)))
> + gimple *stmt = gsi_stmt (gsi);
> + /* Ignore nops, predicates and labels. */
> + if (gimple_code (stmt) == GIMPLE_NOP
> + || gimple_code (stmt) == GIMPLE_PREDICT
> + || gimple_code (stmt) == GIMPLE_LABEL)
> + ;
> + else if (gassign *assign = dyn_cast <gassign *> (stmt))
> {
> tree lhs = gimple_assign_lhs (assign);
> enum tree_code ass_code
> --
> 2.43.0
>