blob: e8338bb96f72f116c080ca2c8b0a29255a0aef1d [file] [log] [blame]
Reid Spencerf39f66e2004-08-21 21:39:24 +00001//===- LowerPacked.cpp - Implementation of LowerPacked Transform ---------===//
Misha Brukmanb1c93172005-04-21 23:48:37 +00002//
Reid Spencerf39f66e2004-08-21 21:39:24 +00003// The LLVM Compiler Infrastructure
4//
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.
Misha Brukmanb1c93172005-04-21 23:48:37 +00007//
Reid Spencerf39f66e2004-08-21 21:39:24 +00008//===----------------------------------------------------------------------===//
9//
10// This file implements lowering Packed datatypes into more primitive
11// Packed datatypes, and finally to scalar operations.
12//
13//===----------------------------------------------------------------------===//
14
Chris Lattner446948e2004-11-19 16:49:34 +000015#include "llvm/Transforms/Scalar.h"
Reid Spencerf39f66e2004-08-21 21:39:24 +000016#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"
Reid Spencer7c16caa2004-09-01 22:55:40 +000023#include "llvm/ADT/StringExtras.h"
Reid Spencerf39f66e2004-08-21 21:39:24 +000024#include <algorithm>
25#include <map>
26#include <iostream>
Duraid Madina7a3ad6c2005-12-26 13:48:44 +000027#include <functional>
Reid Spencerf39f66e2004-08-21 21:39:24 +000028
29using namespace llvm;
30
31namespace {
32
33/// This pass converts packed operators to an
34/// equivalent operations on smaller packed data, to possibly
35/// scalar operations. Currently it supports lowering
36/// to scalar operations.
37///
38/// @brief Transforms packed instructions to simpler instructions.
39///
40class LowerPacked : public FunctionPass, public InstVisitor<LowerPacked> {
41public:
Misha Brukmanb1c93172005-04-21 23:48:37 +000042 /// @brief Lowers packed operations to scalar operations.
Reid Spencerf39f66e2004-08-21 21:39:24 +000043 /// @param F The fuction to process
44 virtual bool runOnFunction(Function &F);
45
46 /// @brief Lowers packed load instructions.
47 /// @param LI the load instruction to convert
48 void visitLoadInst(LoadInst& LI);
49
50 /// @brief Lowers packed store instructions.
51 /// @param SI the store instruction to convert
52 void visitStoreInst(StoreInst& SI);
53
54 /// @brief Lowers packed binary operations.
55 /// @param BO the binary operator to convert
56 void visitBinaryOperator(BinaryOperator& BO);
57
58 /// @brief Lowers packed select instructions.
59 /// @param SELI the select operator to convert
60 void visitSelectInst(SelectInst& SELI);
61
Robert Bocchinobd518d12006-01-10 19:05:05 +000062 /// @brief Lowers packed extractelement instructions.
63 /// @param EI the extractelement operator to convert
64 void visitExtractElementInst(ExtractElementInst& EI);
65
Reid Spencerf39f66e2004-08-21 21:39:24 +000066 /// This function asserts if the instruction is a PackedType but
67 /// is handled by another function.
Misha Brukmanb1c93172005-04-21 23:48:37 +000068 ///
Reid Spencerf39f66e2004-08-21 21:39:24 +000069 /// @brief Asserts if PackedType instruction is not handled elsewhere.
70 /// @param I the unhandled instruction
71 void visitInstruction(Instruction &I)
72 {
73 if(isa<PackedType>(I.getType())) {
Misha Brukmanb1c93172005-04-21 23:48:37 +000074 std::cerr << "Unhandled Instruction with Packed ReturnType: " <<
Reid Spencerf39f66e2004-08-21 21:39:24 +000075 I << '\n';
76 }
77 }
78private:
79 /// @brief Retrieves lowered values for a packed value.
80 /// @param val the packed value
81 /// @return the lowered values
82 std::vector<Value*>& getValues(Value* val);
83
84 /// @brief Sets lowered values for a packed value.
85 /// @param val the packed value
86 /// @param values the corresponding lowered values
87 void setValues(Value* val,const std::vector<Value*>& values);
88
89 // Data Members
Misha Brukmanb1c93172005-04-21 23:48:37 +000090 /// @brief whether we changed the function or not
Reid Spencerf39f66e2004-08-21 21:39:24 +000091 bool Changed;
92
93 /// @brief a map from old packed values to new smaller packed values
94 std::map<Value*,std::vector<Value*> > packedToScalarMap;
95
96 /// Instructions in the source program to get rid of
97 /// after we do a pass (the old packed instructions)
98 std::vector<Instruction*> instrsToRemove;
Misha Brukmanb1c93172005-04-21 23:48:37 +000099};
Reid Spencerf39f66e2004-08-21 21:39:24 +0000100
Misha Brukmanb1c93172005-04-21 23:48:37 +0000101RegisterOpt<LowerPacked>
102X("lower-packed",
Reid Spencerf39f66e2004-08-21 21:39:24 +0000103 "lowers packed operations to operations on smaller packed datatypes");
104
Misha Brukmanb1c93172005-04-21 23:48:37 +0000105} // end namespace
Reid Spencerf39f66e2004-08-21 21:39:24 +0000106
Chris Lattner446948e2004-11-19 16:49:34 +0000107FunctionPass *llvm::createLowerPackedPass() { return new LowerPacked(); }
Chris Lattnerc08ac112004-11-18 17:24:20 +0000108
109
Reid Spencerf39f66e2004-08-21 21:39:24 +0000110// This function sets lowered values for a corresponding
111// packed value. Note, in the case of a forward reference
Misha Brukmanb1c93172005-04-21 23:48:37 +0000112// getValues(Value*) will have already been called for
113// the packed parameter. This function will then replace
114// all references in the in the function of the "dummy"
115// value the previous getValues(Value*) call
Reid Spencerf39f66e2004-08-21 21:39:24 +0000116// returned with actual references.
117void LowerPacked::setValues(Value* value,const std::vector<Value*>& values)
118{
Misha Brukmanb1c93172005-04-21 23:48:37 +0000119 std::map<Value*,std::vector<Value*> >::iterator it =
Reid Spencerf39f66e2004-08-21 21:39:24 +0000120 packedToScalarMap.lower_bound(value);
121 if (it == packedToScalarMap.end() || it->first != value) {
122 // there was not a forward reference to this element
123 packedToScalarMap.insert(it,std::make_pair(value,values));
124 }
125 else {
126 // replace forward declarations with actual definitions
Misha Brukmanb1c93172005-04-21 23:48:37 +0000127 assert(it->second.size() == values.size() &&
Reid Spencerf39f66e2004-08-21 21:39:24 +0000128 "Error forward refences and actual definition differ in size");
129 for (unsigned i = 0, e = values.size(); i != e; ++i) {
130 // replace and get rid of old forward references
131 it->second[i]->replaceAllUsesWith(values[i]);
132 delete it->second[i];
133 it->second[i] = values[i];
134 }
135 }
136}
137
138// This function will examine the packed value parameter
139// and if it is a packed constant or a forward reference
140// properly create the lowered values needed. Otherwise
Misha Brukmanb1c93172005-04-21 23:48:37 +0000141// it will simply retreive values from a
142// setValues(Value*,const std::vector<Value*>&)
Reid Spencerf39f66e2004-08-21 21:39:24 +0000143// call. Failing both of these cases, it will abort
144// the program.
145std::vector<Value*>& LowerPacked::getValues(Value* value)
146{
147 assert(isa<PackedType>(value->getType()) &&
148 "Value must be PackedType");
149
150 // reject further processing if this one has
151 // already been handled
Misha Brukmanb1c93172005-04-21 23:48:37 +0000152 std::map<Value*,std::vector<Value*> >::iterator it =
Reid Spencerf39f66e2004-08-21 21:39:24 +0000153 packedToScalarMap.lower_bound(value);
154 if (it != packedToScalarMap.end() && it->first == value) {
155 return it->second;
156 }
157
158 if (ConstantPacked* CP = dyn_cast<ConstantPacked>(value)) {
159 // non-zero constant case
160 std::vector<Value*> results;
161 results.reserve(CP->getNumOperands());
162 for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) {
163 results.push_back(CP->getOperand(i));
164 }
165 return packedToScalarMap.insert(it,
166 std::make_pair(value,results))->second;
167 }
168 else if (ConstantAggregateZero* CAZ =
169 dyn_cast<ConstantAggregateZero>(value)) {
Misha Brukmanb1c93172005-04-21 23:48:37 +0000170 // zero constant
Reid Spencerf39f66e2004-08-21 21:39:24 +0000171 const PackedType* PKT = cast<PackedType>(CAZ->getType());
172 std::vector<Value*> results;
173 results.reserve(PKT->getNumElements());
Misha Brukmanb1c93172005-04-21 23:48:37 +0000174
Reid Spencerf39f66e2004-08-21 21:39:24 +0000175 Constant* C = Constant::getNullValue(PKT->getElementType());
176 for (unsigned i = 0, e = PKT->getNumElements(); i != e; ++i) {
177 results.push_back(C);
178 }
179 return packedToScalarMap.insert(it,
180 std::make_pair(value,results))->second;
181 }
182 else if (isa<Instruction>(value)) {
183 // foward reference
184 const PackedType* PKT = cast<PackedType>(value->getType());
185 std::vector<Value*> results;
186 results.reserve(PKT->getNumElements());
Misha Brukmanb1c93172005-04-21 23:48:37 +0000187
Reid Spencerf39f66e2004-08-21 21:39:24 +0000188 for (unsigned i = 0, e = PKT->getNumElements(); i != e; ++i) {
189 results.push_back(new Argument(PKT->getElementType()));
190 }
191 return packedToScalarMap.insert(it,
192 std::make_pair(value,results))->second;
193 }
194 else {
195 // we don't know what it is, and we are trying to retrieve
196 // a value for it
197 assert(false && "Unhandled PackedType value");
198 abort();
199 }
200}
201
202void LowerPacked::visitLoadInst(LoadInst& LI)
203{
204 // Make sure what we are dealing with is a packed type
205 if (const PackedType* PKT = dyn_cast<PackedType>(LI.getType())) {
206 // Initialization, Idx is needed for getelementptr needed later
207 std::vector<Value*> Idx(2);
208 Idx[0] = ConstantUInt::get(Type::UIntTy,0);
209
210 ArrayType* AT = ArrayType::get(PKT->getContainedType(0),
211 PKT->getNumElements());
212 PointerType* APT = PointerType::get(AT);
213
214 // Cast the packed type to an array
215 Value* array = new CastInst(LI.getPointerOperand(),
216 APT,
217 LI.getName() + ".a",
218 &LI);
219
220 // Convert this load into num elements number of loads
221 std::vector<Value*> values;
222 values.reserve(PKT->getNumElements());
223
224 for (unsigned i = 0, e = PKT->getNumElements(); i != e; ++i) {
225 // Calculate the second index we will need
226 Idx[1] = ConstantUInt::get(Type::UIntTy,i);
227
228 // Get the pointer
Misha Brukmanb1c93172005-04-21 23:48:37 +0000229 Value* val = new GetElementPtrInst(array,
Reid Spencerf39f66e2004-08-21 21:39:24 +0000230 Idx,
Misha Brukmanb1c93172005-04-21 23:48:37 +0000231 LI.getName() +
Reid Spencerf39f66e2004-08-21 21:39:24 +0000232 ".ge." + utostr(i),
233 &LI);
234
235 // generate the new load and save the result in packedToScalar map
Misha Brukmanb1c93172005-04-21 23:48:37 +0000236 values.push_back(new LoadInst(val,
Reid Spencerf39f66e2004-08-21 21:39:24 +0000237 LI.getName()+"."+utostr(i),
238 LI.isVolatile(),
239 &LI));
240 }
Misha Brukmanb1c93172005-04-21 23:48:37 +0000241
Reid Spencerf39f66e2004-08-21 21:39:24 +0000242 setValues(&LI,values);
243 Changed = true;
244 instrsToRemove.push_back(&LI);
245 }
246}
247
248void LowerPacked::visitBinaryOperator(BinaryOperator& BO)
249{
250 // Make sure both operands are PackedTypes
251 if (isa<PackedType>(BO.getOperand(0)->getType())) {
252 std::vector<Value*>& op0Vals = getValues(BO.getOperand(0));
253 std::vector<Value*>& op1Vals = getValues(BO.getOperand(1));
254 std::vector<Value*> result;
255 assert((op0Vals.size() == op1Vals.size()) &&
256 "The two packed operand to scalar maps must be equal in size.");
257
258 result.reserve(op0Vals.size());
Misha Brukmanb1c93172005-04-21 23:48:37 +0000259
Reid Spencerf39f66e2004-08-21 21:39:24 +0000260 // generate the new binary op and save the result
261 for (unsigned i = 0; i != op0Vals.size(); ++i) {
Misha Brukmanb1c93172005-04-21 23:48:37 +0000262 result.push_back(BinaryOperator::create(BO.getOpcode(),
263 op0Vals[i],
Reid Spencerf39f66e2004-08-21 21:39:24 +0000264 op1Vals[i],
Misha Brukmanb1c93172005-04-21 23:48:37 +0000265 BO.getName() +
Reid Spencerf39f66e2004-08-21 21:39:24 +0000266 "." + utostr(i),
267 &BO));
268 }
269
270 setValues(&BO,result);
271 Changed = true;
272 instrsToRemove.push_back(&BO);
273 }
274}
275
276void LowerPacked::visitStoreInst(StoreInst& SI)
277{
Misha Brukmanb1c93172005-04-21 23:48:37 +0000278 if (const PackedType* PKT =
Reid Spencerf39f66e2004-08-21 21:39:24 +0000279 dyn_cast<PackedType>(SI.getOperand(0)->getType())) {
280 // We will need this for getelementptr
281 std::vector<Value*> Idx(2);
282 Idx[0] = ConstantUInt::get(Type::UIntTy,0);
Misha Brukmanb1c93172005-04-21 23:48:37 +0000283
Reid Spencerf39f66e2004-08-21 21:39:24 +0000284 ArrayType* AT = ArrayType::get(PKT->getContainedType(0),
285 PKT->getNumElements());
286 PointerType* APT = PointerType::get(AT);
287
288 // cast the packed to an array type
289 Value* array = new CastInst(SI.getPointerOperand(),
290 APT,
291 "store.ge.a.",
292 &SI);
293 std::vector<Value*>& values = getValues(SI.getOperand(0));
Misha Brukmanb1c93172005-04-21 23:48:37 +0000294
Reid Spencerf39f66e2004-08-21 21:39:24 +0000295 assert((values.size() == PKT->getNumElements()) &&
296 "Scalar must have the same number of elements as Packed Type");
297
298 for (unsigned i = 0, e = PKT->getNumElements(); i != e; ++i) {
299 // Generate the indices for getelementptr
300 Idx[1] = ConstantUInt::get(Type::UIntTy,i);
Misha Brukmanb1c93172005-04-21 23:48:37 +0000301 Value* val = new GetElementPtrInst(array,
Reid Spencerf39f66e2004-08-21 21:39:24 +0000302 Idx,
303 "store.ge." +
304 utostr(i) + ".",
305 &SI);
306 new StoreInst(values[i], val, SI.isVolatile(),&SI);
307 }
Misha Brukmanb1c93172005-04-21 23:48:37 +0000308
Reid Spencerf39f66e2004-08-21 21:39:24 +0000309 Changed = true;
310 instrsToRemove.push_back(&SI);
311 }
312}
313
314void LowerPacked::visitSelectInst(SelectInst& SELI)
315{
316 // Make sure both operands are PackedTypes
317 if (isa<PackedType>(SELI.getType())) {
318 std::vector<Value*>& op0Vals = getValues(SELI.getTrueValue());
319 std::vector<Value*>& op1Vals = getValues(SELI.getFalseValue());
320 std::vector<Value*> result;
321
322 assert((op0Vals.size() == op1Vals.size()) &&
323 "The two packed operand to scalar maps must be equal in size.");
324
325 for (unsigned i = 0; i != op0Vals.size(); ++i) {
326 result.push_back(new SelectInst(SELI.getCondition(),
Misha Brukmanb1c93172005-04-21 23:48:37 +0000327 op0Vals[i],
Reid Spencerf39f66e2004-08-21 21:39:24 +0000328 op1Vals[i],
329 SELI.getName()+ "." + utostr(i),
330 &SELI));
331 }
Misha Brukmanb1c93172005-04-21 23:48:37 +0000332
Reid Spencerf39f66e2004-08-21 21:39:24 +0000333 setValues(&SELI,result);
334 Changed = true;
335 instrsToRemove.push_back(&SELI);
336 }
337}
338
Robert Bocchinobd518d12006-01-10 19:05:05 +0000339void LowerPacked::visitExtractElementInst(ExtractElementInst& EI)
340{
341 std::vector<Value*>& op0Vals = getValues(EI.getOperand(0));
342 const PackedType *PTy = cast<PackedType>(EI.getOperand(0)->getType());
343 Value *op1 = EI.getOperand(1);
344
345 if (ConstantUInt *C = dyn_cast<ConstantUInt>(op1)) {
346 EI.replaceAllUsesWith(op0Vals[C->getValue()]);
347 } else {
348 AllocaInst *alloca = new AllocaInst(PTy->getElementType(),
349 ConstantUInt::get(Type::UIntTy, PTy->getNumElements()),
350 EI.getName() + ".alloca", &(EI.getParent()->getParent()->getEntryBlock().front()));
351 for (unsigned i = 0; i < PTy->getNumElements(); ++i) {
352 GetElementPtrInst *GEP = new GetElementPtrInst(alloca, ConstantUInt::get(Type::UIntTy, i),
353 "store.ge", &EI);
354 new StoreInst(op0Vals[i], GEP, &EI);
355 }
356 GetElementPtrInst *GEP = new GetElementPtrInst(alloca, op1,
357 EI.getName() + ".ge", &EI);
358 LoadInst *load = new LoadInst(GEP, EI.getName() + ".load", &EI);
359 EI.replaceAllUsesWith(load);
360 }
361
362 Changed = true;
363 instrsToRemove.push_back(&EI);
364}
365
Reid Spencerf39f66e2004-08-21 21:39:24 +0000366bool LowerPacked::runOnFunction(Function& F)
367{
368 // initialize
Misha Brukmanb1c93172005-04-21 23:48:37 +0000369 Changed = false;
370
Reid Spencerf39f66e2004-08-21 21:39:24 +0000371 // Does three passes:
Misha Brukmanb1c93172005-04-21 23:48:37 +0000372 // Pass 1) Converts Packed Operations to
Reid Spencerf39f66e2004-08-21 21:39:24 +0000373 // new Packed Operations on smaller
374 // datatypes
375 visit(F);
Misha Brukmanb1c93172005-04-21 23:48:37 +0000376
Reid Spencerf39f66e2004-08-21 21:39:24 +0000377 // Pass 2) Drop all references
378 std::for_each(instrsToRemove.begin(),
379 instrsToRemove.end(),
380 std::mem_fun(&Instruction::dropAllReferences));
381
382 // Pass 3) Delete the Instructions to remove aka packed instructions
Misha Brukmanb1c93172005-04-21 23:48:37 +0000383 for (std::vector<Instruction*>::iterator i = instrsToRemove.begin(),
384 e = instrsToRemove.end();
Reid Spencerf39f66e2004-08-21 21:39:24 +0000385 i != e; ++i) {
Misha Brukmanb1c93172005-04-21 23:48:37 +0000386 (*i)->getParent()->getInstList().erase(*i);
Reid Spencerf39f66e2004-08-21 21:39:24 +0000387 }
388
389 // clean-up
390 packedToScalarMap.clear();
391 instrsToRemove.clear();
392
393 return Changed;
394}
395