This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH 2/3] Simplify wrapped binops
- From: Robin Dapp <rdapp at linux dot vnet dot ibm dot com>
- To: "Bin.Cheng" <amker dot cheng at gmail dot com>
- Cc: Richard Biener <richard dot guenther at gmail dot com>, GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 20 Jun 2017 15:08:24 +0200
- Subject: Re: [PATCH 2/3] Simplify wrapped binops
- Authentication-results: sourceware.org; auth=none
- References: <5790A709.4060804@linux.vnet.ibm.com> <CAFiYyc0gnMe7j+DgTeudnpH-zD22nK7Cuv4a2zj4Va-anApTBA@mail.gmail.com> <27be603c-4499-ca96-f252-40934d3e420d@linux.vnet.ibm.com> <CAFiYyc1s699beSC9bpDGxY_2ppenDLoP3nbjYSnThF1cp2YHDA@mail.gmail.com> <d6e24bfd-fc3e-4160-fe27-db3eda5b857c@linux.vnet.ibm.com> <CAFiYyc1AcFG8JzoO3LYW9iyGsPj+7Kv17weZp+U3vTaeiqdhKA@mail.gmail.com> <260c4925-29e2-d50a-871e-397e2f9f4efb@linux.vnet.ibm.com> <CAFiYyc2_WX+3vzX27iRO9byK4zoc8N43F-d=Cg2xXoHwLRTgGQ@mail.gmail.com> <CAHFci299r3v3jbaZn0pzKPmk+yvF=Hwnbq+hxYGJCz-y8Qx0jg@mail.gmail.com> <803f5629-2a68-db02-a3a1-16fbe656f242@linux.vnet.ibm.com> <CAHFci2-zFEjPa4TokPca8EDF4zM5PU+0B8maFKa189=Pyrcj7Q@mail.gmail.com> <57eda9e0-8fbb-7508-f41e-d98000314012@linux.vnet.ibm.com> <CAHFci2-VJu5SbWzm43uozxRq2L=4Sxp0L573y-vPeK69RX_iaA@mail.gmail.com> <bb91b7d9-2d8d-72af-1741-bb5d97e64466@linux.vnet.ibm.com> <CAHFci2_GZb1k9DSrX1MR2ZUSLFQRxxAhRr4ywkfv0_PUrzn0VQ@mail.gmail.com>
>> Currently, extract_... () does that all that for me, is it really too
>> expensive to call? I guess, using get_range_info first and calling
>> extract when get_range_info returns a VR_RANGE is not really a favorable
>> thing to do either? :)
> Not only the cost, we should avoid introducing more interfaces while
> old ones can do the work. Anyway, it's Richard's call here.
I rewrote the match.pd patterns to use get_range_info () now, keeping
track of an "ok" overflow (both min and max overflow) and one which does
not allow us to continue (min xor max overflow, split/anti range). Test
suite on s390x has no regressions, bootstrap is ok, x86 running.
Regards
Robin
--
gcc/ChangeLog:
2017-06-19 Robin Dapp <rdapp@linux.vnet.ibm.com>
* match.pd: Simplify wrapped binary operations.
diff --git a/gcc/match.pd b/gcc/match.pd
index 80a17ba..66c37f6 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1290,6 +1290,128 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (cst && !TREE_OVERFLOW (cst))
(plus { cst; } @0))))
+/* ((T)(A +- CST)) +- CST -> (T)(A) +- CST) */
+#if GIMPLE
+ (for outer_op (plus minus)
+ (for inner_op (plus minus)
+ (simplify
+ (outer_op (convert (inner_op@3 @0 INTEGER_CST@1)) INTEGER_CST@2)
+ (if (TREE_CODE (type) == INTEGER_TYPE
+ && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (@3)))
+ (with
+ {
+ tree cst = NULL_TREE;
+ tree inner_type = TREE_TYPE (@3);
+ wide_int wmin, wmax;
+ wide_int wmin0, wmax0;
+
+ bool ovf = true;
+ bool ovf_undef = TYPE_OVERFLOW_UNDEFINED (inner_type);
+
+ enum value_range_type vr_outer =
+ get_range_info (@3, &wmin, &wmax);
+ enum value_range_type vr0 =
+ get_range_info (@0, &wmin0, &wmax0);
+
+ /* Convert combined constant to tree of outer type if
+ there was no overflow in the original operation. */
+ if (ovf_undef || vr_outer == VR_RANGE)
+ {
+ wide_int w1 = @1;
+ wide_int w2 = @2;
+
+ if (ovf_undef || vr0 == VR_RANGE)
+ {
+ if (inner_op == MINUS_EXPR)
+ w1 = wi::neg (w1);
+
+ if (outer_op == MINUS_EXPR)
+ w2 = wi::neg (w2);
+
+ bool split_range = true;
+
+ if (!ovf_undef && vr0 == VR_RANGE)
+ {
+ int max_ovf = 0;
+ int min_ovf = 0;
+
+ signop sgn = TYPE_SIGN (inner_type);
+
+ wmin = wi::add (wmin0, w1);
+ min_ovf = wi::cmp (wmin, w1, sgn) < 0;
+
+ wmax = wi::add (wmax0, w1);
+ max_ovf = wi::cmp (wmax, w1, sgn) < 0;
+
+ ovf = min_ovf || max_ovf;
+
+ split_range = ((min_ovf && !max_ovf)
+ || (!min_ovf && max_ovf));
+ }
+
+ if (ovf_undef || !split_range)
+ {
+ /* Extend @1 to TYPE. */
+ w1 = w1.from (w1, TYPE_PRECISION (type),
+ ovf ? SIGNED : TYPE_SIGN (TREE_TYPE (@1)));
+
+ /* Combine in outer, larger type. */
+ wide_int combined_cst;
+ combined_cst = wi::add (w1, w2);
+
+ cst = wide_int_to_tree (type, combined_cst);
+ }
+ }
+ }
+ }
+(if (cst)
+ (outer_op (convert @0) { cst; }))
+ )))))
+#endif
+
+/* ((T)(A)) +- CST -> (T)(A +- CST) */
+#if GIMPLE
+ (for outer_op (plus minus)
+ (simplify
+ (outer_op (convert SSA_NAME@0) INTEGER_CST@2)
+ (if (TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (@0))
+ && TREE_CODE (TREE_TYPE (@0)) == INTEGER_TYPE
+ && TREE_CODE (type) == INTEGER_TYPE)
+ /* Perform binary operation inside the cast if the constant fits
+ and there is no overflow. */
+ (with
+ {
+ bool split_range = true;
+ tree cst_inner = NULL_TREE;
+ enum value_range_type vr = VR_VARYING;
+ tree inner_type = TREE_TYPE (@0);
+
+ if (int_fits_type_p (@2, inner_type))
+ {
+ cst_inner = fold_convert (inner_type, @2);
+
+ wide_int wmin0, wmax0;
+ wide_int w1 = cst_inner;
+ signop sgn = TYPE_SIGN (inner_type);
+ vr = get_range_info (@0, &wmin0, &wmax0);
+
+ if (vr == VR_RANGE)
+ {
+ wide_int wmin = wi::add (wmin0, w1);
+ bool min_ovf = wi::cmp (wmin, w1, sgn) < 0;
+
+ wide_int wmax = wi::add (wmax0, w1);
+ bool max_ovf = wi::cmp (wmax, w1, sgn) < 0;
+
+ split_range = (min_ovf && !max_ovf) || (!min_ovf && max_ovf);
+ }
+ }
+ }
+ (if (cst_inner && !split_range)
+ (convert (outer_op @0 { cst_inner; })))
+ ))))
+#endif
+
/* ~A + A -> -1 */
(simplify
(plus:c (bit_not @0) @0)