On Tue, Nov 26, 2013 at 8:00 AM, Jeff Law <l...@redhat.com> wrote: > On 11/22/13 18:43, Kai Tietz wrote: >> >> ----- Original Message ----- >> >> That is actual wished. We shouldn't come to patterns, which have more >> type-casts by this patch. >> What we see here is the normalization of shift-left/right operations. >> This patch takes care that we prefer in general (Type) (X shift-left/right >> y) over ((Type) X) shift-left/right y notation. > > > What is the rationale behind one for over the other? Or is it arbitrary? I > can easily make a case for either form based on what we're trying to > optimize. In general, it seems to me that....
When (Type) is a widening cast then you have to worry to not introduce undefined behavior when y is larger than the number of bits in X. When (Type) is a shortening cast then we lose information - because then the range we can determine for y from the shift operation will be larger. So I'm not sure I follow the reasoning to move out the casting when possible. The goal for canonicalization should be to shorten operations where possible. Thus both cases, sinking and hoisting the cast should be applied dependent on validity and whether the shift will be performed in a smaller type in the end. > If we're more interested in combining the shift with statements that define > the shift's operands, then the former is going to be a better representation > because we're typecasting the result and thus the typecast doesn't interfere > with the desired optimization. > > In contrast if we are more interested in cases where the shift defines > operands for some other statement, then the latter form is more beneficial > because we're typecasting the inputs and thus the typecast doesn't interfere > with the desired optimization. Always a trade-off which is why combining passes always have to consider casts. > Unfortunately, within a pass (or even a phase of a pass) we can have both > cases. Let's look at the code in tree-ssa-forwprop.c you're proposing we > change. > > The code in question loops over every statement and tries to combine the > current statement with the statements which define its operands, then it > moves on to the next statement in execution order. > > So your patch seems to make perfect sense when STMT is a shift. It moves > the typecast out of the way of combining STMT with the statements which > define its operands. > > However, once we move to the next statement in the IL, the shift is now > defining operands for later statements and the other form would seem to be > preferred. > > So it almost seems to me you want to apply the transformation on STMT, try > to combine into the STMT, then apply the reverse transformation on STMT if > it's safe to do so. > > That kindof implies there really isn't a perferred global form for shifts > with typecasts, but instead there is a form that is preferred based on the > optimizations we're trying to perform at any given time. It may also argue > that type promotion/demotion in general shouldn't be separate passes. I'm > still pondering that. ;) Not an easy problem. > Thoughts? I think the goal of "canonicalizing" operations to work on the smallest mode possible during early GIMPLE passes makes the most sense (even if then a cast is not always outside or inside an operation). Later (currently during RTL expansion) we can widen operations again according to target needs. Shorter operations simply carry more implicit information on value ranges (and are usually easier to vectorize for example). Richard. > Jeff > >