* Add support for different "PassType's"
[oota-llvm.git] / lib / Transforms / Scalar / DecomposeMultiDimRefs.cpp
1 //===- llvm/Transforms/DecomposeMultiDimRefs.cpp - Lower array refs to 1D -===//
2 //
3 // DecomposeMultiDimRefs - Convert multi-dimensional references consisting of
4 // any combination of 2 or more array and structure indices into a sequence of
5 // instructions (using getelementpr and cast) so that each instruction has at
6 // most one index (except structure references, which need an extra leading
7 // index of [0]).
8 //
9 //===----------------------------------------------------------------------===//
10
11 #include "llvm/Transforms/Scalar.h"
12 #include "llvm/DerivedTypes.h"
13 #include "llvm/Constant.h"
14 #include "llvm/iMemory.h"
15 #include "llvm/iOther.h"
16 #include "llvm/BasicBlock.h"
17 #include "llvm/Pass.h"
18 #include "Support/StatisticReporter.h"
19
20 static Statistic<> NumAdded("lowerrefs\t\t- New instructions added");
21
22 namespace {
23   struct DecomposePass : public BasicBlockPass {
24     virtual bool runOnBasicBlock(BasicBlock &BB);
25
26   private:
27     static void decomposeArrayRef(BasicBlock::iterator &BBI);
28   };
29
30   RegisterOpt<DecomposePass> X("lowerrefs", "Decompose multi-dimensional "
31                                "structure/array references");
32 }
33
34 Pass *createDecomposeMultiDimRefsPass() {
35   return new DecomposePass();
36 }
37
38
39 // runOnBasicBlock - Entry point for array or structure references with multiple
40 // indices.
41 //
42 bool DecomposePass::runOnBasicBlock(BasicBlock &BB) {
43   bool Changed = false;
44   for (BasicBlock::iterator II = BB.begin(); II != BB.end(); ) {
45     if (MemAccessInst *MAI = dyn_cast<MemAccessInst>(&*II)) {
46       if (MAI->getNumOperands() > MAI->getFirstIndexOperandNumber()+1) {
47         decomposeArrayRef(II);
48         Changed = true;
49       } else {
50         ++II;
51       }
52     } else {
53       ++II;
54     }
55   }
56   
57   return Changed;
58 }
59
60 // 
61 // For any combination of 2 or more array and structure indices,
62 // this function repeats the foll. until we have a one-dim. reference: {
63 //      ptr1 = getElementPtr [CompositeType-N] * lastPtr, uint firstIndex
64 //      ptr2 = cast [CompositeType-N] * ptr1 to [CompositeType-N] *
65 // }
66 // Then it replaces the original instruction with an equivalent one that
67 // uses the last ptr2 generated in the loop and a single index.
68 // If any index is (uint) 0, we omit the getElementPtr instruction.
69 // 
70
71 void DecomposePass::decomposeArrayRef(BasicBlock::iterator &BBI) {
72   MemAccessInst &MAI = cast<MemAccessInst>(*BBI);
73   BasicBlock *BB = MAI.getParent();
74   Value *LastPtr = MAI.getPointerOperand();
75
76   // Remove the instruction from the stream
77   BB->getInstList().remove(BBI);
78
79   std::vector<Instruction*> NewInsts;
80   
81   // Process each index except the last one.
82   // 
83
84   User::const_op_iterator OI = MAI.idx_begin(), OE = MAI.idx_end();
85   for (; OI+1 != OE; ++OI) {
86     assert(isa<PointerType>(LastPtr->getType()));
87       
88     // Check for a zero index.  This will need a cast instead of
89     // a getElementPtr, or it may need neither.
90     bool indexIsZero = isa<Constant>(*OI) && 
91                        cast<Constant>(OI->get())->isNullValue() &&
92                        OI->get()->getType() == Type::UIntTy;
93       
94     // Extract the first index.  If the ptr is a pointer to a structure
95     // and the next index is a structure offset (i.e., not an array offset), 
96     // we need to include an initial [0] to index into the pointer.
97     //
98
99     std::vector<Value*> Indices;
100     const PointerType *PtrTy = cast<PointerType>(LastPtr->getType());
101
102     if (isa<StructType>(PtrTy->getElementType())
103         && !PtrTy->indexValid(*OI))
104       Indices.push_back(Constant::getNullValue(Type::UIntTy));
105     Indices.push_back(*OI);
106
107     // Get the type obtained by applying the first index.
108     // It must be a structure or array.
109     const Type *NextTy = MemAccessInst::getIndexedType(LastPtr->getType(),
110                                                        Indices, true);
111     assert(isa<CompositeType>(NextTy));
112     
113     // Get a pointer to the structure or to the elements of the array.
114     const Type *NextPtrTy =
115       PointerType::get(isa<StructType>(NextTy) ? NextTy
116                        : cast<ArrayType>(NextTy)->getElementType());
117       
118     // Instruction 1: nextPtr1 = GetElementPtr LastPtr, Indices
119     // This is not needed if the index is zero.
120     if (!indexIsZero) {
121       LastPtr = new GetElementPtrInst(LastPtr, Indices, "ptr1");
122       NewInsts.push_back(cast<Instruction>(LastPtr));
123       ++NumAdded;
124     }
125
126       
127     // Instruction 2: nextPtr2 = cast nextPtr1 to NextPtrTy
128     // This is not needed if the two types are identical.
129     //
130     if (LastPtr->getType() != NextPtrTy) {
131       LastPtr = new CastInst(LastPtr, NextPtrTy, "ptr2");
132       NewInsts.push_back(cast<Instruction>(LastPtr));
133       ++NumAdded;
134     }
135   }
136   
137   // 
138   // Now create a new instruction to replace the original one
139   //
140   const PointerType *PtrTy = cast<PointerType>(LastPtr->getType());
141
142   // First, get the final index vector.  As above, we may need an initial [0].
143
144   std::vector<Value*> Indices;
145   if (isa<StructType>(PtrTy->getElementType())
146       && !PtrTy->indexValid(*OI))
147     Indices.push_back(Constant::getNullValue(Type::UIntTy));
148
149   Indices.push_back(*OI);
150
151   Instruction *NewI = 0;
152   switch(MAI.getOpcode()) {
153   case Instruction::Load:
154     NewI = new LoadInst(LastPtr, Indices, MAI.getName());
155     break;
156   case Instruction::Store:
157     NewI = new StoreInst(MAI.getOperand(0), LastPtr, Indices);
158     break;
159   case Instruction::GetElementPtr:
160     NewI = new GetElementPtrInst(LastPtr, Indices, MAI.getName());
161     break;
162   default:
163     assert(0 && "Unrecognized memory access instruction");
164   }
165   NewInsts.push_back(NewI);
166
167   
168   // Replace all uses of the old instruction with the new
169   MAI.replaceAllUsesWith(NewI);
170
171   // Now delete the old instruction...
172   delete &MAI;
173
174   // Insert all of the new instructions...
175   BB->getInstList().insert(BBI, NewInsts.begin(), NewInsts.end());
176   
177   // Advance the iterator to the instruction following the one just inserted...
178   BBI = NewInsts.back();
179   ++BBI;
180 }