This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 2/3] Simplify wrapped binops


> While the initialization value doesn't matter (wi::add will overwrite it)
> better initialize both to false ;)  Ah, you mean because we want to
> transform only if get_range_info returned VR_RANGE.  Indeed somewhat
> unintuitive (but still the best variant for now).

> so I'm still missing a comment on why min_ovf && max_ovf is ok.
> The simple-minded would have written [...]

I suppose it's more a matter of considering too many things at the same
time for me...  I was still thinking of including more cases than
necessary for the regression.  Guess the attached version will do as
well and should not contain any more surprises.  If needed, I'll add
additional cases some time.

Tests in a followup message.

Regards
 Robin
diff --git a/gcc/match.pd b/gcc/match.pd
index 80a17ba..3acf8be 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1290,6 +1290,70 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     (if (cst && !TREE_OVERFLOW (cst))
      (plus { cst; } @0))))
 
+/* ((T)(A + CST1)) + CST2 -> (T)(A) + CST  */
+#if GIMPLE
+  (simplify
+    (plus (convert (plus@3 @0 INTEGER_CST@1)) INTEGER_CST@2)
+      (if (INTEGRAL_TYPE_P (type)
+           && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (@3)))
+       /* Combine CST1 and CST2 to CST and convert to outer type if
+          (A + CST1)'s range does not overflow.  */
+       (with
+       {
+         tree inner_type = TREE_TYPE (@3);
+         wide_int wmin0, wmax0;
+         wide_int w1 = @1;
+
+         bool ovf_undef = TYPE_OVERFLOW_UNDEFINED (inner_type);
+         bool min_ovf = true, max_ovf = true;
+
+         enum value_range_type vr0 = get_range_info (@0, &wmin0, &wmax0);
+
+         if (ovf_undef || vr0 == VR_RANGE)
+           {
+             if (!ovf_undef && vr0 == VR_RANGE)
+	       {
+		 wi::add (wmin0, w1, TYPE_SIGN (inner_type), &min_ovf);
+		 wi::add (wmax0, w1, TYPE_SIGN (inner_type), &max_ovf);
+	       }
+	     w1 = w1.from (@1, TYPE_PRECISION (type), TYPE_SIGN (inner_type));
+           }
+       }
+   (if (ovf_undef || !(min_ovf || max_ovf))
+    (plus (convert @0) { wide_int_to_tree (type, wi::add (w1, @2)); }
+     )))))
+#endif
+
+/* ((T)(A)) + CST -> (T)(A + CST)  */
+#if GIMPLE
+  (simplify
+   (plus (convert SSA_NAME@0) INTEGER_CST@1)
+    (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+         && INTEGRAL_TYPE_P (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
+      {
+        bool min_ovf = true, max_ovf = true;
+        tree inner_type = TREE_TYPE (@0);
+
+        wide_int w1 = w1.from (@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 && !max_ovf)
+      (convert (plus @0 { {wide_int_to_tree (TREE_TYPE (@0), w1)}; })))
+     )))
+#endif
+
   /* ~A + A -> -1 */
   (simplify
    (plus:c (bit_not @0) @0)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]