http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55611



             Bug #: 55611

           Summary: Operand swapping for commutative operators

    Classification: Unclassified

           Product: gcc

           Version: 4.8.0

            Status: UNCONFIRMED

          Severity: enhancement

          Priority: P3

         Component: rtl-optimization

        AssignedTo: unassig...@gcc.gnu.org

        ReportedBy: gli...@gcc.gnu.org





Hello,



this PR is here to remember this discussion on IRC. It started because I

noticed that a patch I wrote for bug 55583 failed when the operands of | were

not given in the right order, but is a more general question about how to avoid

a combinatorial explosion of the number of patterns involving commutative

operators. Two promising directions: put a stronger priority order on rtx

(canonicalize more), or when priorities are the same and one order doesn't

match, try the other one.



<MarcG> Hello. It seems that in RTL we don't make a very strong effort to swap

operands of commutative operators, we only swap when one is obviously more

complicated than the other.

<MarcG> For things like an OR of a left shift and a right shift, are we

supposed to have 2 patterns in .md files?

<Richi> there is always a canonical form

<Richi> but I'm not sure that such combine helping pattern is really the

correct approach

<MarcG> if I compile C code (a<<2)|(b>>30) and (b>>30)|(a<<2) I don't get the

same pattern, so it isn't canonical

<Jakub> richi: in this case I believe they have the same operand priority, so

there is no canonical order

<Richi> we could of course change that

<MarcG> I wonder whether an arbitrary order would help?

<Richi> generally not, but for avoiding pattern explosion yes

<Jakub> it can't be done in commutative_operand_precedence (rtx op)

<Jakub> because it doesn't see both operands

<Richi> but we can assign a different precedence for rshift vs lshift?

<Jakub> and there are numerous commutative_operand_precedence callers, so

changing it just in swap_commutative_operands_p might not be enough

<MarcG> can't we just assign a different number to left shift, right shift,

etc? (their enum value?)

<Jakub> marcg: I'm afraid it would penalize code unnecessarily

<Jakub> marcg: the only case you want to treat specially is if one operand is

left shift and one is right shift

<Richi> jakub: I'm not sure - why dont' we want canonical form of say a<<3 | (b

+ 1) as well?

<Jakub> marcg: if you use different priority for <<, >> and the rest of binary

operations, why would you be swapping the operands?

<MarcG> I don't really see how that would penalize code.

<MatZ> Me neither.

<Jakub> marcg: it can increase register pressure or similar (or decrease of

course), it is one further thing where it changes code from what user

originally wrote unnecessarily

<MarcG> Although it might force a lot of trivial reordering in .md files, not

sure.

<MarcG> ah, I see. So maybe find a way to only _try_ it and drop it if it

doesn't help.

<MarcG> seems more complicated already :-(

<Jakub> I think what makes more sense is that the combiner if both operands of

a commutative expression have the same precedence, if the original order

doesn't match, tries also the other order

<MatZ> jakub: That's not pessimization in my book, but shuffling with unclear

effects. The solution to that problem, if it is one, is not to generally avoid

swapping operands, but instead to improve the register allocator for instance.

<Richi> jakub: that sounds reasonable

<Richi> jakub: though in general duplicates work (maybe only if RTX_CODE of the

ops is different)

<MatZ> I think canonicalization as much as possible is better.

<Richi> we can simply have a special combine variant of the precedence

<Jakub> in any case, not a 4.8 thing, if you change canonicalization, it might

take months to catch up in various backends

<Richi> thus make combine select a more canonical variant for matching patterns

<Richi> but not change the IL

<MatZ> I bet the reason it's currently not implemented is not because somebody

conciously decided that it would shuffle too much, but rather simply because

nobody bothered until now, so it seems premature caution to worry about

potential performance effects.

<MatZ> richi: Yes, we could. We could do many thing. The question is, why

should we?

<MarcG> jakub: yes, of course not for 4.8.

<Jakub> marcg: IMHO if you want something for 4.8, just duplicate the pattern,

or write it using some macro where it will match any direction of shift on

either side and in the pattern condition test that the direction is different

<MarcG> I don't want anything for 4.8, I am only interested in long term here

:-)

<MarcG> but that may still be a good idea

<MarcG> except that there is a constraint on the left shift argument being the

same as the output that breaks symmetry and complicates things...

<MarcG> anyway, I never hit that pattern myself, it was more a general question

because I had already wondered about it for other patterns in the past.

<Jakub> or not even a code iterator, you can use match_operator which would

check for logical left/right shift

<MarcG> canonicalizing still has limits. For instance, getting a canonical

order between vec_select x y for different values of y would sometimes be

convenient, but such recursive behavior can't be done by assigning a priority

number.

Reply via email to