blob: f02c40f4d8a27439e7f2b1bd55f4b9c895c10e4d [file] [log] [blame]
Reid Spencer42e83fe2004-08-21 21:39:24 +00001//===- LowerPacked.cpp - Implementation of LowerPacked Transform ---------===//
Misha Brukmanfd939082005-04-21 23:48:37 +00002//
Reid Spencer42e83fe2004-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 Brukmanfd939082005-04-21 23:48:37 +00007//
Reid Spencer42e83fe2004-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 Lattner7b73a662004-11-19 16:49:34 +000015#include "llvm/Transforms/Scalar.h"
Reid Spencer42e83fe2004-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"
Bill Wendlingb7427032006-11-26 09:46:52 +000023#include "llvm/Support/Streams.h"
Reid Spencer551ccae2004-09-01 22:55:40 +000024#include "llvm/ADT/StringExtras.h"
Reid Spencer42e83fe2004-08-21 21:39:24 +000025#include <algorithm>
26#include <map>
Duraid Madinab5186852005-12-26 13:48:44 +000027#include <functional>
Reid Spencer42e83fe2004-08-21 21:39:24 +000028using namespace llvm;
29
30namespace {
31
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.
36///
37/// @brief Transforms packed instructions to simpler instructions.
38///
39class LowerPacked : public FunctionPass, public InstVisitor<LowerPacked> {
40public:
Misha Brukmanfd939082005-04-21 23:48:37 +000041 /// @brief Lowers packed operations to scalar operations.
Reid Spencer42e83fe2004-08-21 21:39:24 +000042 /// @param F The fuction to process
43 virtual bool runOnFunction(Function &F);
44
45 /// @brief Lowers packed load instructions.
46 /// @param LI the load instruction to convert
47 void visitLoadInst(LoadInst& LI);
48
49 /// @brief Lowers packed store instructions.
50 /// @param SI the store instruction to convert
51 void visitStoreInst(StoreInst& SI);
52
53 /// @brief Lowers packed binary operations.
54 /// @param BO the binary operator to convert
55 void visitBinaryOperator(BinaryOperator& BO);
56
57 /// @brief Lowers packed select instructions.
58 /// @param SELI the select operator to convert
59 void visitSelectInst(SelectInst& SELI);
60
Robert Bocchino56107e22006-01-10 19:05:05 +000061 /// @brief Lowers packed extractelement instructions.
62 /// @param EI the extractelement operator to convert
Robert Bocchino8fcf01e2006-01-17 20:06:55 +000063 void visitExtractElementInst(ExtractElementInst& EE);
64
65 /// @brief Lowers packed insertelement instructions.
66 /// @param EI the insertelement operator to convert
67 void visitInsertElementInst(InsertElementInst& IE);
Robert Bocchino56107e22006-01-10 19:05:05 +000068
Reid Spencer42e83fe2004-08-21 21:39:24 +000069 /// This function asserts if the instruction is a PackedType but
70 /// is handled by another function.
Misha Brukmanfd939082005-04-21 23:48:37 +000071 ///
Reid Spencer42e83fe2004-08-21 21:39:24 +000072 /// @brief Asserts if PackedType instruction is not handled elsewhere.
73 /// @param I the unhandled instruction
Bill Wendlingb7427032006-11-26 09:46:52 +000074 void visitInstruction(Instruction &I) {
75 if (isa<PackedType>(I.getType()))
76 llvm_cerr << "Unhandled Instruction with Packed ReturnType: "
77 << I << '\n';
Reid Spencer42e83fe2004-08-21 21:39:24 +000078 }
79private:
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);
84
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);
89
90 // Data Members
Misha Brukmanfd939082005-04-21 23:48:37 +000091 /// @brief whether we changed the function or not
Reid Spencer42e83fe2004-08-21 21:39:24 +000092 bool Changed;
93
94 /// @brief a map from old packed values to new smaller packed values
95 std::map<Value*,std::vector<Value*> > packedToScalarMap;
96
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;
Misha Brukmanfd939082005-04-21 23:48:37 +0000100};
Reid Spencer42e83fe2004-08-21 21:39:24 +0000101
Chris Lattner7f8897f2006-08-27 22:42:52 +0000102RegisterPass<LowerPacked>
Misha Brukmanfd939082005-04-21 23:48:37 +0000103X("lower-packed",
Reid Spencer42e83fe2004-08-21 21:39:24 +0000104 "lowers packed operations to operations on smaller packed datatypes");
105
Misha Brukmanfd939082005-04-21 23:48:37 +0000106} // end namespace
Reid Spencer42e83fe2004-08-21 21:39:24 +0000107
Chris Lattner7b73a662004-11-19 16:49:34 +0000108FunctionPass *llvm::createLowerPackedPass() { return new LowerPacked(); }
Chris Lattner56de0362004-11-18 17:24:20 +0000109
110
Reid Spencer42e83fe2004-08-21 21:39:24 +0000111// This function sets lowered values for a corresponding
112// packed value. Note, in the case of a forward reference
Misha Brukmanfd939082005-04-21 23:48:37 +0000113// 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
Reid Spencer42e83fe2004-08-21 21:39:24 +0000117// returned with actual references.
118void LowerPacked::setValues(Value* value,const std::vector<Value*>& values)
119{
Misha Brukmanfd939082005-04-21 23:48:37 +0000120 std::map<Value*,std::vector<Value*> >::iterator it =
Reid Spencer42e83fe2004-08-21 21:39:24 +0000121 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));
125 }
126 else {
127 // replace forward declarations with actual definitions
Misha Brukmanfd939082005-04-21 23:48:37 +0000128 assert(it->second.size() == values.size() &&
Reid Spencer42e83fe2004-08-21 21:39:24 +0000129 "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];
135 }
136 }
137}
138
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
Misha Brukmanfd939082005-04-21 23:48:37 +0000142// it will simply retreive values from a
143// setValues(Value*,const std::vector<Value*>&)
Reid Spencer42e83fe2004-08-21 21:39:24 +0000144// call. Failing both of these cases, it will abort
145// the program.
146std::vector<Value*>& LowerPacked::getValues(Value* value)
147{
148 assert(isa<PackedType>(value->getType()) &&
149 "Value must be PackedType");
150
151 // reject further processing if this one has
152 // already been handled
Misha Brukmanfd939082005-04-21 23:48:37 +0000153 std::map<Value*,std::vector<Value*> >::iterator it =
Reid Spencer42e83fe2004-08-21 21:39:24 +0000154 packedToScalarMap.lower_bound(value);
155 if (it != packedToScalarMap.end() && it->first == value) {
156 return it->second;
157 }
158
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));
165 }
166 return packedToScalarMap.insert(it,
167 std::make_pair(value,results))->second;
168 }
169 else if (ConstantAggregateZero* CAZ =
170 dyn_cast<ConstantAggregateZero>(value)) {
Misha Brukmanfd939082005-04-21 23:48:37 +0000171 // zero constant
Reid Spencer42e83fe2004-08-21 21:39:24 +0000172 const PackedType* PKT = cast<PackedType>(CAZ->getType());
173 std::vector<Value*> results;
174 results.reserve(PKT->getNumElements());
Misha Brukmanfd939082005-04-21 23:48:37 +0000175
Reid Spencer42e83fe2004-08-21 21:39:24 +0000176 Constant* C = Constant::getNullValue(PKT->getElementType());
177 for (unsigned i = 0, e = PKT->getNumElements(); i != e; ++i) {
178 results.push_back(C);
179 }
180 return packedToScalarMap.insert(it,
181 std::make_pair(value,results))->second;
182 }
183 else if (isa<Instruction>(value)) {
184 // foward reference
185 const PackedType* PKT = cast<PackedType>(value->getType());
186 std::vector<Value*> results;
187 results.reserve(PKT->getNumElements());
Misha Brukmanfd939082005-04-21 23:48:37 +0000188
Reid Spencer42e83fe2004-08-21 21:39:24 +0000189 for (unsigned i = 0, e = PKT->getNumElements(); i != e; ++i) {
190 results.push_back(new Argument(PKT->getElementType()));
191 }
192 return packedToScalarMap.insert(it,
193 std::make_pair(value,results))->second;
194 }
195 else {
196 // we don't know what it is, and we are trying to retrieve
197 // a value for it
198 assert(false && "Unhandled PackedType value");
199 abort();
200 }
201}
202
203void LowerPacked::visitLoadInst(LoadInst& LI)
204{
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);
Reid Spencerb83eb642006-10-20 07:07:24 +0000209 Idx[0] = ConstantInt::get(Type::UIntTy,0);
Reid Spencer42e83fe2004-08-21 21:39:24 +0000210
211 ArrayType* AT = ArrayType::get(PKT->getContainedType(0),
212 PKT->getNumElements());
213 PointerType* APT = PointerType::get(AT);
214
Reid Spencer3da59db2006-11-27 01:05:10 +0000215 // Cast the pointer to packed type to an equivalent array
216 Value* array = new BitCastInst(LI.getPointerOperand(), APT,
217 LI.getName() + ".a", &LI);
Reid Spencer42e83fe2004-08-21 21:39:24 +0000218
219 // Convert this load into num elements number of loads
220 std::vector<Value*> values;
221 values.reserve(PKT->getNumElements());
222
223 for (unsigned i = 0, e = PKT->getNumElements(); i != e; ++i) {
224 // Calculate the second index we will need
Reid Spencerb83eb642006-10-20 07:07:24 +0000225 Idx[1] = ConstantInt::get(Type::UIntTy,i);
Reid Spencer42e83fe2004-08-21 21:39:24 +0000226
227 // Get the pointer
Misha Brukmanfd939082005-04-21 23:48:37 +0000228 Value* val = new GetElementPtrInst(array,
Reid Spencer42e83fe2004-08-21 21:39:24 +0000229 Idx,
Misha Brukmanfd939082005-04-21 23:48:37 +0000230 LI.getName() +
Reid Spencer42e83fe2004-08-21 21:39:24 +0000231 ".ge." + utostr(i),
232 &LI);
233
234 // generate the new load and save the result in packedToScalar map
Reid Spencer3da59db2006-11-27 01:05:10 +0000235 values.push_back(new LoadInst(val, LI.getName()+"."+utostr(i),
236 LI.isVolatile(), &LI));
Reid Spencer42e83fe2004-08-21 21:39:24 +0000237 }
Misha Brukmanfd939082005-04-21 23:48:37 +0000238
Reid Spencer42e83fe2004-08-21 21:39:24 +0000239 setValues(&LI,values);
240 Changed = true;
241 instrsToRemove.push_back(&LI);
242 }
243}
244
245void LowerPacked::visitBinaryOperator(BinaryOperator& BO)
246{
247 // Make sure both operands are PackedTypes
248 if (isa<PackedType>(BO.getOperand(0)->getType())) {
249 std::vector<Value*>& op0Vals = getValues(BO.getOperand(0));
250 std::vector<Value*>& op1Vals = getValues(BO.getOperand(1));
251 std::vector<Value*> result;
252 assert((op0Vals.size() == op1Vals.size()) &&
253 "The two packed operand to scalar maps must be equal in size.");
254
255 result.reserve(op0Vals.size());
Misha Brukmanfd939082005-04-21 23:48:37 +0000256
Reid Spencer42e83fe2004-08-21 21:39:24 +0000257 // generate the new binary op and save the result
258 for (unsigned i = 0; i != op0Vals.size(); ++i) {
Misha Brukmanfd939082005-04-21 23:48:37 +0000259 result.push_back(BinaryOperator::create(BO.getOpcode(),
260 op0Vals[i],
Reid Spencer42e83fe2004-08-21 21:39:24 +0000261 op1Vals[i],
Misha Brukmanfd939082005-04-21 23:48:37 +0000262 BO.getName() +
Reid Spencer42e83fe2004-08-21 21:39:24 +0000263 "." + utostr(i),
264 &BO));
265 }
266
267 setValues(&BO,result);
268 Changed = true;
269 instrsToRemove.push_back(&BO);
270 }
271}
272
273void LowerPacked::visitStoreInst(StoreInst& SI)
274{
Misha Brukmanfd939082005-04-21 23:48:37 +0000275 if (const PackedType* PKT =
Reid Spencer42e83fe2004-08-21 21:39:24 +0000276 dyn_cast<PackedType>(SI.getOperand(0)->getType())) {
277 // We will need this for getelementptr
278 std::vector<Value*> Idx(2);
Reid Spencerb83eb642006-10-20 07:07:24 +0000279 Idx[0] = ConstantInt::get(Type::UIntTy,0);
Misha Brukmanfd939082005-04-21 23:48:37 +0000280
Reid Spencer42e83fe2004-08-21 21:39:24 +0000281 ArrayType* AT = ArrayType::get(PKT->getContainedType(0),
282 PKT->getNumElements());
283 PointerType* APT = PointerType::get(AT);
284
Reid Spencer3da59db2006-11-27 01:05:10 +0000285 // Cast the pointer to packed to an array of equivalent type
286 Value* array = new BitCastInst(SI.getPointerOperand(), APT,
287 "store.ge.a.", &SI);
288
Reid Spencer42e83fe2004-08-21 21:39:24 +0000289 std::vector<Value*>& values = getValues(SI.getOperand(0));
Misha Brukmanfd939082005-04-21 23:48:37 +0000290
Reid Spencer42e83fe2004-08-21 21:39:24 +0000291 assert((values.size() == PKT->getNumElements()) &&
292 "Scalar must have the same number of elements as Packed Type");
293
294 for (unsigned i = 0, e = PKT->getNumElements(); i != e; ++i) {
295 // Generate the indices for getelementptr
Reid Spencerb83eb642006-10-20 07:07:24 +0000296 Idx[1] = ConstantInt::get(Type::UIntTy,i);
Misha Brukmanfd939082005-04-21 23:48:37 +0000297 Value* val = new GetElementPtrInst(array,
Reid Spencer42e83fe2004-08-21 21:39:24 +0000298 Idx,
299 "store.ge." +
300 utostr(i) + ".",
301 &SI);
302 new StoreInst(values[i], val, SI.isVolatile(),&SI);
303 }
Misha Brukmanfd939082005-04-21 23:48:37 +0000304
Reid Spencer42e83fe2004-08-21 21:39:24 +0000305 Changed = true;
306 instrsToRemove.push_back(&SI);
307 }
308}
309
310void LowerPacked::visitSelectInst(SelectInst& SELI)
311{
312 // Make sure both operands are PackedTypes
313 if (isa<PackedType>(SELI.getType())) {
314 std::vector<Value*>& op0Vals = getValues(SELI.getTrueValue());
315 std::vector<Value*>& op1Vals = getValues(SELI.getFalseValue());
316 std::vector<Value*> result;
317
318 assert((op0Vals.size() == op1Vals.size()) &&
319 "The two packed operand to scalar maps must be equal in size.");
320
321 for (unsigned i = 0; i != op0Vals.size(); ++i) {
322 result.push_back(new SelectInst(SELI.getCondition(),
Misha Brukmanfd939082005-04-21 23:48:37 +0000323 op0Vals[i],
Reid Spencer42e83fe2004-08-21 21:39:24 +0000324 op1Vals[i],
325 SELI.getName()+ "." + utostr(i),
326 &SELI));
327 }
Misha Brukmanfd939082005-04-21 23:48:37 +0000328
Reid Spencer42e83fe2004-08-21 21:39:24 +0000329 setValues(&SELI,result);
330 Changed = true;
331 instrsToRemove.push_back(&SELI);
332 }
333}
334
Robert Bocchino56107e22006-01-10 19:05:05 +0000335void LowerPacked::visitExtractElementInst(ExtractElementInst& EI)
336{
337 std::vector<Value*>& op0Vals = getValues(EI.getOperand(0));
338 const PackedType *PTy = cast<PackedType>(EI.getOperand(0)->getType());
339 Value *op1 = EI.getOperand(1);
340
Reid Spencerb83eb642006-10-20 07:07:24 +0000341 if (ConstantInt *C = dyn_cast<ConstantInt>(op1)) {
342 EI.replaceAllUsesWith(op0Vals[C->getZExtValue()]);
Robert Bocchino56107e22006-01-10 19:05:05 +0000343 } else {
Robert Bocchino8fcf01e2006-01-17 20:06:55 +0000344 AllocaInst *alloca =
345 new AllocaInst(PTy->getElementType(),
Reid Spencerb83eb642006-10-20 07:07:24 +0000346 ConstantInt::get(Type::UIntTy, PTy->getNumElements()),
Robert Bocchino8fcf01e2006-01-17 20:06:55 +0000347 EI.getName() + ".alloca",
348 EI.getParent()->getParent()->getEntryBlock().begin());
Robert Bocchino56107e22006-01-10 19:05:05 +0000349 for (unsigned i = 0; i < PTy->getNumElements(); ++i) {
Robert Bocchino8fcf01e2006-01-17 20:06:55 +0000350 GetElementPtrInst *GEP =
Reid Spencerb83eb642006-10-20 07:07:24 +0000351 new GetElementPtrInst(alloca, ConstantInt::get(Type::UIntTy, i),
Robert Bocchino8fcf01e2006-01-17 20:06:55 +0000352 "store.ge", &EI);
Robert Bocchino56107e22006-01-10 19:05:05 +0000353 new StoreInst(op0Vals[i], GEP, &EI);
354 }
Robert Bocchino8fcf01e2006-01-17 20:06:55 +0000355 GetElementPtrInst *GEP =
356 new GetElementPtrInst(alloca, op1, EI.getName() + ".ge", &EI);
Robert Bocchino56107e22006-01-10 19:05:05 +0000357 LoadInst *load = new LoadInst(GEP, EI.getName() + ".load", &EI);
358 EI.replaceAllUsesWith(load);
359 }
360
361 Changed = true;
362 instrsToRemove.push_back(&EI);
363}
364
Robert Bocchino8fcf01e2006-01-17 20:06:55 +0000365void LowerPacked::visitInsertElementInst(InsertElementInst& IE)
366{
367 std::vector<Value*>& Vals = getValues(IE.getOperand(0));
368 Value *Elt = IE.getOperand(1);
369 Value *Idx = IE.getOperand(2);
370 std::vector<Value*> result;
371 result.reserve(Vals.size());
372
Reid Spencerb83eb642006-10-20 07:07:24 +0000373 if (ConstantInt *C = dyn_cast<ConstantInt>(Idx)) {
374 unsigned idxVal = C->getZExtValue();
Robert Bocchino8fcf01e2006-01-17 20:06:55 +0000375 for (unsigned i = 0; i != Vals.size(); ++i) {
376 result.push_back(i == idxVal ? Elt : Vals[i]);
377 }
378 } else {
379 for (unsigned i = 0; i != Vals.size(); ++i) {
380 SetCondInst *setcc =
381 new SetCondInst(Instruction::SetEQ, Idx,
Reid Spencerb83eb642006-10-20 07:07:24 +0000382 ConstantInt::get(Type::UIntTy, i),
Robert Bocchino8fcf01e2006-01-17 20:06:55 +0000383 "setcc", &IE);
384 SelectInst *select =
385 new SelectInst(setcc, Elt, Vals[i], "select", &IE);
386 result.push_back(select);
387 }
388 }
389
390 setValues(&IE, result);
391 Changed = true;
392 instrsToRemove.push_back(&IE);
393}
394
Reid Spencer42e83fe2004-08-21 21:39:24 +0000395bool LowerPacked::runOnFunction(Function& F)
396{
397 // initialize
Misha Brukmanfd939082005-04-21 23:48:37 +0000398 Changed = false;
399
Reid Spencer42e83fe2004-08-21 21:39:24 +0000400 // Does three passes:
Misha Brukmanfd939082005-04-21 23:48:37 +0000401 // Pass 1) Converts Packed Operations to
Reid Spencer42e83fe2004-08-21 21:39:24 +0000402 // new Packed Operations on smaller
403 // datatypes
404 visit(F);
Misha Brukmanfd939082005-04-21 23:48:37 +0000405
Reid Spencer42e83fe2004-08-21 21:39:24 +0000406 // Pass 2) Drop all references
407 std::for_each(instrsToRemove.begin(),
408 instrsToRemove.end(),
409 std::mem_fun(&Instruction::dropAllReferences));
410
411 // Pass 3) Delete the Instructions to remove aka packed instructions
Misha Brukmanfd939082005-04-21 23:48:37 +0000412 for (std::vector<Instruction*>::iterator i = instrsToRemove.begin(),
413 e = instrsToRemove.end();
Reid Spencer42e83fe2004-08-21 21:39:24 +0000414 i != e; ++i) {
Misha Brukmanfd939082005-04-21 23:48:37 +0000415 (*i)->getParent()->getInstList().erase(*i);
Reid Spencer42e83fe2004-08-21 21:39:24 +0000416 }
417
418 // clean-up
419 packedToScalarMap.clear();
420 instrsToRemove.clear();
421
422 return Changed;
423}
424