On 09/06/2017 11:17 AM, Richard Henderson wrote: > On 09/06/2017 09:53 AM, Jeff Law wrote: >>> I think the easiest solution to this is for combine to notice when IOR has >>> operands with non-zero-bits that do not overlap, convert the operation to >>> ADD. >>> That allows the final two insns to fold to "addw" and the compiler need do >>> no >>> further analysis. >> I thought we had combine support for that. I don't think it's ever been >> particularly good though. With your alpha background you're probably >> more familiar with it than anyone -- IIRC it fell out of removal of low >> order bit masking to deal with alignment issues on the Alpha. > > Yes, but that would have been within AND to drop unnecessary/redundant masks. > We probably just need a few lines over in IOR to handle this case with the > same > machinery. Right. My point was most of the infrastructure ought to be in place.
> > Heh... Just having a browse shows that we currently perform exactly the > opposite transformation: > > /* If we are adding two things that have no bits in common, convert > the addition into an IOR. This will often be further simplified, > for example in cases like ((a & 1) + (a & 2)), which can > become a & 3. */ > > So managing these conflicting goals might be tricky... And I wonder how often that happens in practice. > >> I wrote some match.pd patterns to do it in gimple as part of a larger >> problem. The work as a whole on that larger problem ultimately didn't >> pan out (generated even worse code than what we have on the trunk). But >> it might be possible to resurrect those patterns and see if they are >> useful independently. My recollection was I was looking at low order >> bits only, but the concepts were general enough. > > That would be interesting, yes. So I just dug up the BZ. 59393. Sadly it was the other way around -- turning a PLUS into BIT_IOR like combine. So not helpful here. The PLUS->IOR apparently was still profitable from a codesize standpoint. But in general, I'm not sure how to select between the two forms. I guess IOR is slightly better because we know precisely what bits are potentially changed based on the constant. > >>>> $ cat rshift.c >>>> unsigned rs24(unsigned rs1) { return rs1 >> 24; } >>>> $ cat rshift.s >>>> rs24: >>>> sllw a0,a0,24 >>>> sext.w a0,a0 # redundant >>>> ret >>> >>> That seems like a missing check somewhere (combine? simplify-rtx? both?) for >>> SUBREG_PROMOTED_SIGNED_P. Since Alpha didn't have a 32-bit shift you're in >>> new >>> territory for this one. >> Yea. I'd also expect zero/nonzero bits tracking in combine to catch >> this. Shouldn't the sign bit be known to be zero after the shift which >> makes the extension redundant regardless of the SUBREG_PROMOTED flag? > > You're right, this should be irrelevant. Any anyway combine should be > constrained by modes, so it should require the SIGN_EXTEND to be present just > to make the modes match up. Perhaps this test case is being suppressed > because > of something else, e.g. failure to combine insns when a hard-reg is involved? It could well be hard register involvement. jeff