1 //===- LowerPacked.cpp - Implementation of LowerPacked Transform ---------===//
3 // The LLVM Compiler Infrastructure
5 // This file was developed by Brad Jones and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements lowering Packed datatypes into more primitive
11 // Packed datatypes, and finally to scalar operations.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Transforms/Scalar.h"
16 #include "llvm/Argument.h"
17 #include "llvm/Constants.h"
18 #include "llvm/DerivedTypes.h"
19 #include "llvm/Function.h"
20 #include "llvm/Instructions.h"
21 #include "llvm/Pass.h"
22 #include "llvm/Support/InstVisitor.h"
23 #include "llvm/Support/Streams.h"
24 #include "llvm/ADT/StringExtras.h"
32 /// This pass converts packed operators to an
33 /// equivalent operations on smaller packed data, to possibly
34 /// scalar operations. Currently it supports lowering
35 /// to scalar operations.
37 /// @brief Transforms packed instructions to simpler instructions.
39 class LowerPacked : public FunctionPass, public InstVisitor<LowerPacked> {
41 /// @brief Lowers packed operations to scalar operations.
42 /// @param F The fuction to process
43 virtual bool runOnFunction(Function &F);
45 /// @brief Lowers packed load instructions.
46 /// @param LI the load instruction to convert
47 void visitLoadInst(LoadInst& LI);
49 /// @brief Lowers packed store instructions.
50 /// @param SI the store instruction to convert
51 void visitStoreInst(StoreInst& SI);
53 /// @brief Lowers packed binary operations.
54 /// @param BO the binary operator to convert
55 void visitBinaryOperator(BinaryOperator& BO);
57 /// @brief Lowers packed select instructions.
58 /// @param SELI the select operator to convert
59 void visitSelectInst(SelectInst& SELI);
61 /// @brief Lowers packed extractelement instructions.
62 /// @param EI the extractelement operator to convert
63 void visitExtractElementInst(ExtractElementInst& EE);
65 /// @brief Lowers packed insertelement instructions.
66 /// @param EI the insertelement operator to convert
67 void visitInsertElementInst(InsertElementInst& IE);
69 /// This function asserts if the instruction is a PackedType but
70 /// is handled by another function.
72 /// @brief Asserts if PackedType instruction is not handled elsewhere.
73 /// @param I the unhandled instruction
74 void visitInstruction(Instruction &I) {
75 if (isa<PackedType>(I.getType()))
76 llvm_cerr << "Unhandled Instruction with Packed ReturnType: "
80 /// @brief Retrieves lowered values for a packed value.
81 /// @param val the packed value
82 /// @return the lowered values
83 std::vector<Value*>& getValues(Value* val);
85 /// @brief Sets lowered values for a packed value.
86 /// @param val the packed value
87 /// @param values the corresponding lowered values
88 void setValues(Value* val,const std::vector<Value*>& values);
91 /// @brief whether we changed the function or not
94 /// @brief a map from old packed values to new smaller packed values
95 std::map<Value*,std::vector<Value*> > packedToScalarMap;
97 /// Instructions in the source program to get rid of
98 /// after we do a pass (the old packed instructions)
99 std::vector<Instruction*> instrsToRemove;
102 RegisterPass<LowerPacked>
104 "lowers packed operations to operations on smaller packed datatypes");
108 FunctionPass *llvm::createLowerPackedPass() { return new LowerPacked(); }
111 // This function sets lowered values for a corresponding
112 // packed value. Note, in the case of a forward reference
113 // getValues(Value*) will have already been called for
114 // the packed parameter. This function will then replace
115 // all references in the in the function of the "dummy"
116 // value the previous getValues(Value*) call
117 // returned with actual references.
118 void LowerPacked::setValues(Value* value,const std::vector<Value*>& values)
120 std::map<Value*,std::vector<Value*> >::iterator it =
121 packedToScalarMap.lower_bound(value);
122 if (it == packedToScalarMap.end() || it->first != value) {
123 // there was not a forward reference to this element
124 packedToScalarMap.insert(it,std::make_pair(value,values));
127 // replace forward declarations with actual definitions
128 assert(it->second.size() == values.size() &&
129 "Error forward refences and actual definition differ in size");
130 for (unsigned i = 0, e = values.size(); i != e; ++i) {
131 // replace and get rid of old forward references
132 it->second[i]->replaceAllUsesWith(values[i]);
133 delete it->second[i];
134 it->second[i] = values[i];
139 // This function will examine the packed value parameter
140 // and if it is a packed constant or a forward reference
141 // properly create the lowered values needed. Otherwise
142 // it will simply retreive values from a
143 // setValues(Value*,const std::vector<Value*>&)
144 // call. Failing both of these cases, it will abort
146 std::vector<Value*>& LowerPacked::getValues(Value* value)
148 assert(isa<PackedType>(value->getType()) &&
149 "Value must be PackedType");
151 // reject further processing if this one has
152 // already been handled
153 std::map<Value*,std::vector<Value*> >::iterator it =
154 packedToScalarMap.lower_bound(value);
155 if (it != packedToScalarMap.end() && it->first == value) {
159 if (ConstantPacked* CP = dyn_cast<ConstantPacked>(value)) {
160 // non-zero constant case
161 std::vector<Value*> results;
162 results.reserve(CP->getNumOperands());
163 for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) {
164 results.push_back(CP->getOperand(i));
166 return packedToScalarMap.insert(it,
167 std::make_pair(value,results))->second;
169 else if (ConstantAggregateZero* CAZ =
170 dyn_cast<ConstantAggregateZero>(value)) {
172 const PackedType* PKT = cast<PackedType>(CAZ->getType());
173 std::vector<Value*> results;
174 results.reserve(PKT->getNumElements());
176 Constant* C = Constant::getNullValue(PKT->getElementType());
177 for (unsigned i = 0, e = PKT->getNumElements(); i != e; ++i) {
178 results.push_back(C);
180 return packedToScalarMap.insert(it,
181 std::make_pair(value,results))->second;
183 else if (isa<Instruction>(value)) {
185 const PackedType* PKT = cast<PackedType>(value->getType());
186 std::vector<Value*> results;
187 results.reserve(PKT->getNumElements());
189 for (unsigned i = 0, e = PKT->getNumElements(); i != e; ++i) {
190 results.push_back(new Argument(PKT->getElementType()));
192 return packedToScalarMap.insert(it,
193 std::make_pair(value,results))->second;
196 // we don't know what it is, and we are trying to retrieve
198 assert(false && "Unhandled PackedType value");
203 void LowerPacked::visitLoadInst(LoadInst& LI)
205 // Make sure what we are dealing with is a packed type
206 if (const PackedType* PKT = dyn_cast<PackedType>(LI.getType())) {
207 // Initialization, Idx is needed for getelementptr needed later
208 std::vector<Value*> Idx(2);
209 Idx[0] = ConstantInt::get(Type::UIntTy,0);
211 ArrayType* AT = ArrayType::get(PKT->getContainedType(0),
212 PKT->getNumElements());
213 PointerType* APT = PointerType::get(AT);
215 // Cast the packed type to an array
216 Value* array = new CastInst(LI.getPointerOperand(),
221 // Convert this load into num elements number of loads
222 std::vector<Value*> values;
223 values.reserve(PKT->getNumElements());
225 for (unsigned i = 0, e = PKT->getNumElements(); i != e; ++i) {
226 // Calculate the second index we will need
227 Idx[1] = ConstantInt::get(Type::UIntTy,i);
230 Value* val = new GetElementPtrInst(array,
236 // generate the new load and save the result in packedToScalar map
237 values.push_back(new LoadInst(val,
238 LI.getName()+"."+utostr(i),
243 setValues(&LI,values);
245 instrsToRemove.push_back(&LI);
249 void LowerPacked::visitBinaryOperator(BinaryOperator& BO)
251 // Make sure both operands are PackedTypes
252 if (isa<PackedType>(BO.getOperand(0)->getType())) {
253 std::vector<Value*>& op0Vals = getValues(BO.getOperand(0));
254 std::vector<Value*>& op1Vals = getValues(BO.getOperand(1));
255 std::vector<Value*> result;
256 assert((op0Vals.size() == op1Vals.size()) &&
257 "The two packed operand to scalar maps must be equal in size.");
259 result.reserve(op0Vals.size());
261 // generate the new binary op and save the result
262 for (unsigned i = 0; i != op0Vals.size(); ++i) {
263 result.push_back(BinaryOperator::create(BO.getOpcode(),
271 setValues(&BO,result);
273 instrsToRemove.push_back(&BO);
277 void LowerPacked::visitStoreInst(StoreInst& SI)
279 if (const PackedType* PKT =
280 dyn_cast<PackedType>(SI.getOperand(0)->getType())) {
281 // We will need this for getelementptr
282 std::vector<Value*> Idx(2);
283 Idx[0] = ConstantInt::get(Type::UIntTy,0);
285 ArrayType* AT = ArrayType::get(PKT->getContainedType(0),
286 PKT->getNumElements());
287 PointerType* APT = PointerType::get(AT);
289 // cast the packed to an array type
290 Value* array = new CastInst(SI.getPointerOperand(),
294 std::vector<Value*>& values = getValues(SI.getOperand(0));
296 assert((values.size() == PKT->getNumElements()) &&
297 "Scalar must have the same number of elements as Packed Type");
299 for (unsigned i = 0, e = PKT->getNumElements(); i != e; ++i) {
300 // Generate the indices for getelementptr
301 Idx[1] = ConstantInt::get(Type::UIntTy,i);
302 Value* val = new GetElementPtrInst(array,
307 new StoreInst(values[i], val, SI.isVolatile(),&SI);
311 instrsToRemove.push_back(&SI);
315 void LowerPacked::visitSelectInst(SelectInst& SELI)
317 // Make sure both operands are PackedTypes
318 if (isa<PackedType>(SELI.getType())) {
319 std::vector<Value*>& op0Vals = getValues(SELI.getTrueValue());
320 std::vector<Value*>& op1Vals = getValues(SELI.getFalseValue());
321 std::vector<Value*> result;
323 assert((op0Vals.size() == op1Vals.size()) &&
324 "The two packed operand to scalar maps must be equal in size.");
326 for (unsigned i = 0; i != op0Vals.size(); ++i) {
327 result.push_back(new SelectInst(SELI.getCondition(),
330 SELI.getName()+ "." + utostr(i),
334 setValues(&SELI,result);
336 instrsToRemove.push_back(&SELI);
340 void LowerPacked::visitExtractElementInst(ExtractElementInst& EI)
342 std::vector<Value*>& op0Vals = getValues(EI.getOperand(0));
343 const PackedType *PTy = cast<PackedType>(EI.getOperand(0)->getType());
344 Value *op1 = EI.getOperand(1);
346 if (ConstantInt *C = dyn_cast<ConstantInt>(op1)) {
347 EI.replaceAllUsesWith(op0Vals[C->getZExtValue()]);
350 new AllocaInst(PTy->getElementType(),
351 ConstantInt::get(Type::UIntTy, PTy->getNumElements()),
352 EI.getName() + ".alloca",
353 EI.getParent()->getParent()->getEntryBlock().begin());
354 for (unsigned i = 0; i < PTy->getNumElements(); ++i) {
355 GetElementPtrInst *GEP =
356 new GetElementPtrInst(alloca, ConstantInt::get(Type::UIntTy, i),
358 new StoreInst(op0Vals[i], GEP, &EI);
360 GetElementPtrInst *GEP =
361 new GetElementPtrInst(alloca, op1, EI.getName() + ".ge", &EI);
362 LoadInst *load = new LoadInst(GEP, EI.getName() + ".load", &EI);
363 EI.replaceAllUsesWith(load);
367 instrsToRemove.push_back(&EI);
370 void LowerPacked::visitInsertElementInst(InsertElementInst& IE)
372 std::vector<Value*>& Vals = getValues(IE.getOperand(0));
373 Value *Elt = IE.getOperand(1);
374 Value *Idx = IE.getOperand(2);
375 std::vector<Value*> result;
376 result.reserve(Vals.size());
378 if (ConstantInt *C = dyn_cast<ConstantInt>(Idx)) {
379 unsigned idxVal = C->getZExtValue();
380 for (unsigned i = 0; i != Vals.size(); ++i) {
381 result.push_back(i == idxVal ? Elt : Vals[i]);
384 for (unsigned i = 0; i != Vals.size(); ++i) {
386 new SetCondInst(Instruction::SetEQ, Idx,
387 ConstantInt::get(Type::UIntTy, i),
390 new SelectInst(setcc, Elt, Vals[i], "select", &IE);
391 result.push_back(select);
395 setValues(&IE, result);
397 instrsToRemove.push_back(&IE);
400 bool LowerPacked::runOnFunction(Function& F)
405 // Does three passes:
406 // Pass 1) Converts Packed Operations to
407 // new Packed Operations on smaller
411 // Pass 2) Drop all references
412 std::for_each(instrsToRemove.begin(),
413 instrsToRemove.end(),
414 std::mem_fun(&Instruction::dropAllReferences));
416 // Pass 3) Delete the Instructions to remove aka packed instructions
417 for (std::vector<Instruction*>::iterator i = instrsToRemove.begin(),
418 e = instrsToRemove.end();
420 (*i)->getParent()->getInstList().erase(*i);
424 packedToScalarMap.clear();
425 instrsToRemove.clear();