--- /dev/null
+/* { 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();
+}
--- /dev/null
+// { 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();
+}
}
/* 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)
{
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