blob: 45ed8b43fdd0715c2752687e6f351101d48a84f3 [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
62 /// This function asserts if the instruction is a PackedType but
63 /// is handled by another function.
Misha Brukmanb1c93172005-04-21 23:48:37 +000064 ///
Reid Spencerf39f66e2004-08-21 21:39:24 +000065 /// @brief Asserts if PackedType instruction is not handled elsewhere.
66 /// @param I the unhandled instruction
67 void visitInstruction(Instruction &I)
68 {
69 if(isa<PackedType>(I.getType())) {
Misha Brukmanb1c93172005-04-21 23:48:37 +000070 std::cerr << "Unhandled Instruction with Packed ReturnType: " <<
Reid Spencerf39f66e2004-08-21 21:39:24 +000071 I << '\n';
72 }
73 }
74private:
75 /// @brief Retrieves lowered values for a packed value.
76 /// @param val the packed value
77 /// @return the lowered values
78 std::vector<Value*>& getValues(Value* val);
79
80 /// @brief Sets lowered values for a packed value.
81 /// @param val the packed value
82 /// @param values the corresponding lowered values
83 void setValues(Value* val,const std::vector<Value*>& values);
84
85 // Data Members
Misha Brukmanb1c93172005-04-21 23:48:37 +000086 /// @brief whether we changed the function or not
Reid Spencerf39f66e2004-08-21 21:39:24 +000087 bool Changed;
88
89 /// @brief a map from old packed values to new smaller packed values
90 std::map<Value*,std::vector<Value*> > packedToScalarMap;
91
92 /// Instructions in the source program to get rid of
93 /// after we do a pass (the old packed instructions)
94 std::vector<Instruction*> instrsToRemove;
Misha Brukmanb1c93172005-04-21 23:48:37 +000095};
Reid Spencerf39f66e2004-08-21 21:39:24 +000096
Misha Brukmanb1c93172005-04-21 23:48:37 +000097RegisterOpt<LowerPacked>
98X("lower-packed",
Reid Spencerf39f66e2004-08-21 21:39:24 +000099 "lowers packed operations to operations on smaller packed datatypes");
100
Misha Brukmanb1c93172005-04-21 23:48:37 +0000101} // end namespace
Reid Spencerf39f66e2004-08-21 21:39:24 +0000102
Chris Lattner446948e2004-11-19 16:49:34 +0000103FunctionPass *llvm::createLowerPackedPass() { return new LowerPacked(); }
Chris Lattnerc08ac112004-11-18 17:24:20 +0000104
105
Reid Spencerf39f66e2004-08-21 21:39:24 +0000106// This function sets lowered values for a corresponding
107// packed value. Note, in the case of a forward reference
Misha Brukmanb1c93172005-04-21 23:48:37 +0000108// getValues(Value*) will have already been called for
109// the packed parameter. This function will then replace
110// all references in the in the function of the "dummy"
111// value the previous getValues(Value*) call
Reid Spencerf39f66e2004-08-21 21:39:24 +0000112// returned with actual references.
113void LowerPacked::setValues(Value* value,const std::vector<Value*>& values)
114{
Misha Brukmanb1c93172005-04-21 23:48:37 +0000115 std::map<Value*,std::vector<Value*> >::iterator it =
Reid Spencerf39f66e2004-08-21 21:39:24 +0000116 packedToScalarMap.lower_bound(value);
117 if (it == packedToScalarMap.end() || it->first != value) {
118 // there was not a forward reference to this element
119 packedToScalarMap.insert(it,std::make_pair(value,values));
120 }
121 else {
122 // replace forward declarations with actual definitions
Misha Brukmanb1c93172005-04-21 23:48:37 +0000123 assert(it->second.size() == values.size() &&
Reid Spencerf39f66e2004-08-21 21:39:24 +0000124 "Error forward refences and actual definition differ in size");
125 for (unsigned i = 0, e = values.size(); i != e; ++i) {
126 // replace and get rid of old forward references
127 it->second[i]->replaceAllUsesWith(values[i]);
128 delete it->second[i];
129 it->second[i] = values[i];
130 }
131 }
132}
133
134// This function will examine the packed value parameter
135// and if it is a packed constant or a forward reference
136// properly create the lowered values needed. Otherwise
Misha Brukmanb1c93172005-04-21 23:48:37 +0000137// it will simply retreive values from a
138// setValues(Value*,const std::vector<Value*>&)
Reid Spencerf39f66e2004-08-21 21:39:24 +0000139// call. Failing both of these cases, it will abort
140// the program.
141std::vector<Value*>& LowerPacked::getValues(Value* value)
142{
143 assert(isa<PackedType>(value->getType()) &&
144 "Value must be PackedType");
145
146 // reject further processing if this one has
147 // already been handled
Misha Brukmanb1c93172005-04-21 23:48:37 +0000148 std::map<Value*,std::vector<Value*> >::iterator it =
Reid Spencerf39f66e2004-08-21 21:39:24 +0000149 packedToScalarMap.lower_bound(value);
150 if (it != packedToScalarMap.end() && it->first == value) {
151 return it->second;
152 }
153
154 if (ConstantPacked* CP = dyn_cast<ConstantPacked>(value)) {
155 // non-zero constant case
156 std::vector<Value*> results;
157 results.reserve(CP->getNumOperands());
158 for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) {
159 results.push_back(CP->getOperand(i));
160 }
161 return packedToScalarMap.insert(it,
162 std::make_pair(value,results))->second;
163 }
164 else if (ConstantAggregateZero* CAZ =
165 dyn_cast<ConstantAggregateZero>(value)) {
Misha Brukmanb1c93172005-04-21 23:48:37 +0000166 // zero constant
Reid Spencerf39f66e2004-08-21 21:39:24 +0000167 const PackedType* PKT = cast<PackedType>(CAZ->getType());
168 std::vector<Value*> results;
169 results.reserve(PKT->getNumElements());
Misha Brukmanb1c93172005-04-21 23:48:37 +0000170
Reid Spencerf39f66e2004-08-21 21:39:24 +0000171 Constant* C = Constant::getNullValue(PKT->getElementType());
172 for (unsigned i = 0, e = PKT->getNumElements(); i != e; ++i) {
173 results.push_back(C);
174 }
175 return packedToScalarMap.insert(it,
176 std::make_pair(value,results))->second;
177 }
178 else if (isa<Instruction>(value)) {
179 // foward reference
180 const PackedType* PKT = cast<PackedType>(value->getType());
181 std::vector<Value*> results;
182 results.reserve(PKT->getNumElements());
Misha Brukmanb1c93172005-04-21 23:48:37 +0000183
Reid Spencerf39f66e2004-08-21 21:39:24 +0000184 for (unsigned i = 0, e = PKT->getNumElements(); i != e; ++i) {
185 results.push_back(new Argument(PKT->getElementType()));
186 }
187 return packedToScalarMap.insert(it,
188 std::make_pair(value,results))->second;
189 }
190 else {
191 // we don't know what it is, and we are trying to retrieve
192 // a value for it
193 assert(false && "Unhandled PackedType value");
194 abort();
195 }
196}
197
198void LowerPacked::visitLoadInst(LoadInst& LI)
199{
200 // Make sure what we are dealing with is a packed type
201 if (const PackedType* PKT = dyn_cast<PackedType>(LI.getType())) {
202 // Initialization, Idx is needed for getelementptr needed later
203 std::vector<Value*> Idx(2);
204 Idx[0] = ConstantUInt::get(Type::UIntTy,0);
205
206 ArrayType* AT = ArrayType::get(PKT->getContainedType(0),
207 PKT->getNumElements());
208 PointerType* APT = PointerType::get(AT);
209
210 // Cast the packed type to an array
211 Value* array = new CastInst(LI.getPointerOperand(),
212 APT,
213 LI.getName() + ".a",
214 &LI);
215
216 // Convert this load into num elements number of loads
217 std::vector<Value*> values;
218 values.reserve(PKT->getNumElements());
219
220 for (unsigned i = 0, e = PKT->getNumElements(); i != e; ++i) {
221 // Calculate the second index we will need
222 Idx[1] = ConstantUInt::get(Type::UIntTy,i);
223
224 // Get the pointer
Misha Brukmanb1c93172005-04-21 23:48:37 +0000225 Value* val = new GetElementPtrInst(array,
Reid Spencerf39f66e2004-08-21 21:39:24 +0000226 Idx,
Misha Brukmanb1c93172005-04-21 23:48:37 +0000227 LI.getName() +
Reid Spencerf39f66e2004-08-21 21:39:24 +0000228 ".ge." + utostr(i),
229 &LI);
230
231 // generate the new load and save the result in packedToScalar map
Misha Brukmanb1c93172005-04-21 23:48:37 +0000232 values.push_back(new LoadInst(val,
Reid Spencerf39f66e2004-08-21 21:39:24 +0000233 LI.getName()+"."+utostr(i),
234 LI.isVolatile(),
235 &LI));
236 }
Misha Brukmanb1c93172005-04-21 23:48:37 +0000237
Reid Spencerf39f66e2004-08-21 21:39:24 +0000238 setValues(&LI,values);
239 Changed = true;
240 instrsToRemove.push_back(&LI);
241 }
242}
243
244void LowerPacked::visitBinaryOperator(BinaryOperator& BO)
245{
246 // Make sure both operands are PackedTypes
247 if (isa<PackedType>(BO.getOperand(0)->getType())) {
248 std::vector<Value*>& op0Vals = getValues(BO.getOperand(0));
249 std::vector<Value*>& op1Vals = getValues(BO.getOperand(1));
250 std::vector<Value*> result;
251 assert((op0Vals.size() == op1Vals.size()) &&
252 "The two packed operand to scalar maps must be equal in size.");
253
254 result.reserve(op0Vals.size());
Misha Brukmanb1c93172005-04-21 23:48:37 +0000255
Reid Spencerf39f66e2004-08-21 21:39:24 +0000256 // generate the new binary op and save the result
257 for (unsigned i = 0; i != op0Vals.size(); ++i) {
Misha Brukmanb1c93172005-04-21 23:48:37 +0000258 result.push_back(BinaryOperator::create(BO.getOpcode(),
259 op0Vals[i],
Reid Spencerf39f66e2004-08-21 21:39:24 +0000260 op1Vals[i],
Misha Brukmanb1c93172005-04-21 23:48:37 +0000261 BO.getName() +
Reid Spencerf39f66e2004-08-21 21:39:24 +0000262 "." + utostr(i),
263 &BO));
264 }
265
266 setValues(&BO,result);
267 Changed = true;
268 instrsToRemove.push_back(&BO);
269 }
270}
271
272void LowerPacked::visitStoreInst(StoreInst& SI)
273{
Misha Brukmanb1c93172005-04-21 23:48:37 +0000274 if (const PackedType* PKT =
Reid Spencerf39f66e2004-08-21 21:39:24 +0000275 dyn_cast<PackedType>(SI.getOperand(0)->getType())) {
276 // We will need this for getelementptr
277 std::vector<Value*> Idx(2);
278 Idx[0] = ConstantUInt::get(Type::UIntTy,0);
Misha Brukmanb1c93172005-04-21 23:48:37 +0000279
Reid Spencerf39f66e2004-08-21 21:39:24 +0000280 ArrayType* AT = ArrayType::get(PKT->getContainedType(0),
281 PKT->getNumElements());
282 PointerType* APT = PointerType::get(AT);
283
284 // cast the packed to an array type
285 Value* array = new CastInst(SI.getPointerOperand(),
286 APT,
287 "store.ge.a.",
288 &SI);
289 std::vector<Value*>& values = getValues(SI.getOperand(0));
Misha Brukmanb1c93172005-04-21 23:48:37 +0000290
Reid Spencerf39f66e2004-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
296 Idx[1] = ConstantUInt::get(Type::UIntTy,i);
Misha Brukmanb1c93172005-04-21 23:48:37 +0000297 Value* val = new GetElementPtrInst(array,
Reid Spencerf39f66e2004-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 Brukmanb1c93172005-04-21 23:48:37 +0000304
Reid Spencerf39f66e2004-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 Brukmanb1c93172005-04-21 23:48:37 +0000323 op0Vals[i],
Reid Spencerf39f66e2004-08-21 21:39:24 +0000324 op1Vals[i],
325 SELI.getName()+ "." + utostr(i),
326 &SELI));
327 }
Misha Brukmanb1c93172005-04-21 23:48:37 +0000328
Reid Spencerf39f66e2004-08-21 21:39:24 +0000329 setValues(&SELI,result);
330 Changed = true;
331 instrsToRemove.push_back(&SELI);
332 }
333}
334
335bool LowerPacked::runOnFunction(Function& F)
336{
337 // initialize
Misha Brukmanb1c93172005-04-21 23:48:37 +0000338 Changed = false;
339
Reid Spencerf39f66e2004-08-21 21:39:24 +0000340 // Does three passes:
Misha Brukmanb1c93172005-04-21 23:48:37 +0000341 // Pass 1) Converts Packed Operations to
Reid Spencerf39f66e2004-08-21 21:39:24 +0000342 // new Packed Operations on smaller
343 // datatypes
344 visit(F);
Misha Brukmanb1c93172005-04-21 23:48:37 +0000345
Reid Spencerf39f66e2004-08-21 21:39:24 +0000346 // Pass 2) Drop all references
347 std::for_each(instrsToRemove.begin(),
348 instrsToRemove.end(),
349 std::mem_fun(&Instruction::dropAllReferences));
350
351 // Pass 3) Delete the Instructions to remove aka packed instructions
Misha Brukmanb1c93172005-04-21 23:48:37 +0000352 for (std::vector<Instruction*>::iterator i = instrsToRemove.begin(),
353 e = instrsToRemove.end();
Reid Spencerf39f66e2004-08-21 21:39:24 +0000354 i != e; ++i) {
Misha Brukmanb1c93172005-04-21 23:48:37 +0000355 (*i)->getParent()->getInstList().erase(*i);
Reid Spencerf39f66e2004-08-21 21:39:24 +0000356 }
357
358 // clean-up
359 packedToScalarMap.clear();
360 instrsToRemove.clear();
361
362 return Changed;
363}
364