diff --git a/gcc/testsuite/c-c++-common/torture/pr116098-2.c b/gcc/testsuite/c-c++-common/torture/pr116098-2.c new file mode 100644 index 0000000000000000000000000000000000000000..614ed0491717b14bda1db2a9d90a2d28af8484ae --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/pr116098-2.c @@ -0,0 +1,46 @@ +/* { dg-do run } */ +/* PR tree-optimization/116098 */ + + +#include <stdbool.h> + +struct Value { + int type; + union { + bool boolean; + long long t; + }; +}; + +static struct Value s_item_mem; + +/* truthy was being miscompiled for the value.type==2 case, + because we would have a VCE from unsigned char to bool + that went from being conditional in the value.type==1 case + to unconditional when `value.type!=0`. + The move of the VCE from conditional to unconditional, + needs to changed into a convert (NOP_EXPR). */ +static bool truthy(void) __attribute__((noipa)); +static bool +truthy(void) +{ + struct Value value = s_item_mem; + if (value.type == 0) + return 0; + if (value.type == 1) + return value.boolean; + return 1; +} + +int +main(void) +{ + s_item_mem.type = 2; + s_item_mem.t = -1; + bool b1 = !truthy(); + s_item_mem.type = 1; + s_item_mem.boolean = b1; + bool b = truthy(); + if (b1 != b) __builtin_abort(); + if (b) __builtin_abort(); +} diff --git a/gcc/testsuite/g++.dg/torture/pr116098-1.C b/gcc/testsuite/g++.dg/torture/pr116098-1.C new file mode 100644 index 0000000000000000000000000000000000000000..90e44a6eeedb9273c0e134712514ef1eb66b1d9b --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr116098-1.C @@ -0,0 +1,33 @@ +// { dg-do run } +/* PR tree-optimization/116098 */ + + +static bool truthy(int type, unsigned char data) __attribute__((noipa)); +/* truthy was being miscompiled for the type==2 case, + because we would have a VCE from unsigned char to bool + that went from being conditional in the type==1 case + to unconditional when `type!=0`. + The move of the VCE from conditional to unconditional, + needs to changed into a convert (NOP_EXPR). */ + +static bool truthy(void) __attribute__((noipa)); +static bool +truthy(int type, unsigned char data) +{ + if (type == 0) + return 0; + if (type == 1) + /* Emulate what SRA does, so this can be + tested without depending on SRA. */ + return __builtin_bit_cast (bool, data); + return 1; +} + +int +main(void) +{ + bool b1 = !truthy(2, -1); + bool b = truthy(1, b1); + if (b1 != b) __builtin_abort(); + if (b) __builtin_abort(); +} diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc index bd7f9607eb9a37f773a0e4fa3f57e5fa9679f19b..43b65b362a3964f2aa9905d087871c5f93cb25ec 100644 --- a/gcc/tree-ssa-phiopt.cc +++ b/gcc/tree-ssa-phiopt.cc @@ -742,7 +742,8 @@ empty_bb_or_one_feeding_into_p (basic_block bb, } /* Move STMT to before GSI and insert its defining - name into INSERTED_EXPRS bitmap. */ + name into INSERTED_EXPRS bitmap. + Also rewrite its if it might be undefined when unconditionalized. */ static void move_stmt (gimple *stmt, gimple_stmt_iterator *gsi, auto_bitmap &inserted_exprs) { @@ -761,6 +762,31 @@ move_stmt (gimple *stmt, gimple_stmt_iterator *gsi, auto_bitmap &inserted_exprs) gimple_stmt_iterator gsi1 = gsi_for_stmt (stmt); gsi_move_before (&gsi1, gsi); reset_flow_sensitive_info (name); + + /* Rewrite some code which might be undefined when + unconditionalized. */ + if (gimple_assign_single_p (stmt)) + { + tree rhs = gimple_assign_rhs1 (stmt); + /* VCE from integral types to another integral types but with + different precisions need to be changed into casts + to be well defined when unconditional. */ + if (gimple_assign_rhs_code (stmt) == VIEW_CONVERT_EXPR + && INTEGRAL_TYPE_P (TREE_TYPE (name)) + && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (rhs, 0)))) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "rewriting stmt with maybe undefined VCE "); + print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); + } + tree new_rhs = TREE_OPERAND (rhs, 0); + gcc_assert (is_gimple_val (new_rhs)); + gimple_assign_set_rhs_code (stmt, NOP_EXPR); + gimple_assign_set_rhs1 (stmt, new_rhs); + update_stmt (stmt); + } + } } /* RAII style class to temporarily remove flow sensitive