blob: 7c1c88004be28df9395a94eebcf703bb2b559945 [file] [log] [blame]
//==- ExpandInsertExtractElement.cpp - Expand vector insert and extract -=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===------------------------------------------------------------------===//
//
// This pass expands insertelement and extractelement instructions with
// variable indices, which SIMD.js doesn't natively support yet.
//
//===------------------------------------------------------------------===//
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Transforms/NaCl.h"
#include "llvm/Transforms/Utils/Local.h"
#include <map>
#include <vector>
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
namespace {
class ExpandInsertExtractElement : public FunctionPass {
bool Changed;
public:
static char ID;
ExpandInsertExtractElement() : FunctionPass(ID) {
initializeExpandInsertExtractElementPass(*PassRegistry::getPassRegistry());
}
bool runOnFunction(Function &F) override;
};
}
char ExpandInsertExtractElement::ID = 0;
INITIALIZE_PASS(ExpandInsertExtractElement, "expand-insert-extract-elements",
"Expand and lower insert and extract element operations",
false, false)
// Utilities
bool ExpandInsertExtractElement::runOnFunction(Function &F) {
Changed = false;
Instruction *Entry = &*F.getEntryBlock().begin();
Type *Int32 = Type::getInt32Ty(F.getContext());
Constant *Zero = ConstantInt::get(Int32, 0);
for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ) {
Instruction *Inst = &*I++;
if (InsertElementInst *III = dyn_cast<InsertElementInst>(Inst)) {
if (isa<ConstantInt>(III->getOperand(2)))
continue;
Type *AllocaTy = III->getType();
Instruction *A = new AllocaInst(AllocaTy, 0, "", Entry);
CopyDebug(new StoreInst(III->getOperand(0), A, III), III);
Value *Idxs[] = { Zero, III->getOperand(2) };
Instruction *B = CopyDebug(
GetElementPtrInst::Create(AllocaTy, A, Idxs, "", III), III);
CopyDebug(new StoreInst(III->getOperand(1), B, III), III);
Instruction *L = CopyDebug(new LoadInst(A, "", III), III);
III->replaceAllUsesWith(L);
III->eraseFromParent();
} else if (ExtractElementInst *EII = dyn_cast<ExtractElementInst>(Inst)) {
if (isa<ConstantInt>(EII->getOperand(1)))
continue;
Type *AllocaTy = EII->getOperand(0)->getType();
Instruction *A = new AllocaInst(AllocaTy, 0, "", Entry);
CopyDebug(new StoreInst(EII->getOperand(0), A, EII), EII);
Value *Idxs[] = { Zero, EII->getOperand(1) };
Instruction *B = CopyDebug(
GetElementPtrInst::Create(AllocaTy, A, Idxs, "", EII), EII);
Instruction *L = CopyDebug(new LoadInst(B, "", EII), EII);
EII->replaceAllUsesWith(L);
EII->eraseFromParent();
}
}
return Changed;
}
FunctionPass *llvm::createExpandInsertExtractElementPass() {
return new ExpandInsertExtractElement();
}