diff mbox series

tree-optimization/94103 avoid CSE of loads with padding

Message ID nycvar.YFH.7.76.2003120916340.5137@zhemvz.fhfr.qr
State New
Headers show
Series tree-optimization/94103 avoid CSE of loads with padding | expand

Commit Message

Richard Biener March 12, 2020, 8:18 a.m. UTC
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  <rguenther@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 mbox series

Patch

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)