OLD | NEW |
(Empty) | |
| 1 //===- ConstantInsertExtractElementIndex.cpp - Insert/Extract element -----===// |
| 2 // |
| 3 // The LLVM Compiler Infrastructure |
| 4 // |
| 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. |
| 7 // |
| 8 //===----------------------------------------------------------------------===// |
| 9 // |
| 10 // Transform all InsertElement and ExtractElement with non-constant or |
| 11 // out-of-bounds indices into stack accesses. This moves all undefined |
| 12 // behavior to the stack, making InsertElement and ExtractElement |
| 13 // well-defined. |
| 14 // |
| 15 //===----------------------------------------------------------------------===// |
| 16 |
| 17 #include "llvm/IR/DataLayout.h" |
| 18 #include "llvm/IR/IRBuilder.h" |
| 19 #include "llvm/IR/Instruction.h" |
| 20 #include "llvm/IR/Instructions.h" |
| 21 #include "llvm/IR/Module.h" |
| 22 #include "llvm/Pass.h" |
| 23 #include "llvm/Transforms/NaCl.h" |
| 24 |
| 25 #include <algorithm> |
| 26 |
| 27 using namespace llvm; |
| 28 |
| 29 namespace { |
| 30 class ConstantInsertExtractElementIndex : public BasicBlockPass { |
| 31 public: |
| 32 static char ID; // Pass identification, replacement for typeid |
| 33 ConstantInsertExtractElementIndex() : BasicBlockPass(ID), M(0), TD(0) { |
| 34 initializeConstantInsertExtractElementIndexPass( |
| 35 *PassRegistry::getPassRegistry()); |
| 36 } |
| 37 virtual void getAnalysisUsage(AnalysisUsage &AU) const { |
| 38 AU.addRequired<DataLayout>(); |
| 39 BasicBlockPass::getAnalysisUsage(AU); |
| 40 } |
| 41 virtual bool doInitialization(Module &Mod) { |
| 42 M = &Mod; |
| 43 return false; // Unchanged. |
| 44 } |
| 45 virtual bool runOnBasicBlock(BasicBlock &BB); |
| 46 |
| 47 private: |
| 48 typedef SmallVector<Instruction *, 8> Instructions; |
| 49 const Module *M; |
| 50 const DataLayout *TD; |
| 51 |
| 52 /// Get the index of an InsertElement or ExtractElement instruction, or null. |
| 53 static Value *getIdx(const Instruction *I); |
| 54 |
| 55 void findInvalidInsertExtractElements(const BasicBlock &BB, |
| 56 Instructions &BadVectorIdx) const; |
| 57 void fixInvalidInsertExtractElements(BasicBlock &BB, |
| 58 const Instructions &BadVectorIdx) const; |
| 59 }; |
| 60 } |
| 61 |
| 62 char ConstantInsertExtractElementIndex::ID = 0; |
| 63 INITIALIZE_PASS( |
| 64 ConstantInsertExtractElementIndex, "constant-insert-extract-element-index", |
| 65 "Force insert and extract vector elemement to always be in bounds", false, |
| 66 false) |
| 67 |
| 68 Value *ConstantInsertExtractElementIndex::getIdx(const Instruction *I) { |
| 69 switch (I->getOpcode()) { |
| 70 default: return 0; |
| 71 case Instruction::InsertElement: return I->getOperand(2); |
| 72 case Instruction::ExtractElement: return I->getOperand(1); |
| 73 } |
| 74 } |
| 75 |
| 76 void ConstantInsertExtractElementIndex::findInvalidInsertExtractElements( |
| 77 const BasicBlock &BB, Instructions &BadVectorIdx) const { |
| 78 for (BasicBlock::const_iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; |
| 79 ++BBI) { |
| 80 const Instruction *I = &*BBI; |
| 81 Value *Idx = getIdx(I); |
| 82 if (!Idx) |
| 83 // Not and InsertElement or ExtractElement, ignore the instruction. |
| 84 continue; |
| 85 if (ConstantInt *CI = dyn_cast<ConstantInt>(Idx)) { |
| 86 unsigned NumElements = |
| 87 cast<VectorType>(I->getOperand(0)->getType())->getNumElements(); |
| 88 if (CI->getValue().ult(NumElements)) |
| 89 // Index is constant in-range for the vector type, keep as-is. |
| 90 continue; |
| 91 } |
| 92 BadVectorIdx.push_back(const_cast<Instruction *>(I)); |
| 93 } |
| 94 } |
| 95 |
| 96 void ConstantInsertExtractElementIndex::fixInvalidInsertExtractElements( |
| 97 BasicBlock &BB, const Instructions &BadVectorIdx) const { |
| 98 for (Instructions::const_iterator IB = BadVectorIdx.begin(), |
| 99 IE = BadVectorIdx.end(); |
| 100 IB != IE; ++IB) { |
| 101 Instruction *I = *IB; |
| 102 Value *Vec = I->getOperand(0); |
| 103 Value *Idx = getIdx(I); |
| 104 VectorType *VecTy = cast<VectorType>(Vec->getType()); |
| 105 Type *ElemTy = VecTy->getElementType(); |
| 106 unsigned ElemAlign = TD->getPrefTypeAlignment(ElemTy); |
| 107 unsigned VecAlign = std::max(ElemAlign, TD->getPrefTypeAlignment(VecTy)); |
| 108 |
| 109 IRBuilder<> IRB(I); |
| 110 AllocaInst *Alloca = IRB.CreateAlloca( |
| 111 ElemTy, ConstantInt::get(Type::getInt32Ty(M->getContext()), |
| 112 VecTy->getNumElements())); |
| 113 Alloca->setAlignment(VecAlign); |
| 114 Value *AllocaAsVec = IRB.CreateBitCast(Alloca, VecTy->getPointerTo()); |
| 115 IRB.CreateAlignedStore(Vec, AllocaAsVec, Alloca->getAlignment()); |
| 116 Value *GEP = IRB.CreateGEP(Alloca, Idx); |
| 117 |
| 118 Value *Res; |
| 119 switch (I->getOpcode()) { |
| 120 default: |
| 121 llvm_unreachable("expected InsertElement or ExtractElement"); |
| 122 case Instruction::InsertElement: { |
| 123 IRB.CreateAlignedStore(I->getOperand(1), GEP, ElemAlign); |
| 124 Res = IRB.CreateAlignedLoad(AllocaAsVec, Alloca->getAlignment()); |
| 125 break; |
| 126 } |
| 127 case Instruction::ExtractElement: { |
| 128 Res = IRB.CreateAlignedLoad(GEP, ElemAlign); |
| 129 break; |
| 130 } |
| 131 } |
| 132 |
| 133 I->replaceAllUsesWith(Res); |
| 134 I->eraseFromParent(); |
| 135 } |
| 136 } |
| 137 |
| 138 bool ConstantInsertExtractElementIndex::runOnBasicBlock(BasicBlock &BB) { |
| 139 bool Changed = false; |
| 140 if (!TD) |
| 141 TD = &getAnalysis<DataLayout>(); |
| 142 Instructions BadVectorIdx; |
| 143 findInvalidInsertExtractElements(BB, BadVectorIdx); |
| 144 if (!BadVectorIdx.empty()) { |
| 145 Changed = true; |
| 146 fixInvalidInsertExtractElements(BB, BadVectorIdx); |
| 147 } |
| 148 return Changed; |
| 149 } |
| 150 |
| 151 BasicBlockPass *llvm::createConstantInsertExtractElementIndexPass() { |
| 152 return new ConstantInsertExtractElementIndex(); |
| 153 } |
OLD | NEW |