Message ID | 20240831002658.685004-2-quic_apinski@quicinc.com |
---|---|
State | New |
Headers | show |
Series | [1/2] testsuite: Change what is being tested for pr66726-2.c | expand |
> Am 31.08.2024 um 02:27 schrieb Andrew Pinski <quic_apinski@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_apinski@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 >
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
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. 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_apinski@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