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

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

Issue 221693002: PNaCl: Add support for GCC/LLVM vector extensions (Closed) Base URL: http://git.chromium.org/native_client/pnacl-llvm.git@master
Patch Set: Address dschuff's comments. Created 6 years, 8 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 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 *DL;
51
52 void findNonConstantInsertExtractElements(
53 const BasicBlock &BB, Instructions &OutOfRangeConstantIndices,
54 Instructions &NonConstantVectorIndices) const;
55 void fixOutOfRangeConstantIndices(BasicBlock &BB,
56 const Instructions &Instrs) const;
57 void fixNonConstantVectorIndices(BasicBlock &BB,
58 const Instructions &Instrs) const;
59 };
60
61 /// Number of elements in a vector instruction.
62 unsigned vectorNumElements(const Instruction *I) {
63 return cast<VectorType>(I->getOperand(0)->getType())->getNumElements();
64 }
65
66 /// Get the index of an InsertElement or ExtractElement instruction, or null.
67 Value *getInsertExtractElementIdx(const Instruction *I) {
68 switch (I->getOpcode()) {
69 default: return NULL;
70 case Instruction::InsertElement: return I->getOperand(2);
71 case Instruction::ExtractElement: return I->getOperand(1);
72 }
73 }
74
75 /// Set the index of an InsertElement or ExtractElement instruction.
76 void setInsertExtractElementIdx(Instruction *I, Value *NewIdx) {
77 switch (I->getOpcode()) {
78 default:
79 llvm_unreachable(
80 "expected instruction to be InsertElement or ExtractElement");
81 case Instruction::InsertElement: I->setOperand(2, NewIdx); break;
82 case Instruction::ExtractElement: I->setOperand(1, NewIdx); break;
83 }
84 }
85 } // anonymous namespace
86
87 char ConstantInsertExtractElementIndex::ID = 0;
88 INITIALIZE_PASS(
89 ConstantInsertExtractElementIndex, "constant-insert-extract-element-index",
90 "Force insert and extract vector element to always be in bounds", false,
91 false)
92
93 void ConstantInsertExtractElementIndex::findNonConstantInsertExtractElements(
94 const BasicBlock &BB, Instructions &OutOfRangeConstantIndices,
95 Instructions &NonConstantVectorIndices) const {
96 for (BasicBlock::const_iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE;
97 ++BBI) {
98 const Instruction *I = &*BBI;
99 if (Value *Idx = getInsertExtractElementIdx(I)) {
100 if (ConstantInt *CI = dyn_cast<ConstantInt>(Idx)) {
101 if (!CI->getValue().ult(vectorNumElements(I)))
102 OutOfRangeConstantIndices.push_back(const_cast<Instruction *>(I));
103 } else
104 NonConstantVectorIndices.push_back(const_cast<Instruction *>(I));
105 }
106 }
107 }
108
109 void ConstantInsertExtractElementIndex::fixOutOfRangeConstantIndices(
110 BasicBlock &BB, const Instructions &Instrs) const {
111 for (Instructions::const_iterator IB = Instrs.begin(), IE = Instrs.end();
112 IB != IE; ++IB) {
113 Instruction *I = *IB;
114 const APInt &Idx =
115 cast<ConstantInt>(getInsertExtractElementIdx(I))->getValue();
116 APInt NumElements = APInt(Idx.getBitWidth(), vectorNumElements(I));
117 APInt NewIdx = Idx.urem(NumElements);
118 setInsertExtractElementIdx(I, ConstantInt::get(M->getContext(), NewIdx));
119 }
120 }
121
122 void ConstantInsertExtractElementIndex::fixNonConstantVectorIndices(
123 BasicBlock &BB, const Instructions &Instrs) const {
124 for (Instructions::const_iterator IB = Instrs.begin(), IE = Instrs.end();
125 IB != IE; ++IB) {
126 Instruction *I = *IB;
127 Value *Vec = I->getOperand(0);
128 Value *Idx = getInsertExtractElementIdx(I);
129 VectorType *VecTy = cast<VectorType>(Vec->getType());
130 Type *ElemTy = VecTy->getElementType();
131 unsigned ElemAlign = DL->getPrefTypeAlignment(ElemTy);
132 unsigned VecAlign = std::max(ElemAlign, DL->getPrefTypeAlignment(VecTy));
133
134 IRBuilder<> IRB(I);
135 AllocaInst *Alloca = IRB.CreateAlloca(
136 ElemTy, ConstantInt::get(Type::getInt32Ty(M->getContext()),
137 vectorNumElements(I)));
138 Alloca->setAlignment(VecAlign);
139 Value *AllocaAsVec = IRB.CreateBitCast(Alloca, VecTy->getPointerTo());
140 IRB.CreateAlignedStore(Vec, AllocaAsVec, Alloca->getAlignment());
141 Value *GEP = IRB.CreateGEP(Alloca, Idx);
142
143 Value *Res;
144 switch (I->getOpcode()) {
145 default:
146 llvm_unreachable("expected InsertElement or ExtractElement");
147 case Instruction::InsertElement:
148 IRB.CreateAlignedStore(I->getOperand(1), GEP, ElemAlign);
149 Res = IRB.CreateAlignedLoad(AllocaAsVec, Alloca->getAlignment());
150 break;
151 case Instruction::ExtractElement:
152 Res = IRB.CreateAlignedLoad(GEP, ElemAlign);
153 break;
154 }
155
156 I->replaceAllUsesWith(Res);
157 I->eraseFromParent();
158 }
159 }
160
161 bool ConstantInsertExtractElementIndex::runOnBasicBlock(BasicBlock &BB) {
162 bool Changed = false;
163 if (!DL)
164 DL = &getAnalysis<DataLayout>();
165 Instructions OutOfRangeConstantIndices;
166 Instructions NonConstantVectorIndices;
167
168 findNonConstantInsertExtractElements(BB, OutOfRangeConstantIndices,
169 NonConstantVectorIndices);
170 if (!OutOfRangeConstantIndices.empty()) {
171 Changed = true;
172 fixOutOfRangeConstantIndices(BB, OutOfRangeConstantIndices);
173 }
174 if (!NonConstantVectorIndices.empty()) {
175 Changed = true;
176 fixNonConstantVectorIndices(BB, NonConstantVectorIndices);
177 }
178 return Changed;
179 }
180
181 BasicBlockPass *llvm::createConstantInsertExtractElementIndexPass() {
182 return new ConstantInsertExtractElementIndex();
183 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698