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

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: "ConstantInsertExtractElementIndex now forces out-of-range constant indices to be in range instead … 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 = cast<ConstantInt>(getInsertExtractElementIdx(I))->getValu e();
Derek Schuff 2014/04/15 20:30:43 80 col
JF 2014/04/15 20:43:26 Done.
115 APInt NumElements = APInt(Idx.getBitWidth(), vectorNumElements(I));
116 APInt NewIdx = Idx.urem(NumElements);
117 setInsertExtractElementIdx(I, ConstantInt::get(M->getContext(), NewIdx));
118 }
119 }
120
121 void ConstantInsertExtractElementIndex::fixNonConstantVectorIndices(
122 BasicBlock &BB, const Instructions &Instrs) const {
123 for (Instructions::const_iterator IB = Instrs.begin(), IE = Instrs.end();
124 IB != IE; ++IB) {
125 Instruction *I = *IB;
126 Value *Vec = I->getOperand(0);
127 Value *Idx = getInsertExtractElementIdx(I);
128 VectorType *VecTy = cast<VectorType>(Vec->getType());
129 Type *ElemTy = VecTy->getElementType();
130 unsigned ElemAlign = DL->getPrefTypeAlignment(ElemTy);
131 unsigned VecAlign = std::max(ElemAlign, DL->getPrefTypeAlignment(VecTy));
132
133 IRBuilder<> IRB(I);
134 AllocaInst *Alloca = IRB.CreateAlloca(
135 ElemTy, ConstantInt::get(Type::getInt32Ty(M->getContext()),
136 vectorNumElements(I)));
137 Alloca->setAlignment(VecAlign);
138 Value *AllocaAsVec = IRB.CreateBitCast(Alloca, VecTy->getPointerTo());
139 IRB.CreateAlignedStore(Vec, AllocaAsVec, Alloca->getAlignment());
140 Value *GEP = IRB.CreateGEP(Alloca, Idx);
141
142 Value *Res;
143 switch (I->getOpcode()) {
144 default:
145 llvm_unreachable("expected InsertElement or ExtractElement");
146 case Instruction::InsertElement:
147 IRB.CreateAlignedStore(I->getOperand(1), GEP, ElemAlign);
148 Res = IRB.CreateAlignedLoad(AllocaAsVec, Alloca->getAlignment());
149 break;
150 case Instruction::ExtractElement:
151 Res = IRB.CreateAlignedLoad(GEP, ElemAlign);
152 break;
153 }
154
155 I->replaceAllUsesWith(Res);
156 I->eraseFromParent();
157 }
158 }
159
160 bool ConstantInsertExtractElementIndex::runOnBasicBlock(BasicBlock &BB) {
161 bool Changed = false;
162 if (!DL)
163 DL = &getAnalysis<DataLayout>();
164 Instructions OutOfRangeConstantIndices;
165 Instructions NonConstantVectorIndices;
166
167 findNonConstantInsertExtractElements(BB, OutOfRangeConstantIndices,
168 NonConstantVectorIndices);
169 if (!OutOfRangeConstantIndices.empty()) {
170 Changed = true;
171 fixOutOfRangeConstantIndices(BB, OutOfRangeConstantIndices);
172 }
173 if (!NonConstantVectorIndices.empty()) {
174 Changed = true;
175 fixNonConstantVectorIndices(BB, NonConstantVectorIndices);
176 }
177 return Changed;
178 }
179
180 BasicBlockPass *llvm::createConstantInsertExtractElementIndexPass() {
181 return new ConstantInsertExtractElementIndex();
182 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698