[PATCH] X86: sink splat-shuffle into block doing a shift.

Nadav Rotem nrotem at apple.com
Mon Feb 17 08:39:31 PST 2014


  Hi Tim!

  Thanks for working on this. I think that your approach makes sense. Did you look at the AVX512 instruction set?

   A few comments below:

  +bool X86TargetLowering::isVariableVectorShiftExpensive(Type *Ty) const {
  +  // Before SSE2 there are no vector shift instructions that LLVM can use, so it
  +  // doesn't particularly matter either way whether a shift is variable or not.
  +  if (!Subtarget->hasSSE2())
  +    return false;
  +
  +  // With SSE2 and above, there are no 8-bit shifts by vector or scalar: don't
  +  // take special steps.
  +  unsigned Bits = Ty->getScalarSizeInBits();
  +  if (Bits == 8)
  +    return false;
  +
  +  // SSE2 introduced vector-shift-by-scalar instructions (e.g psllw), but before
  +  // AVX2 there were no variable shift instructions so it's worth sinking splat
  +  // shuffles so they're visible to CodeGen.
  +  if (!Subtarget->hasInt256())
  +    return true;
  +
  +  // With AVX2 there are 32-bit and 64-bit variable shifts so they're not
  +  // expensive. 8-bit shifts were handled above, leaving 16-bit shifts. It turns
  +  // out scalar is still preferable there.
  +  return Bits == 16;
  +}
  +


  I think we can handle the 8bit and 16bit together.  I would just write this long function like this:

  bool X86TargetLowering::isVariableVectorShiftExpensive(Type *Ty) const {
   if (Subtarget->hasInt256() && (Bits == 32 || Bits == 64))
     return false;

    return true;
  }


  This can be extracted into a helper function - isBroadcast / isSplat.

  +  SmallVector<int, 16> Mask(SVI->getShuffleMask());
  +  int SplatElem = -1;
  +  for (unsigned i = 0; i < Mask.size(); ++i) {
  +    if (SplatElem != -1 && Mask[i] != -1 && Mask[i] != SplatElem)
  +      return false;
  +    SplatElem = Mask[i];
  +  }


  Do we really need this check?  Won’t SelectionDAG CSE it for us?

  +  // InsertedShuffles - Only insert a shuffle in each block once.
  +  DenseMap<BasicBlock*, Instruction*> InsertedShuffles;
  +
  +  bool MadeChange = false;
  +  for (Value::use_iterator UI = SVI->use_begin(), E = SVI->use_end();
  +       UI != E; ++UI) {
  +    Instruction *User = cast<Instruction>(*UI);

  Won’t SDAG do it for us?

  +  // If we removed all uses, nuke the shuffle.
  +  if (SVI->use_empty()) {
  +    SVI->eraseFromParent();
  +    MadeChange = true;
  +  }

http://llvm-reviews.chandlerc.com/D2816



More information about the llvm-commits mailing list