| Index: lib/Transforms/NaCl/ExpandShuffleVector.cpp
|
| diff --git a/lib/Transforms/NaCl/ExpandShuffleVector.cpp b/lib/Transforms/NaCl/ExpandShuffleVector.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7212668216bde673deb3f9605934f515822fdf35
|
| --- /dev/null
|
| +++ b/lib/Transforms/NaCl/ExpandShuffleVector.cpp
|
| @@ -0,0 +1,110 @@
|
| +//===- ExpandShuffleVector.cpp - shufflevector to {insert/extract}element -===//
|
| +//
|
| +// The LLVM Compiler Infrastructure
|
| +//
|
| +// This file is distributed under the University of Illinois Open Source
|
| +// License. See LICENSE.TXT for details.
|
| +//
|
| +//===----------------------------------------------------------------------===//
|
| +//
|
| +// Replace all shufflevector instructions by insertelement / extractelement.
|
| +// BackendCanonicalize is able to reconstruct the shufflevector.
|
| +//
|
| +//===----------------------------------------------------------------------===//
|
| +
|
| +#include "llvm/IR/BasicBlock.h"
|
| +#include "llvm/IR/Constants.h"
|
| +#include "llvm/IR/Instruction.h"
|
| +#include "llvm/IR/Instructions.h"
|
| +#include "llvm/IR/Module.h"
|
| +#include "llvm/IR/Type.h"
|
| +#include "llvm/Pass.h"
|
| +#include "llvm/Transforms/NaCl.h"
|
| +
|
| +using namespace llvm;
|
| +
|
| +namespace {
|
| +class ExpandShuffleVector : public BasicBlockPass {
|
| +public:
|
| + static char ID; // Pass identification, replacement for typeid
|
| + ExpandShuffleVector() : BasicBlockPass(ID), M(0) {
|
| + initializeExpandShuffleVectorPass(*PassRegistry::getPassRegistry());
|
| + }
|
| + using BasicBlockPass::doInitialization;
|
| + bool doInitialization(Module &Mod) override {
|
| + M = &Mod;
|
| + return false; // Unchanged.
|
| + }
|
| + bool runOnBasicBlock(BasicBlock &BB) override;
|
| +
|
| +private:
|
| + const Module *M;
|
| + void Expand(ShuffleVectorInst *Shuf, Type *Int32);
|
| +};
|
| +}
|
| +
|
| +char ExpandShuffleVector::ID = 0;
|
| +INITIALIZE_PASS(
|
| + ExpandShuffleVector, "expand-shufflevector",
|
| + "Expand shufflevector instructions into insertelement and extractelement",
|
| + false, false)
|
| +
|
| +void ExpandShuffleVector::Expand(ShuffleVectorInst *Shuf, Type *Int32) {
|
| + Value *L = Shuf->getOperand(0);
|
| + Value *R = Shuf->getOperand(1);
|
| + assert(L->getType() == R->getType());
|
| + VectorType *SrcVecTy = cast<VectorType>(L->getType());
|
| + VectorType *DstVecTy = Shuf->getType();
|
| + Type *ElemTy = DstVecTy->getElementType();
|
| + SmallVector<int, 16> Mask = Shuf->getShuffleMask();
|
| + unsigned NumSrcElems = SrcVecTy->getNumElements();
|
| + unsigned NumDstElems = Mask.size();
|
| +
|
| + // Start with an undefined vector, extract each element from either L
|
| + // or R according to the Mask, and insert it into contiguous element
|
| + // locations in the result vector.
|
| + //
|
| + // The sources for shufflevector must have the same type but the
|
| + // destination could be a narrower or wider vector with the same
|
| + // element type.
|
| + Instruction *ExtractLoc = Shuf;
|
| + Value *Res = UndefValue::get(DstVecTy);
|
| + for (unsigned Elem = 0; Elem != NumDstElems; ++Elem) {
|
| + bool IsUndef =
|
| + 0 > Mask[Elem] || static_cast<unsigned>(Mask[Elem]) >= NumSrcElems * 2;
|
| + bool IsL = static_cast<unsigned>(Mask[Elem]) < NumSrcElems;
|
| + Value *From = IsL ? L : R;
|
| + int Adjustment = IsL ? 0 : NumSrcElems;
|
| + Constant *ExtractIdx = ConstantInt::get(Int32, Mask[Elem] - Adjustment);
|
| + Constant *InsertIdx = ConstantInt::get(Int32, Elem);
|
| + Value *ElemToInsert = IsUndef ? UndefValue::get(ElemTy)
|
| + : (Value *)ExtractElementInst::Create(
|
| + From, ExtractIdx, "", ExtractLoc);
|
| + Res = InsertElementInst::Create(Res, ElemToInsert, InsertIdx, "", Shuf);
|
| + if (ExtractLoc == Shuf)
|
| + // All the extracts should be added just before the first insert we added.
|
| + ExtractLoc = cast<Instruction>(Res);
|
| + }
|
| +
|
| + Shuf->replaceAllUsesWith(Res);
|
| + Shuf->eraseFromParent();
|
| +}
|
| +
|
| +bool ExpandShuffleVector::runOnBasicBlock(BasicBlock &BB) {
|
| + Type *Int32 = Type::getInt32Ty(M->getContext());
|
| + typedef SmallVector<ShuffleVectorInst *, 8> Instructions;
|
| + Instructions Shufs;
|
| +
|
| + for (BasicBlock::iterator BBI = BB.begin(); BBI != BB.end(); ++BBI)
|
| + if (ShuffleVectorInst *S = dyn_cast<ShuffleVectorInst>(&*BBI))
|
| + Shufs.push_back(S);
|
| +
|
| + for (Instructions::iterator S = Shufs.begin(), E = Shufs.end(); S != E; ++S)
|
| + Expand(*S, Int32);
|
| +
|
| + return !Shufs.empty();
|
| +}
|
| +
|
| +BasicBlockPass *llvm::createExpandShuffleVectorPass() {
|
| + return new ExpandShuffleVector();
|
| +}
|
|
|