> So - which case is it?  IIRC we want to handle small signed
> constants but the code can end up unsigned.  For the
> above we could write (unsigned long)((int)a + 1 - 1) and thus
> sign-extend?  Or even avoid this if we know the range.
> That is, it becomes the first case again (operation performed
> in a smaller type).

Both :) But in order to move forward the second transform suffices to
get rid of the redundant subtraction/addition of the ivopts candidate.

Attached is a new version as single file that disregards the other
possible cases (3/3 from before), only performs this transform and
checks for gimple_simplified in vrp2 after ivopts now.

Bootstrapped, no regressions on s390 and x86.

Regards
 Robin
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index a6e33833680..99ec5f34319 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -5428,8 +5428,9 @@ gfc_conv_intrinsic_findloc (gfc_se *se, gfc_expr *expr)
   tree type;
   tree tmp;
   tree found;
-  tree forward_branch;
-  tree back_branch;
+  /* Initialize here to avoid 'maybe used uninitialized'.  */
+  tree forward_branch = NULL_TREE;
+  tree back_branch = NULL_TREE;
   gfc_loopinfo loop;
   gfc_ss *arrayss;
   gfc_ss *maskss;
diff --git a/gcc/gimple-loop-versioning.cc b/gcc/gimple-loop-versioning.cc
index 8fa19488490..35344b7b448 100644
--- a/gcc/gimple-loop-versioning.cc
+++ b/gcc/gimple-loop-versioning.cc
@@ -1266,6 +1266,12 @@ loop_versioning::record_address_fragment (gimple *stmt,
 		  continue;
 		}
 	    }
+	  if (CONVERT_EXPR_CODE_P (code))
+	    {
+	      tree op1 = gimple_assign_rhs1 (assign);
+	      address->terms[i].expr = strip_casts (op1);
+	      continue;
+	    }
 	}
       i += 1;
     }
diff --git a/gcc/match.pd b/gcc/match.pd
index 0317bc704f7..22282615f84 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2020,6 +2020,37 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     (if (cst && !TREE_OVERFLOW (cst))
      (plus { cst; } @0))))
 
+/* ((T)(A)) + CST -> (T)(A + CST)  */
+#if GIMPLE
+  (simplify
+   (plus (convert SSA_NAME@0) INTEGER_CST@1)
+    (if (TREE_CODE (TREE_TYPE (@0)) == INTEGER_TYPE
+         && TREE_CODE (type) == INTEGER_TYPE
+         && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (@0))
+         && int_fits_type_p (@1, TREE_TYPE (@0)))
+     /* Perform binary operation inside the cast if the constant fits
+        and (A + CST)'s range does not overflow.  */
+     (with
+      {
+	wi::overflow_type min_ovf = wi::OVF_OVERFLOW,
+			  max_ovf = wi::OVF_OVERFLOW;
+        tree inner_type = TREE_TYPE (@0);
+
+        wide_int w1 = wide_int::from (wi::to_wide (@1), TYPE_PRECISION (inner_type),
+	    TYPE_SIGN (inner_type));
+
+        wide_int wmin0, wmax0;
+        if (get_range_info (@0, &wmin0, &wmax0) == VR_RANGE)
+          {
+            wi::add (wmin0, w1, TYPE_SIGN (inner_type), &min_ovf);
+            wi::add (wmax0, w1, TYPE_SIGN (inner_type), &max_ovf);
+          }
+      }
+     (if (min_ovf == wi::OVF_NONE && max_ovf == wi::OVF_NONE)
+      (convert (plus @0 { wide_int_to_tree (TREE_TYPE (@0), w1); } )))
+     )))
+#endif
+
   /* ~A + A -> -1 */
   (simplify
    (plus:c (bit_not @0) @0)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-5.c b/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-5.c
index 3d9940558cb..7f2e4dc2e4d 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-5.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-5.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-ch2-details" } */
+/* { dg-options "-O2 -fno-tree-ccp -fno-tree-vrp -fdump-tree-ch2-details" } */
 
 int is_sorted(int *a, int n)
 {
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-7.c b/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-7.c
index a0a6e6a9b57..58b341c392c 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-7.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-7.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-ch2-details --param logical-op-non-short-circuit=0" } */
+/* { dg-options "-O2 -fno-tree-ccp -fno-tree-vrp -fdump-tree-ch2-details --param logical-op-non-short-circuit=0" } */
 
 int is_sorted(int *a, int n, int m, int k)
 {
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-16.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-16.c
index 1bef7e7a31f..bef76e597dd 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-16.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-16.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O -fdump-tree-forwprop1" } */
+/* { dg-options "-O -fdump-tree-forwprop2" } */
 
 int foo (double xx, double xy)
 {
@@ -10,4 +10,4 @@ int foo (double xx, double xy)
   return 2;
 }
 
-/* { dg-final { scan-tree-dump "if \\\(x" "forwprop1" } } */
+/* { dg-final { scan-tree-dump "if \\\(x" "forwprop2" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-15.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-15.c
index b437518487d..dce6ad57a04 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/loop-15.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-15.c
@@ -19,7 +19,7 @@ int bla(void)
 }
 
 /* Since the loop is removed, there should be no addition.  */
-/* { dg-final { scan-tree-dump-times " \\+ " 0 "optimized" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times " \\+ " 0 "optimized" } } */
 /* { dg-final { scan-tree-dump-times " \\* " 1 "optimized" } } */
 
 /* The if from the loop header copying remains in the code.  */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23744.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23744.c
index 3385aa1e424..ba3fda352ca 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr23744.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23744.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fno-tree-ccp -fdisable-tree-evrp -fdump-tree-vrp1" } */
+/* { dg-options "-O2 -fno-tree-ccp -fdisable-tree-evrp -fdump-tree-vrp1-details" } */
 
 void h (void);
 
@@ -17,4 +17,4 @@ int g (int i, int j)
     return 1;
 }
 
-/* { dg-final { scan-tree-dump-times "Folding predicate.*to 1" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "gimple_simplified" 1 "vrp1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr52631.c b/gcc/testsuite/gcc.dg/tree-ssa/pr52631.c
index c18a5d570b4..2e99d112057 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr52631.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr52631.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fno-tree-forwprop -fdump-tree-fre1-details" } */
+/* { dg-options "-O2 -fno-tree-forwprop -fdump-tree-ccp1-details" } */
 
 unsigned f(unsigned a)
 {
@@ -12,6 +12,6 @@ unsigned f(unsigned a)
 }
 
 /* We want to verify that we replace the b & 1 with b.  */
-/* { dg-final { scan-tree-dump-times "Replaced b_\[0-9\]+ & 1 with b_\[0-9\]+ in" 1 "fre1"} } */
+/* { dg-final { scan-tree-dump-times "Match-and-simplified b_\[0-9\]+ & 1 to b_\[0-9\]+" 1 "ccp1"} } */
  
 
diff --git a/gcc/testsuite/gcc.dg/vect/vect-over-widen-23.c b/gcc/testsuite/gcc.dg/vect/vect-over-widen-23.c
index 34ce512f372..e2e0d6cb8bc 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-over-widen-23.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-over-widen-23.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-additional-options "-fno-tree-forwprop -fno-tree-vrp" }
+/* { dg-additional-options "-fno-tree-forwprop -fno-tree-vrp -fno-tree-ccp -fno-tree-copy-prop" } */
 /* { dg-require-effective-target vect_int } */
 
 #include "tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/wrapped-binop-simplify.c b/gcc/testsuite/gcc.dg/wrapped-binop-simplify.c
new file mode 100644
index 00000000000..44d85c04bfb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/wrapped-binop-simplify.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp2-details" } */
+/* { dg-final { scan-tree-dump-times "gimple_simplified to" 4 "vrp2" } } */
+
+void v1 (unsigned long *in, unsigned long *out, unsigned int n)
+{
+  int i;
+
+  for (i = 0; i < n; i++)
+  {
+    out[i] = in[i];
+  }
+}
+
+void v2 (unsigned long *in, unsigned long *out, int n)
+{
+  int i;
+
+  for (i = 0; i < n; i++)
+  {
+    out[i] = in[i];
+  }
+}
+
+void v3 (unsigned long *in, unsigned long *out, unsigned int n)
+{
+  unsigned int i;
+
+  for (i = 0; i < n; i++)
+  {
+    out[i] = in[i];
+  }
+}
+
+void v4 (unsigned long *in, unsigned long *out, int n)
+{
+  unsigned int i;
+
+  for (i = 0; i < n; i++)
+  {
+    out[i] = in[i];
+  }
+}
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index 0862f83e9a1..40621709036 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -814,7 +814,6 @@ ssa_propagation_engine::ssa_propagate (void)
   ssa_prop_fini ();
 }
 
-
 /* Return true if STMT is of the form 'mem_ref = RHS', where 'mem_ref'
    is a non-volatile pointer dereference, a structure reference or a
    reference to a single _DECL.  Ignore volatile memory references
@@ -1072,6 +1071,15 @@ substitute_and_fold_dom_walker::before_dom_children (basic_block bb)
 	  gimple_set_modified (stmt, true);
 	}
 
+      /* Also fold if we want to fold all statements.  */
+      if (!did_replace && substitute_and_fold_engine->fold_all_stmts
+	  && fold_stmt (&i, follow_single_use_edges))
+	{
+	  did_replace = true;
+	  stmt = gsi_stmt (i);
+	  gimple_set_modified (stmt, true);
+	}
+
       /* Some statements may be simplified using propagator
 	 specific information.  Do this before propagating
 	 into the stmt to not disturb pass specific information.  */
diff --git a/gcc/tree-ssa-propagate.h b/gcc/tree-ssa-propagate.h
index 81b635e0787..0606b21dbd2 100644
--- a/gcc/tree-ssa-propagate.h
+++ b/gcc/tree-ssa-propagate.h
@@ -100,6 +100,7 @@ class ssa_propagation_engine
 class substitute_and_fold_engine
 {
  public:
+  substitute_and_fold_engine () : fold_all_stmts (false) { }
   virtual ~substitute_and_fold_engine (void) { }
   virtual bool fold_stmt (gimple_stmt_iterator *) { return false; }
   virtual tree get_value (tree) { return NULL_TREE; }
@@ -107,6 +108,12 @@ class substitute_and_fold_engine
   bool substitute_and_fold (basic_block = NULL);
   bool replace_uses_in (gimple *);
   bool replace_phi_args_in (gphi *);
+
+  void set_fold_all_stmts () { fold_all_stmts = true; }
+
+  /* Users like VRP can set this when they want to perform
+     folding for every propagation.  */
+  bool fold_all_stmts;
 };
 
 #endif /* _TREE_SSA_PROPAGATE_H  */
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index e2850682da2..9328c2edaae 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -6693,6 +6693,7 @@ vrp_prop::vrp_finalize (bool warn_array_bounds_p)
     set_all_edges_as_executable (cfun);
 
   class vrp_folder vrp_folder;
+  vrp_folder.set_fold_all_stmts ();
   vrp_folder.vr_values = &vr_values;
   vrp_folder.substitute_and_fold ();
 

Reply via email to