[gcc/devel/gccgo] Fix availability compute during VN DOM elimination

Ian Lance Taylor ian@gcc.gnu.org
Sun Jul 12 18:00:08 GMT 2020


https://gcc.gnu.org/g:2b42509f8b7bdf0a27a6687a941663380b485416

commit 2b42509f8b7bdf0a27a6687a941663380b485416
Author: Richard Biener <rguenther@suse.de>
Date:   Fri May 8 10:24:37 2020 +0200

    Fix availability compute during VN DOM elimination
    
    This fixes an issue with redundant store elimination in FRE/PRE
    which, when invoked by the DOM elimination walk, ends up using
    possibly stale availability data from the RPO walk.  It also
    fixes a missed optimization during valueization of addresses
    by making sure to use get_addr_base_and_unit_offset_1 which can
    valueize and adjusting that to also valueize ARRAY_REFs low-bound.
    
    2020-05-08  Richard Biener  <rguenther@suse.de>
    
            * tree-ssa-sccvn.c (rpo_avail): Change type to
            eliminate_dom_walker *.
            (eliminate_with_rpo_vn): Adjust rpo_avail to make vn_valueize
            use the DOM walker availability.
            (vn_reference_fold_indirect): Use get_addr_base_and_unit_offset_1
            with vn_valueize as valueization callback.
            (vn_reference_maybe_forwprop_address): Likewise.
            * tree-dfa.c (get_addr_base_and_unit_offset_1): Also valueize
            array_ref_low_bound.
    
            * gnat.dg/opt83.adb: New testcase.

Diff:
---
 gcc/ChangeLog                   | 12 ++++++++++++
 gcc/testsuite/ChangeLog         |  4 ++++
 gcc/testsuite/gnat.dg/opt83.adb | 33 +++++++++++++++++++++++++++++++++
 gcc/tree-dfa.c                  | 32 +++++++++++++++++---------------
 gcc/tree-ssa-sccvn.c            | 15 ++++++++++-----
 5 files changed, 76 insertions(+), 20 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5373046116c..14605950a8b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2020-05-08  Richard Biener  <rguenther@suse.de>
+
+	* tree-ssa-sccvn.c (rpo_avail): Change type to
+	eliminate_dom_walker *.
+	(eliminate_with_rpo_vn): Adjust rpo_avail to make vn_valueize
+	use the DOM walker availability.
+	(vn_reference_fold_indirect): Use get_addr_base_and_unit_offset_1
+	with vn_valueize as valueization callback.
+	(vn_reference_maybe_forwprop_address): Likewise.
+	* tree-dfa.c (get_addr_base_and_unit_offset_1): Also valueize
+	array_ref_low_bound.
+
 2020-05-08  Jakub Jelinek  <jakub@redhat.com>
 
 	PR tree-optimization/94786
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b95696f0f19..adacf69b027 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2020-05-08  Richard Biener  <rguenther@suse.de>
+
+	* gnat.dg/opt83.adb: New testcase.
+
 2020-05-08  Jakub Jelinek  <jakub@redhat.com>
 
 	PR tree-optimization/94786
diff --git a/gcc/testsuite/gnat.dg/opt83.adb b/gcc/testsuite/gnat.dg/opt83.adb
new file mode 100644
index 00000000000..d71672f622c
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt83.adb
@@ -0,0 +1,33 @@
+--  { dg-do compile }
+--  { dg-options "-O2" }
+
+--  rpo fre3 used to loop indefinitely replacing _2 with _8 and back,
+--  given MEM[(struct test__e &)_2][0]{lb: _7 sz: 16}._tag = A23s_29;
+--  and an earlier _8 = &*_2[0]{lb: _7 sz: 16}.
+
+procedure Opt83 is
+
+   type E is tagged record
+      I : Natural := 0;
+   end record;
+
+   type A is array (Natural range <>) of aliased E;
+
+   F : E;
+
+   R : access A;
+
+   procedure N is
+   begin
+      if R = null then
+        R := new A (0 .. 4);
+      end if;
+   end N;
+
+begin
+
+   N;
+
+   R (0) := F;
+
+end Opt83;
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
index b6edc5c1352..3283d113f9b 100644
--- a/gcc/tree-dfa.c
+++ b/gcc/tree-dfa.c
@@ -806,23 +806,25 @@ get_addr_base_and_unit_offset_1 (tree exp, poly_int64_pod *poffset,
 	    if (valueize
 		&& TREE_CODE (index) == SSA_NAME)
 	      index = (*valueize) (index);
+	    if (!poly_int_tree_p (index))
+	      return NULL_TREE;
+	    low_bound = array_ref_low_bound (exp);
+	    if (valueize
+		&& TREE_CODE (low_bound) == SSA_NAME)
+	      low_bound = (*valueize) (low_bound);
+	    if (!poly_int_tree_p (low_bound))
+	      return NULL_TREE;
+	    unit_size = array_ref_element_size (exp);
+	    if (TREE_CODE (unit_size) != INTEGER_CST)
+	      return NULL_TREE;
 
 	    /* If the resulting bit-offset is constant, track it.  */
-	    if (poly_int_tree_p (index)
-		&& (low_bound = array_ref_low_bound (exp),
-		    poly_int_tree_p (low_bound))
-		&& (unit_size = array_ref_element_size (exp),
-		    TREE_CODE (unit_size) == INTEGER_CST))
-	      {
-		poly_offset_int woffset
-		  = wi::sext (wi::to_poly_offset (index)
-			      - wi::to_poly_offset (low_bound),
-			      TYPE_PRECISION (TREE_TYPE (index)));
-		woffset *= wi::to_offset (unit_size);
-		byte_offset += woffset.force_shwi ();
-	      }
-	    else
-	      return NULL_TREE;
+	    poly_offset_int woffset
+		= wi::sext (wi::to_poly_offset (index)
+			    - wi::to_poly_offset (low_bound),
+			    TYPE_PRECISION (TREE_TYPE (index)));
+	    woffset *= wi::to_offset (unit_size);
+	    byte_offset += woffset.force_shwi ();
 	  }
 	  break;
 
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 8a4af91c54e..39e99007c7e 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -1224,8 +1224,8 @@ vn_reference_fold_indirect (vec<vn_reference_op_s> *ops,
   /* The only thing we have to do is from &OBJ.foo.bar add the offset
      from .foo.bar to the preceding MEM_REF offset and replace the
      address with &OBJ.  */
-  addr_base = get_addr_base_and_unit_offset (TREE_OPERAND (op->op0, 0),
-					     &addr_offset);
+  addr_base = get_addr_base_and_unit_offset_1 (TREE_OPERAND (op->op0, 0),
+					       &addr_offset, vn_valueize);
   gcc_checking_assert (addr_base && TREE_CODE (addr_base) != MEM_REF);
   if (addr_base != TREE_OPERAND (op->op0, 0))
     {
@@ -1282,8 +1282,9 @@ vn_reference_maybe_forwprop_address (vec<vn_reference_op_s> *ops,
 	  poly_int64 addr_offset;
 
 	  addr = gimple_assign_rhs1 (def_stmt);
-	  addr_base = get_addr_base_and_unit_offset (TREE_OPERAND (addr, 0),
-						     &addr_offset);
+	  addr_base = get_addr_base_and_unit_offset_1 (TREE_OPERAND (addr, 0),
+						       &addr_offset,
+						       vn_valueize);
 	  /* If that didn't work because the address isn't invariant propagate
 	     the reference tree from the address operation in case the current
 	     dereference isn't offsetted.  */
@@ -2419,7 +2420,7 @@ public:
 };
 
 /* Global RPO state for access from hooks.  */
-static rpo_elim *rpo_avail;
+static eliminate_dom_walker *rpo_avail;
 basic_block vn_context_bb;
 
 /* Return true if BASE1 and BASE2 can be adjusted so they have the
@@ -6559,7 +6560,11 @@ eliminate_with_rpo_vn (bitmap inserted_exprs)
 {
   eliminate_dom_walker walker (CDI_DOMINATORS, inserted_exprs);
 
+  eliminate_dom_walker *saved_rpo_avail = rpo_avail;
+  rpo_avail = &walker;
   walker.walk (cfun->cfg->x_entry_block_ptr);
+  rpo_avail = saved_rpo_avail;
+
   return walker.eliminate_cleanup ();
 }


More information about the Gcc-cvs mailing list