The following avoids translating expressions through volatile copies. Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.
PR tree-optimization/120944 * tree-ssa-sccvn.cc (vn_reference_lookup_3): Gate optimizations invalid when volatile is involved. * gcc.dg/torture/pr120944.c: New testcase. --- gcc/testsuite/gcc.dg/torture/pr120944.c | 34 +++++++++++++++++++++++++ gcc/tree-ssa-sccvn.cc | 9 +++++-- 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr120944.c diff --git a/gcc/testsuite/gcc.dg/torture/pr120944.c b/gcc/testsuite/gcc.dg/torture/pr120944.c new file mode 100644 index 00000000000..92f3c774996 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr120944.c @@ -0,0 +1,34 @@ +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ +/* { dg-additional-options "-fdump-tree-optimized" } */ + +#include <stdlib.h> + +typedef union { + int u32; + struct + { + int A:1; + int B:2; + int C:3; + }; +} u_t; + +typedef union { + volatile int u[3]; + volatile struct { + u_t a; + int b; + int c; + }; +} DATA; + +void foo (volatile DATA *d) +{ + d->a.u32 = ~0; + u_t u = d->a; + int v = u.A; + if (v) + abort(); +} + +/* { dg-final { scan-tree-dump-times "if \\\(" 1 "optimized" } } */ diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc index 9cdbf3da772..45fb79cd8a1 100644 --- a/gcc/tree-ssa-sccvn.cc +++ b/gcc/tree-ssa-sccvn.cc @@ -2809,7 +2809,8 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, we find a VN result with exactly the same value as the possible clobber. In this case we can ignore the clobber and return the found value. */ - if (is_gimple_reg_type (TREE_TYPE (lhs)) + if (!gimple_has_volatile_ops (def_stmt) + && is_gimple_reg_type (TREE_TYPE (lhs)) && types_compatible_p (TREE_TYPE (lhs), vr->type) && (ref->ref || data->orig_ref.ref) && !data->mask @@ -3093,7 +3094,8 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, else if (is_gimple_reg_type (vr->type) && gimple_assign_single_p (def_stmt) && gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR - && CONSTRUCTOR_NELTS (gimple_assign_rhs1 (def_stmt)) == 0) + && CONSTRUCTOR_NELTS (gimple_assign_rhs1 (def_stmt)) == 0 + && !TREE_THIS_VOLATILE (gimple_assign_lhs (def_stmt))) { tree base2; poly_int64 offset2, size2, maxsize2; @@ -3149,6 +3151,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, && !reverse_storage_order_for_component_p (vr->operands) && !contains_storage_order_barrier_p (vr->operands) && gimple_assign_single_p (def_stmt) + && !TREE_THIS_VOLATILE (gimple_assign_lhs (def_stmt)) && CHAR_BIT == 8 && BITS_PER_UNIT == 8 && BYTES_BIG_ENDIAN == WORDS_BIG_ENDIAN @@ -3307,6 +3310,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, && !reverse_storage_order_for_component_p (vr->operands) && !contains_storage_order_barrier_p (vr->operands) && gimple_assign_single_p (def_stmt) + && !TREE_THIS_VOLATILE (gimple_assign_lhs (def_stmt)) && TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME) { tree lhs = gimple_assign_lhs (def_stmt); @@ -3518,6 +3522,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, the copy kills ref. */ else if (data->vn_walk_kind == VN_WALKREWRITE && gimple_assign_single_p (def_stmt) + && !gimple_has_volatile_ops (def_stmt) && (DECL_P (gimple_assign_rhs1 (def_stmt)) || TREE_CODE (gimple_assign_rhs1 (def_stmt)) == MEM_REF || handled_component_p (gimple_assign_rhs1 (def_stmt)))) -- 2.43.0