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: Richard Biener <richard dot guenther at gmail dot com>
- To: Robin Dapp <rdapp at linux dot vnet dot ibm dot com>
- Cc: "Bin.Cheng" <amker dot cheng at gmail dot com>, GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 20 Jun 2017 15:49:50 +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> <3bb74016-ea97-53ba-348e-51113418e37c@linux.vnet.ibm.com>
On Tue, Jun 20, 2017 at 3:08 PM, Robin Dapp <rdapp@linux.vnet.ibm.com> wrote:
>>> 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.
+ (if (TREE_CODE (type) == INTEGER_TYPE
+ && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (@3)))
+ (with
use INTEGRAL_TYPE_P.
+ bool ovf_undef = TYPE_OVERFLOW_UNDEFINED (inner_type);
+
so this is overflow behavior of the inner op.
+ /* Convert combined constant to tree of outer type if
+ there was no overflow in the original operation. */
"in the original inner operation."
you then go on and use ovf_undef also for the outer operation:
+ if (ovf_undef || vr_outer == VR_RANGE)
+ {
but you do not actually _use_ vr_outer. Do you think that if
vr_outer is a VR_RANGE then the outer operation may not
possibly have wrapped? That's a false conclusion.
But I don't see how overflow in the original outer operation matters
and the code lacks comments as to explaining that as well.
So if you have a vr0 then you can compute whether the inner
operation cannot overflow. You do this here:
+ 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));
ah, here's the use of the outer value-range. This lacks a comment
(and it looks fishy given the outer value-range is a conservative approximation
and thus could be [-INF, +INF]). Why's this not using the
wi::add overload with the overflow flag? ISTR you want to handle "negative"
unsigned constants somehow, but then I don't see how the above works.
I'd say if wmin/wmax interpreted as signed are positive and then using
a signed op to add w1 results in a still positive number you're fine
(you don't seem
to restrict the widening cast to either zero- or sign-extending).
+ if (ovf_undef || !split_range)
+ {
+ /* Extend @1 to TYPE. */
+ w1 = w1.from (w1, TYPE_PRECISION (type),
+ ovf ? SIGNED : TYPE_SIGN
(TREE_TYPE (@1)));
ideally you could always interpret w1 as signed?
+ /* Combine in outer, larger type. */
+ wide_int combined_cst;
+ combined_cst = wi::add (w1, w2);
+(if (cst)
+ (outer_op (convert @0) { cst; }))
+ )))))
bogus indent.
+/* ((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)
INTEGRAL_TYPE_P and do that first before looking at TYPE_PRECISION.
+ 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);
similar why not use wi:add overload with the overflow flag?
Btw, I find
(with
{
tree x = NULL;
if (...) x = non-NULL;
}
(if (x)
(....))))
ugly. Use
(with
{
...
}
(if (...)
(... { non-NULL } )
or sth like that which makes control flow more easily visible.
Richard.
> Regards
> Robin
>
> --
>
> gcc/ChangeLog:
>
> 2017-06-19 Robin Dapp <rdapp@linux.vnet.ibm.com>
>
> * match.pd: Simplify wrapped binary operations.