Chromium Code Reviews| 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; | |
|
jvoung (off chromium)
2014/04/04 23:20:21
I think TargetData was renamed to DataLayout. Some
JF
2014/04/15 01:52:27
Done, in this and other files.
| |
| 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, | |
|
jvoung (off chromium)
2014/04/04 23:20:21
nit: It's not actually invalid so "Invalid" should
JF
2014/04/15 01:52:27
Done.
| |
| 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, | |
|
jvoung (off chromium)
2014/04/04 23:20:21
elemement -> element
This doesn't really force th
JF
2014/04/15 01:52:27
Correct. I don't mind doing what you suggest inste
jvoung (off chromium)
2014/04/16 00:10:27
Sure, I'm okay with leaving this as is for now, si
| |
| 66 false) | |
| 67 | |
| 68 Value *ConstantInsertExtractElementIndex::getIdx(const Instruction *I) { | |
|
jvoung (off chromium)
2014/04/04 23:20:21
Could have just been a static function that's not
JF
2014/04/15 01:52:27
Done.
| |
| 69 switch (I->getOpcode()) { | |
| 70 default: return 0; | |
|
Jim Stichnoth
2014/04/04 23:08:17
I don't know of a style guide reference, but could
JF
2014/04/15 01:52:27
Done.
| |
| 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 { | |
|
jvoung (off chromium)
2014/04/04 23:20:21
nit: BadVectorIdx sounds like it's a single index,
JF
2014/04/15 01:52:27
Done.
| |
| 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. | |
|
Jim Stichnoth
2014/04/04 23:08:17
and --> an
JF
2014/04/15 01:52:27
Done.
| |
| 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)); | |
|
Jim Stichnoth
2014/04/04 23:08:17
I trust const_cast is actually necessary :(
JF
2014/04/15 01:52:27
Yeah, I wanted to go all const-correctness, but so
| |
| 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()), | |
|
jvoung (off chromium)
2014/04/04 23:20:21
Instead of ElemTy, have the alloca be i8, and mult
jvoung (off chromium)
2014/04/07 15:40:11
n/m about this point -- it'll be handled by the Re
JF
2014/04/15 01:52:27
Yeah I wanted to do the "right" thing for LLVM, an
| |
| 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 } | |
|
Jim Stichnoth
2014/04/04 23:08:17
Sorry, these two perfectly aligned braces really b
JF
2014/04/15 01:52:27
Done, though if they *had* been required I'd have
| |
| 132 | |
| 133 I->replaceAllUsesWith(Res); | |
|
jvoung (off chromium)
2014/04/04 23:20:21
CopyDebug?
JF
2014/04/15 01:52:27
I was going to fix IRBuilder instead so it copies
| |
| 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 |