This is an archive of the discontinued LLVM Phabricator instance.

[X86 isel] Fix permute mask calculation in lowerShuffleAsUNPCKAndPermute
ClosedPublic

Authored by zhuhan0 on Apr 20 2023, 2:33 PM.

Details

Summary

This fixes issue 62242

This code block can potentially swap the order of V1 and V2 in Ops and therefore
also in the unpck instruction generated.

SDValue &Op = Ops[Elt & 1];
if (M < NumElts && (Op.isUndef() || Op == V1))
    Op = V1;
else if (NumElts <= M && (Op.isUndef() || Op == V2)) {
    Op = V2;
    NormM -= NumElts;
} else
    return SDValue();

But the permute mask is calculated assuming the first operand being V1 and
second V2, therefore causing a mis-compile.

First check if the input operands are swapped, and then calculate the permute
mask based on that.

Diff Detail

Event Timeline

zhuhan0 created this revision.Apr 20 2023, 2:33 PM
Herald added a project: Restricted Project. · View Herald TranscriptApr 20 2023, 2:33 PM
zhuhan0 requested review of this revision.Apr 20 2023, 2:33 PM
Herald added a project: Restricted Project. · View Herald TranscriptApr 20 2023, 2:33 PM

Chaging the permute mask calculation based on whether V1 and V2 are swapped could be troublesome

I'm not sure I follow why you think this could be a problem?

llvm/lib/Target/X86/X86ISelLowering.cpp
13352

We're going to see regressions from this, because by forcing the V1/V2 unpack order we lose any chance of making use of a better shuffles by V2/V1

Chaging the permute mask calculation based on whether V1 and V2 are swapped could be troublesome

I'm not sure I follow why you think this could be a problem?

Just thought the code would be ugly. Nothing major. I'll look into this since the current fix is introducing a regression.

llvm/lib/Target/X86/X86ISelLowering.cpp
13352

I see. Curious how does the order of the operands affect the quality of generated shuffles? Is it with optimization purpose to set the ops like this SDValue &Op = Ops[Elt & 1];?

zhuhan0 updated this revision to Diff 515856.Apr 21 2023, 11:38 AM

Modify permute mask instead.

zhuhan0 retitled this revision from [X86 isel] Fix operand ordering in lowerShuffleAsUNPCKAndPermute to [X86 isel] Fix permute mask calculation in lowerShuffleAsUNPCKAndPermute.Apr 21 2023, 11:39 AM
zhuhan0 edited the summary of this revision. (Show Details)

Looks like ef38880 also introduced some miscompiles in the vector-interleaved* tests. With this change, the tests have been reverted to pre-ef38880 version.

zhuhan0 updated this revision to Diff 515864.Apr 21 2023, 11:53 AM

Use isInRange.

RKSimon added inline comments.Apr 22 2023, 3:19 AM
llvm/lib/Target/X86/X86ISelLowering.cpp
13349

Is the OpsSwapped logic necessary?

for (int Elt = 0; Elt != NumElts; ++Elt) {
  int M = Mask[Elt];
  if (M < 0)
    continue;
  int NormM = M;
  if (NumElts <= M)
    NormM -= NumElts;
  bool IsFirstOp = M < NumElts;
  int BaseMaskElt =
      NumLaneElts * (NormM / NumLaneElts) + (2 * (NormM % NumHalfLaneElts));
  if ((IsFirstOp && V1 == Ops[0]) || (!IsFirstOp && V2 == Ops[0]))
    PermuteMask[Elt] = BaseMaskElt;
  else if if ((IsFirstOp && V1 == Ops[1]) || (!IsFirstOp && V2 == Ops[1]))
    PermuteMask[Elt] = BaseMaskElt + 1;
}

I think there probably needs to be an assertion there as well someplace.

zhuhan0 updated this revision to Diff 516487.Apr 24 2023, 12:00 PM

Address comment.

RKSimon accepted this revision.Apr 24 2023, 12:43 PM

LGTM - cheers

This revision is now accepted and ready to land.Apr 24 2023, 12:43 PM