[gcc(refs/vendors/ibm/heads/gcc-10-branch)] tree-optimization/88240 - stopgap for floating point code-hoisting issues

Peter Bergner bergner@gcc.gnu.org
Thu Sep 3 16:40:33 GMT 2020


https://gcc.gnu.org/g:7442a775817db6065b8eed4d9d9f57611c7d09aa

commit 7442a775817db6065b8eed4d9d9f57611c7d09aa
Author: Richard Biener <rguenther@suse.de>
Date:   Tue Aug 4 14:10:45 2020 +0200

    tree-optimization/88240 - stopgap for floating point code-hoisting issues
    
    This adds a stopgap measure to avoid performing code-hoisting
    on mixed type loads when the load we'd insert in the hoisting
    position would be a floating point one.  This is because certain
    targets (hello x87) cannot perform floating point loads without
    possibly altering the bit representation and thus cannot be used
    in place of integral loads.
    
    2020-08-04  Richard Biener  <rguenther@suse.de>
    
            PR tree-optimization/88240
            * tree-ssa-sccvn.h (vn_reference_s::punned): New flag.
            * tree-ssa-sccvn.c (vn_reference_insert): Initialize punned.
            (vn_reference_insert_pieces): Likewise.
            (visit_reference_op_call): Likewise.
            (visit_reference_op_load): Track whether a ref was punned.
            * tree-ssa-pre.c (do_hoist_insertion): Refuse to perform hoist
            insertion on punned floating point loads.
    
            * gcc.target/i386/pr88240.c: New testcase.
    
    (cherry picked from commit 1af5cdd77985daf76130f527deac425c43df9f49)

Diff:
---
 gcc/testsuite/gcc.target/i386/pr88240.c | 26 ++++++++++++++++++++++++++
 gcc/tree-ssa-pre.c                      | 10 ++++++++++
 gcc/tree-ssa-sccvn.c                    | 13 ++++++++++++-
 gcc/tree-ssa-sccvn.h                    |  1 +
 4 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/gcc/testsuite/gcc.target/i386/pr88240.c b/gcc/testsuite/gcc.target/i386/pr88240.c
new file mode 100644
index 00000000000..5ee02f3193c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88240.c
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mno-sse" } */
+
+int flag;
+union { double f; unsigned long long i; } u;
+void __attribute__((noinline))
+init ()
+{
+  flag = 1;
+  u.i = 18442936822990639076ULL;
+}
+unsigned long long __attribute__((noinline))
+test ()
+{
+  if (flag)
+    return u.i;
+  else
+    return u.f;
+}
+int main()
+{
+  init ();
+  if (test () != 18442936822990639076ULL)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index fa5a81b7e43..0a94f4e3355 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -3572,6 +3572,16 @@ do_hoist_insertion (basic_block block)
 	  continue;
 	}
 
+      /* If we end up with a punned expression representation and this
+	 happens to be a float typed one give up - we can't know for
+	 sure whether all paths perform the floating-point load we are
+	 about to insert and on some targets this can cause correctness
+	 issues.  See PR88240.  */
+      if (expr->kind == REFERENCE
+	  && PRE_EXPR_REFERENCE (expr)->punned
+	  && FLOAT_TYPE_P (get_expr_type (expr)))
+	continue;
+
       /* OK, we should hoist this value.  Perform the transformation.  */
       pre_stats.hoist_insert++;
       if (dump_file && (dump_flags & TDF_DETAILS))
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 8f22cf7e6ce..78c3a0189a3 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -3590,6 +3590,7 @@ vn_reference_insert (tree op, tree result, tree vuse, tree vdef)
   vr1->vuse = vuse_ssa_val (vuse);
   vr1->operands = valueize_shared_reference_ops_from_ref (op, &tem).copy ();
   vr1->type = TREE_TYPE (op);
+  vr1->punned = 0;
   ao_ref op_ref;
   ao_ref_init (&op_ref, op);
   vr1->set = ao_ref_alias_set (&op_ref);
@@ -3649,6 +3650,7 @@ vn_reference_insert_pieces (tree vuse, alias_set_type set,
   vr1->vuse = vuse_ssa_val (vuse);
   vr1->operands = valueize_refs (operands);
   vr1->type = type;
+  vr1->punned = 0;
   vr1->set = set;
   vr1->base_set = base_set;
   vr1->hashcode = vn_reference_compute_hash (vr1);
@@ -4881,6 +4883,7 @@ visit_reference_op_call (tree lhs, gcall *stmt)
 	 them here.  */
       vr2->operands = vr1.operands.copy ();
       vr2->type = vr1.type;
+      vr2->punned = vr1.punned;
       vr2->set = vr1.set;
       vr2->base_set = vr1.base_set;
       vr2->hashcode = vr1.hashcode;
@@ -4907,10 +4910,11 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt)
   bool changed = false;
   tree last_vuse;
   tree result;
+  vn_reference_t res;
 
   last_vuse = gimple_vuse (stmt);
   result = vn_reference_lookup (op, gimple_vuse (stmt),
-				default_vn_walk_kind, NULL, true, &last_vuse);
+				default_vn_walk_kind, &res, true, &last_vuse);
 
   /* We handle type-punning through unions by value-numbering based
      on offset and size of the access.  Be prepared to handle a
@@ -4932,6 +4936,13 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt)
 	  gimple_match_op res_op (gimple_match_cond::UNCOND,
 				  VIEW_CONVERT_EXPR, TREE_TYPE (op), result);
 	  result = vn_nary_build_or_lookup (&res_op);
+	  if (result
+	      && TREE_CODE (result) == SSA_NAME
+	      && VN_INFO (result)->needs_insertion)
+	    /* Track whether this is the canonical expression for different
+	       typed loads.  We use that as a stopgap measure for code
+	       hoisting when dealing with floating point loads.  */
+	    res->punned = true;
 	}
 
       /* When building the conversion fails avoid inserting the reference
diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h
index d68e7c0ffa3..48701c32544 100644
--- a/gcc/tree-ssa-sccvn.h
+++ b/gcc/tree-ssa-sccvn.h
@@ -145,6 +145,7 @@ typedef struct vn_reference_s
   alias_set_type set;
   alias_set_type base_set;
   tree type;
+  unsigned punned : 1;
   vec<vn_reference_op_s> operands;
   tree result;
   tree result_vdef;


More information about the Gcc-cvs mailing list