This is an archive of the discontinued LLVM Phabricator instance.

[x86] try harder to match bitwise 'or' into an LEA
ClosedPublic

Authored by spatel on Oct 21 2015, 1:43 PM.

Details

Summary

The motivation for this patch starts with the epic fail example in PR18007:
https://llvm.org/bugs/show_bug.cgi?id=18007

...unfortunately, this patch makes no difference for that case, but it solves some simpler cases. We'll get there some day. :)

The current 'or' matching code was using computeKnownBits() via isBaseWithConstantOffset() -> MaskedValueIsZero(), but that's an unnecessarily limited use. We can do more by copying the logic in ValueTracking's haveNoCommonBitsSet(), so we can treat the 'or' as if it was an 'add'.

An example of the better LEA matching:

leal (%rdi,%rdi), %eax
andl $1, %esi
orl %esi, %eax

Becomes:

andl $1, %esi
leal (%rsi,%rdi,2), %eax

Diff Detail

Repository
rL LLVM

Event Timeline

spatel updated this revision to Diff 38041.Oct 21 2015, 1:43 PM
spatel retitled this revision from to [x86] try harder to match bitwise 'or' into an LEA.
spatel updated this object.
spatel added reviewers: chandlerc, qcolombet, silvas.
spatel added a subscriber: llvm-commits.
kbsmith1 accepted this revision.Nov 9 2015, 11:29 AM
kbsmith1 edited edge metadata.

LGTM

This revision is now accepted and ready to land.Nov 9 2015, 11:29 AM
qcolombet accepted this revision.Nov 9 2015, 11:33 AM
qcolombet edited edge metadata.

Hi Sanjay,

LGTM.

One comment though, I believe the problem with isBaseWithConstantOffset is not the use of MaskedValueIsZero, but the fact we expect a constant to feed that mask. I wonder if it could be of general use to refactor the logic so that it is available everywhere, like isOrSameAsAdd or something.

Cheers,
-Quentin

One comment though, I believe the problem with isBaseWithConstantOffset is not the use of MaskedValueIsZero, but the fact we expect a constant to feed that mask. I wonder if it could be of general use to refactor the logic so that it is available everywhere, like isOrSameAsAdd or something.

Thanks, Kevin and Quentin. Yes, this is a good point. At the least, we should be able to share the logic with DAGCombiner. It is currently doing this:

// fold (a+b) -> (a|b) iff a and b share no bits.
if (VT.isInteger() && !VT.isVector()) {
  APInt LHSZero, LHSOne;
  APInt RHSZero, RHSOne;
  DAG.computeKnownBits(N0, LHSZero, LHSOne);

  if (LHSZero.getBoolValue()) {
    DAG.computeKnownBits(N1, RHSZero, RHSOne);

    // If all possibly-set bits on the LHS are clear on the RHS, return an OR.
    // If all possibly-set bits on the RHS are clear on the LHS, return an OR.
    if ((RHSZero & ~LHSZero) == ~LHSZero || (LHSZero & ~RHSZero) == ~RHSZero){
      if (!LegalOperations || TLI.isOperationLegal(ISD::OR, VT))
        return DAG.getNode(ISD::OR, SDLoc(N), VT, N0, N1);
    }
  }
}
This revision was automatically updated to reflect the committed changes.

For reference, I checked in the refactoring here:
http://reviews.llvm.org/rL252539

So now we have two "haveNoCommonBitsSet()" functions. We're going to kill the DAG, right? :)