Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: lib/Transforms/NaCl/ConstantInsertExtractElementIndex.cpp

Issue 939073008: Rebased PNaCl localmods in LLVM to 223109 (Closed)
Patch Set: undo localmod Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 either in-bounds constant accesses or
12 // stack accesses. This moves all undefined behavior to the stack,
13 // making InsertElement and ExtractElement 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), DL(0) {
34 initializeConstantInsertExtractElementIndexPass(
35 *PassRegistry::getPassRegistry());
36 }
37 void getAnalysisUsage(AnalysisUsage &AU) const override {
38 AU.addRequired<DataLayoutPass>();
39 BasicBlockPass::getAnalysisUsage(AU);
40 }
41 using BasicBlockPass::doInitialization;
42 bool doInitialization(Module &Mod) override {
43 M = &Mod;
44 return false; // Unchanged.
45 }
46 bool runOnBasicBlock(BasicBlock &BB) override;
47
48 private:
49 typedef SmallVector<Instruction *, 8> Instructions;
50 const Module *M;
51 const DataLayout *DL;
52
53 void findNonConstantInsertExtractElements(
54 const BasicBlock &BB, Instructions &OutOfRangeConstantIndices,
55 Instructions &NonConstantVectorIndices) const;
56 void fixOutOfRangeConstantIndices(BasicBlock &BB,
57 const Instructions &Instrs) const;
58 void fixNonConstantVectorIndices(BasicBlock &BB,
59 const Instructions &Instrs) const;
60 };
61
62 /// Number of elements in a vector instruction.
63 unsigned vectorNumElements(const Instruction *I) {
64 return cast<VectorType>(I->getOperand(0)->getType())->getNumElements();
65 }
66
67 /// Get the index of an InsertElement or ExtractElement instruction, or null.
68 Value *getInsertExtractElementIdx(const Instruction *I) {
69 switch (I->getOpcode()) {
70 default: return NULL;
71 case Instruction::InsertElement: return I->getOperand(2);
72 case Instruction::ExtractElement: return I->getOperand(1);
73 }
74 }
75
76 /// Set the index of an InsertElement or ExtractElement instruction.
77 void setInsertExtractElementIdx(Instruction *I, Value *NewIdx) {
78 switch (I->getOpcode()) {
79 default:
80 llvm_unreachable(
81 "expected instruction to be InsertElement or ExtractElement");
82 case Instruction::InsertElement: I->setOperand(2, NewIdx); break;
83 case Instruction::ExtractElement: I->setOperand(1, NewIdx); break;
84 }
85 }
86 } // anonymous namespace
87
88 char ConstantInsertExtractElementIndex::ID = 0;
89 INITIALIZE_PASS(
90 ConstantInsertExtractElementIndex, "constant-insert-extract-element-index",
91 "Force insert and extract vector element to always be in bounds", false,
92 false)
93
94 void ConstantInsertExtractElementIndex::findNonConstantInsertExtractElements(
95 const BasicBlock &BB, Instructions &OutOfRangeConstantIndices,
96 Instructions &NonConstantVectorIndices) const {
97 for (BasicBlock::const_iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE;
98 ++BBI) {
99 const Instruction *I = &*BBI;
100 if (Value *Idx = getInsertExtractElementIdx(I)) {
101 if (ConstantInt *CI = dyn_cast<ConstantInt>(Idx)) {
102 if (!CI->getValue().ult(vectorNumElements(I)))
103 OutOfRangeConstantIndices.push_back(const_cast<Instruction *>(I));
104 } else
105 NonConstantVectorIndices.push_back(const_cast<Instruction *>(I));
106 }
107 }
108 }
109
110 void ConstantInsertExtractElementIndex::fixOutOfRangeConstantIndices(
111 BasicBlock &BB, const Instructions &Instrs) const {
112 for (Instructions::const_iterator IB = Instrs.begin(), IE = Instrs.end();
113 IB != IE; ++IB) {
114 Instruction *I = *IB;
115 const APInt &Idx =
116 cast<ConstantInt>(getInsertExtractElementIdx(I))->getValue();
117 APInt NumElements = APInt(Idx.getBitWidth(), vectorNumElements(I));
118 APInt NewIdx = Idx.urem(NumElements);
119 setInsertExtractElementIdx(I, ConstantInt::get(M->getContext(), NewIdx));
120 }
121 }
122
123 void ConstantInsertExtractElementIndex::fixNonConstantVectorIndices(
124 BasicBlock &BB, const Instructions &Instrs) const {
125 for (Instructions::const_iterator IB = Instrs.begin(), IE = Instrs.end();
126 IB != IE; ++IB) {
127 Instruction *I = *IB;
128 Value *Vec = I->getOperand(0);
129 Value *Idx = getInsertExtractElementIdx(I);
130 VectorType *VecTy = cast<VectorType>(Vec->getType());
131 Type *ElemTy = VecTy->getElementType();
132 unsigned ElemAlign = DL->getPrefTypeAlignment(ElemTy);
133 unsigned VecAlign = std::max(ElemAlign, DL->getPrefTypeAlignment(VecTy));
134
135 IRBuilder<> IRB(I);
136 AllocaInst *Alloca = IRB.CreateAlloca(
137 ElemTy, ConstantInt::get(Type::getInt32Ty(M->getContext()),
138 vectorNumElements(I)));
139 Alloca->setAlignment(VecAlign);
140 Value *AllocaAsVec = IRB.CreateBitCast(Alloca, VecTy->getPointerTo());
141 IRB.CreateAlignedStore(Vec, AllocaAsVec, Alloca->getAlignment());
142 Value *GEP = IRB.CreateGEP(Alloca, Idx);
143
144 Value *Res;
145 switch (I->getOpcode()) {
146 default:
147 llvm_unreachable("expected InsertElement or ExtractElement");
148 case Instruction::InsertElement:
149 IRB.CreateAlignedStore(I->getOperand(1), GEP, ElemAlign);
150 Res = IRB.CreateAlignedLoad(AllocaAsVec, Alloca->getAlignment());
151 break;
152 case Instruction::ExtractElement:
153 Res = IRB.CreateAlignedLoad(GEP, ElemAlign);
154 break;
155 }
156
157 I->replaceAllUsesWith(Res);
158 I->eraseFromParent();
159 }
160 }
161
162 bool ConstantInsertExtractElementIndex::runOnBasicBlock(BasicBlock &BB) {
163 bool Changed = false;
164 if (!DL)
165 DL = &getAnalysis<DataLayoutPass>().getDataLayout();
166 Instructions OutOfRangeConstantIndices;
167 Instructions NonConstantVectorIndices;
168
169 findNonConstantInsertExtractElements(BB, OutOfRangeConstantIndices,
170 NonConstantVectorIndices);
171 if (!OutOfRangeConstantIndices.empty()) {
172 Changed = true;
173 fixOutOfRangeConstantIndices(BB, OutOfRangeConstantIndices);
174 }
175 if (!NonConstantVectorIndices.empty()) {
176 Changed = true;
177 fixNonConstantVectorIndices(BB, NonConstantVectorIndices);
178 }
179 return Changed;
180 }
181
182 BasicBlockPass *llvm::createConstantInsertExtractElementIndexPass() {
183 return new ConstantInsertExtractElementIndex();
184 }
OLDNEW
« no previous file with comments | « lib/Transforms/NaCl/CanonicalizeMemIntrinsics.cpp ('k') | lib/Transforms/NaCl/ExceptionInfoWriter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698