VN currently replaces a load of a 16 byte entity 128 bits of precision (TImode) with the result of a load of a 16 byte entity with 80 bits of mode precision (XFmode). That will go downhill since if the padding bits are not actually filled with memory contents those bits are missing.
I'm conservative on the optimization side for now since I'd like to see actual testcases. The fix is likely not comprehensive either since I only touch a single place in VN. At least the fix is somewhat obvious and independent of the mode representation issue of XFmode on x86. Bootstrap and regtest running on x86_64-unknown-linux-gnu. Richard. 2020-03-12 Richard Biener <rguent...@suse.de> PR tree-optimization/94103 * tree-ssa-sccvn.c (visit_reference_op_load): Avoid type punning when the mode precision is not sufficient. * gcc.target/i386/pr94103.c: New testcase. --- gcc/testsuite/gcc.target/i386/pr94103.c | 17 +++++++++++++++++ gcc/tree-ssa-sccvn.c | 23 ++++++++++++++++------- 2 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr94103.c diff --git a/gcc/testsuite/gcc.target/i386/pr94103.c b/gcc/testsuite/gcc.target/i386/pr94103.c new file mode 100644 index 00000000000..91b5fc64b5e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr94103.c @@ -0,0 +1,17 @@ +/* { dg-do run { target lp64 } } */ +/* { dg-options "-O3" } */ + +int main() +{ + long double x; + unsigned long u[2] = {0xEEEEEEEEEEEEEEEEUL, 0xEEEEEEEEEEEEEEEEUL}; + __builtin_memcpy(&x, &u, sizeof x); + __builtin_memcpy(&u, &x, sizeof u); + ++*(unsigned char *)&x; + (void)-x; + __builtin_memcpy(&u, &x, sizeof u); + if (u[1] != 0xEEEEEEEEEEEEEEEEUL + || u[0] != 0xEEEEEEEEEEEEEEEFUL) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index b7174cd603f..150ddad3e69 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -4899,13 +4899,22 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt) if (result && !useless_type_conversion_p (TREE_TYPE (result), TREE_TYPE (op))) { - /* We will be setting the value number of lhs to the value number - of VIEW_CONVERT_EXPR <TREE_TYPE (result)> (result). - So first simplify and lookup this expression to see if it - is already available. */ - gimple_match_op res_op (gimple_match_cond::UNCOND, - VIEW_CONVERT_EXPR, TREE_TYPE (op), result); - result = vn_nary_build_or_lookup (&res_op); + /* Avoid the type punning in case the result mode has padding where + the op we lookup has not. */ + if (maybe_lt (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (result))), + GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (op))))) + result = NULL_TREE; + else + { + /* We will be setting the value number of lhs to the value number + of VIEW_CONVERT_EXPR <TREE_TYPE (result)> (result). + So first simplify and lookup this expression to see if it + is already available. */ + gimple_match_op res_op (gimple_match_cond::UNCOND, + VIEW_CONVERT_EXPR, TREE_TYPE (op), result); + result = vn_nary_build_or_lookup (&res_op); + } + /* When building the conversion fails avoid inserting the reference again. */ if (!result) -- 2.16.4