Chris Lattner | f4066b3 | 2002-03-27 19:45:12 +0000 | [diff] [blame] | 1 | //===- FunctionRepBuilder.cpp - Build the local datastructure graph -------===// |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 2 | // |
| 3 | // Build the local datastructure graph for a single method. |
| 4 | // |
| 5 | //===----------------------------------------------------------------------===// |
| 6 | |
| 7 | #include "FunctionRepBuilder.h" |
| 8 | #include "llvm/Function.h" |
Chris Lattner | 42a4127 | 2002-04-09 18:37:46 +0000 | [diff] [blame] | 9 | #include "llvm/BasicBlock.h" |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 10 | #include "llvm/iMemory.h" |
| 11 | #include "llvm/iPHINode.h" |
| 12 | #include "llvm/iOther.h" |
| 13 | #include "llvm/iTerminators.h" |
| 14 | #include "llvm/DerivedTypes.h" |
Chris Lattner | 31bcdb8 | 2002-04-28 19:55:58 +0000 | [diff] [blame] | 15 | #include "llvm/Constants.h" |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 16 | #include "Support/STLExtras.h" |
| 17 | #include <algorithm> |
Anand Shukla | a928403 | 2002-06-25 20:35:19 +0000 | [diff] [blame^] | 18 | #include <iostream> |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 19 | |
| 20 | // synthesizeNode - Create a new shadow node that is to be linked into this |
| 21 | // chain.. |
| 22 | // FIXME: This should not take a FunctionRepBuilder as an argument! |
| 23 | // |
Chris Lattner | fe14568 | 2002-04-17 03:24:59 +0000 | [diff] [blame] | 24 | ShadowDSNode *DSNode::synthesizeNode(const Type *Ty, |
| 25 | FunctionRepBuilder *Rep) { |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 26 | // If we are a derived shadow node, defer to our parent to synthesize the node |
Chris Lattner | fe14568 | 2002-04-17 03:24:59 +0000 | [diff] [blame] | 27 | if (ShadowDSNode *Th = dyn_cast<ShadowDSNode>(this)) |
| 28 | if (Th->getShadowParent()) |
| 29 | return Th->getShadowParent()->synthesizeNode(Ty, Rep); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 30 | |
| 31 | // See if we have already synthesized a node of this type... |
| 32 | for (unsigned i = 0, e = SynthNodes.size(); i != e; ++i) |
| 33 | if (SynthNodes[i].first == Ty) return SynthNodes[i].second; |
| 34 | |
| 35 | // No we haven't. Do so now and add it to our list of saved nodes... |
Anand Shukla | a928403 | 2002-06-25 20:35:19 +0000 | [diff] [blame^] | 36 | |
Chris Lattner | fe14568 | 2002-04-17 03:24:59 +0000 | [diff] [blame] | 37 | ShadowDSNode *SN = Rep->makeSynthesizedShadow(Ty, this); |
Anand Shukla | a928403 | 2002-06-25 20:35:19 +0000 | [diff] [blame^] | 38 | SynthNodes.push_back(std::make_pair(Ty, SN)); |
| 39 | |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 40 | return SN; |
| 41 | } |
| 42 | |
Chris Lattner | fe14568 | 2002-04-17 03:24:59 +0000 | [diff] [blame] | 43 | ShadowDSNode *FunctionRepBuilder::makeSynthesizedShadow(const Type *Ty, |
| 44 | DSNode *Parent) { |
| 45 | ShadowDSNode *Result = new ShadowDSNode(Ty, F->getFunction()->getParent(), |
| 46 | Parent); |
| 47 | ShadowNodes.push_back(Result); |
| 48 | return Result; |
| 49 | } |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 50 | |
| 51 | |
| 52 | |
| 53 | // visitOperand - If the specified instruction operand is a global value, add |
| 54 | // a node for it... |
| 55 | // |
| 56 | void InitVisitor::visitOperand(Value *V) { |
| 57 | if (!Rep->ValueMap.count(V)) // Only process it once... |
| 58 | if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) { |
| 59 | GlobalDSNode *N = new GlobalDSNode(GV); |
Chris Lattner | 1120c8b | 2002-03-28 17:56:03 +0000 | [diff] [blame] | 60 | Rep->GlobalNodes.push_back(N); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 61 | Rep->ValueMap[V].add(N); |
| 62 | Rep->addAllUsesToWorkList(GV); |
Chris Lattner | f4066b3 | 2002-03-27 19:45:12 +0000 | [diff] [blame] | 63 | |
| 64 | // FIXME: If the global variable has fields, we should add critical |
| 65 | // shadow nodes to represent them! |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 66 | } |
| 67 | } |
| 68 | |
| 69 | |
| 70 | // visitCallInst - Create a call node for the callinst, and create as shadow |
| 71 | // node if the call returns a pointer value. Check to see if the call node |
| 72 | // uses any global variables... |
| 73 | // |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 74 | void InitVisitor::visitCallInst(CallInst &CI) { |
| 75 | CallDSNode *C = new CallDSNode(&CI); |
Chris Lattner | 1120c8b | 2002-03-28 17:56:03 +0000 | [diff] [blame] | 76 | Rep->CallNodes.push_back(C); |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 77 | Rep->CallMap[&CI] = C; |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 78 | |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 79 | if (const PointerType *PT = dyn_cast<PointerType>(CI.getType())) { |
Chris Lattner | f4066b3 | 2002-03-27 19:45:12 +0000 | [diff] [blame] | 80 | // Create a critical shadow node to represent the memory object that the |
| 81 | // return value points to... |
Chris Lattner | 3feaf02 | 2002-04-01 00:14:41 +0000 | [diff] [blame] | 82 | ShadowDSNode *Shad = new ShadowDSNode(PT->getElementType(), |
Chris Lattner | 7650b94 | 2002-04-16 20:39:59 +0000 | [diff] [blame] | 83 | Func->getParent()); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 84 | Rep->ShadowNodes.push_back(Shad); |
| 85 | |
| 86 | // The return value of the function is a pointer to the shadow value |
| 87 | // just created... |
| 88 | // |
| 89 | C->getLink(0).add(Shad); |
| 90 | |
| 91 | // The call instruction returns a pointer to the shadow block... |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 92 | Rep->ValueMap[&CI].add(Shad, &CI); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 93 | |
| 94 | // If the call returns a value with pointer type, add all of the users |
| 95 | // of the call instruction to the work list... |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 96 | Rep->addAllUsesToWorkList(&CI); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 97 | } |
| 98 | |
| 99 | // Loop over all of the operands of the call instruction (except the first |
| 100 | // one), to look for global variable references... |
| 101 | // |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 102 | for_each(CI.op_begin(), CI.op_end(), |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 103 | bind_obj(this, &InitVisitor::visitOperand)); |
| 104 | } |
| 105 | |
| 106 | |
| 107 | // visitAllocationInst - Create an allocation node for the allocation. Since |
| 108 | // allocation instructions do not take pointer arguments, they cannot refer to |
| 109 | // global vars... |
| 110 | // |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 111 | void InitVisitor::visitAllocationInst(AllocationInst &AI) { |
| 112 | AllocDSNode *N = new AllocDSNode(&AI); |
Chris Lattner | 1120c8b | 2002-03-28 17:56:03 +0000 | [diff] [blame] | 113 | Rep->AllocNodes.push_back(N); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 114 | |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 115 | Rep->ValueMap[&AI].add(N, &AI); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 116 | |
| 117 | // Add all of the users of the malloc instruction to the work list... |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 118 | Rep->addAllUsesToWorkList(&AI); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 119 | } |
| 120 | |
| 121 | |
| 122 | // Visit all other instruction types. Here we just scan, looking for uses of |
| 123 | // global variables... |
| 124 | // |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 125 | void InitVisitor::visitInstruction(Instruction &I) { |
| 126 | for_each(I.op_begin(), I.op_end(), |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 127 | bind_obj(this, &InitVisitor::visitOperand)); |
| 128 | } |
| 129 | |
| 130 | |
| 131 | // addAllUsesToWorkList - Add all of the instructions users of the specified |
| 132 | // value to the work list for further processing... |
| 133 | // |
| 134 | void FunctionRepBuilder::addAllUsesToWorkList(Value *V) { |
| 135 | //cerr << "Adding all uses of " << V << "\n"; |
| 136 | for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) { |
| 137 | Instruction *Inst = cast<Instruction>(*I); |
| 138 | // When processing global values, it's possible that the instructions on |
| 139 | // the use list are not all in this method. Only add the instructions |
| 140 | // that _are_ in this method. |
| 141 | // |
| 142 | if (Inst->getParent()->getParent() == F->getFunction()) |
| 143 | // Only let an instruction occur on the work list once... |
| 144 | if (std::find(WorkList.begin(), WorkList.end(), Inst) == WorkList.end()) |
| 145 | WorkList.push_back(Inst); |
| 146 | } |
| 147 | } |
| 148 | |
| 149 | |
| 150 | |
| 151 | |
| 152 | void FunctionRepBuilder::initializeWorkList(Function *Func) { |
| 153 | // Add all of the arguments to the method to the graph and add all users to |
| 154 | // the worklists... |
| 155 | // |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 156 | for (Function::aiterator I = Func->abegin(), E = Func->aend(); I != E; ++I) { |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 157 | // Only process arguments that are of pointer type... |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 158 | if (const PointerType *PT = dyn_cast<PointerType>(I->getType())) { |
Chris Lattner | 212be2e | 2002-04-16 03:44:03 +0000 | [diff] [blame] | 159 | // Add a shadow value for it to represent what it is pointing to and add |
| 160 | // this to the value map... |
Chris Lattner | 3feaf02 | 2002-04-01 00:14:41 +0000 | [diff] [blame] | 161 | ShadowDSNode *Shad = new ShadowDSNode(PT->getElementType(), |
Chris Lattner | 7650b94 | 2002-04-16 20:39:59 +0000 | [diff] [blame] | 162 | Func->getParent()); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 163 | ShadowNodes.push_back(Shad); |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 164 | ValueMap[I].add(PointerVal(Shad), I); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 165 | |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 166 | // Make sure that all users of the argument are processed... |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 167 | addAllUsesToWorkList(I); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 168 | } |
Chris Lattner | 73e2142 | 2002-04-09 19:48:49 +0000 | [diff] [blame] | 169 | } |
| 170 | |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 171 | // Iterate over the instructions in the method. Create nodes for malloc and |
| 172 | // call instructions. Add all uses of these to the worklist of instructions |
| 173 | // to process. |
| 174 | // |
| 175 | InitVisitor IV(this, Func); |
| 176 | IV.visit(Func); |
| 177 | } |
| 178 | |
| 179 | |
| 180 | |
| 181 | |
| 182 | PointerVal FunctionRepBuilder::getIndexedPointerDest(const PointerVal &InP, |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 183 | const MemAccessInst &MAI) { |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 184 | unsigned Index = InP.Index; |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 185 | const Type *SrcTy = MAI.getPointerOperand()->getType(); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 186 | |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 187 | for (MemAccessInst::const_op_iterator I = MAI.idx_begin(), |
| 188 | E = MAI.idx_end(); I != E; ++I) |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 189 | if ((*I)->getType() == Type::UByteTy) { // Look for struct indices... |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 190 | const StructType *STy = cast<StructType>(SrcTy); |
| 191 | unsigned StructIdx = cast<ConstantUInt>(I->get())->getValue(); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 192 | for (unsigned i = 0; i != StructIdx; ++i) |
| 193 | Index += countPointerFields(STy->getContainedType(i)); |
| 194 | |
| 195 | // Advance SrcTy to be the new element type... |
| 196 | SrcTy = STy->getContainedType(StructIdx); |
| 197 | } else { |
| 198 | // Otherwise, stepping into array or initial pointer, just increment type |
| 199 | SrcTy = cast<SequentialType>(SrcTy)->getElementType(); |
| 200 | } |
| 201 | |
| 202 | return PointerVal(InP.Node, Index); |
| 203 | } |
| 204 | |
| 205 | static PointerValSet &getField(const PointerVal &DestPtr) { |
| 206 | assert(DestPtr.Node != 0); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 207 | return DestPtr.Node->getLink(DestPtr.Index); |
| 208 | } |
| 209 | |
| 210 | |
| 211 | // Reprocessing a GEP instruction is the result of the pointer operand |
| 212 | // changing. This means that the set of possible values for the GEP |
| 213 | // needs to be expanded. |
| 214 | // |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 215 | void FunctionRepBuilder::visitGetElementPtrInst(GetElementPtrInst &GEP) { |
| 216 | PointerValSet &GEPPVS = ValueMap[&GEP]; // PointerValSet to expand |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 217 | |
| 218 | // Get the input pointer val set... |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 219 | const PointerValSet &SrcPVS = ValueMap[GEP.getOperand(0)]; |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 220 | |
| 221 | bool Changed = false; // Process each input value... propogating it. |
| 222 | for (unsigned i = 0, e = SrcPVS.size(); i != e; ++i) { |
| 223 | // Calculate where the resulting pointer would point based on an |
| 224 | // input of 'Val' as the pointer type... and add it to our outgoing |
| 225 | // value set. Keep track of whether or not we actually changed |
| 226 | // anything. |
| 227 | // |
| 228 | Changed |= GEPPVS.add(getIndexedPointerDest(SrcPVS[i], GEP)); |
| 229 | } |
| 230 | |
| 231 | // If our current value set changed, notify all of the users of our |
| 232 | // value. |
| 233 | // |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 234 | if (Changed) addAllUsesToWorkList(&GEP); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 235 | } |
| 236 | |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 237 | void FunctionRepBuilder::visitReturnInst(ReturnInst &RI) { |
| 238 | RetNode.add(ValueMap[RI.getOperand(0)]); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 239 | } |
| 240 | |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 241 | void FunctionRepBuilder::visitLoadInst(LoadInst &LI) { |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 242 | // Only loads that return pointers are interesting... |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 243 | const PointerType *DestTy = dyn_cast<PointerType>(LI.getType()); |
Chris Lattner | fe14568 | 2002-04-17 03:24:59 +0000 | [diff] [blame] | 244 | if (DestTy == 0) return; |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 245 | |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 246 | const PointerValSet &SrcPVS = ValueMap[LI.getOperand(0)]; |
| 247 | PointerValSet &LIPVS = ValueMap[&LI]; |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 248 | |
| 249 | bool Changed = false; |
| 250 | for (unsigned si = 0, se = SrcPVS.size(); si != se; ++si) { |
| 251 | PointerVal Ptr = getIndexedPointerDest(SrcPVS[si], LI); |
| 252 | PointerValSet &Field = getField(Ptr); |
| 253 | |
| 254 | if (Field.size()) { // Field loaded wasn't null? |
| 255 | Changed |= LIPVS.add(Field); |
Chris Lattner | fe14568 | 2002-04-17 03:24:59 +0000 | [diff] [blame] | 256 | } else { |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 257 | // If we are loading a null field out of a shadow node, we need to |
| 258 | // synthesize a new shadow node and link it in... |
| 259 | // |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 260 | ShadowDSNode *SynthNode = |
Chris Lattner | fe14568 | 2002-04-17 03:24:59 +0000 | [diff] [blame] | 261 | Ptr.Node->synthesizeNode(DestTy->getElementType(), this); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 262 | Field.add(SynthNode); |
| 263 | |
| 264 | Changed |= LIPVS.add(Field); |
| 265 | } |
| 266 | } |
| 267 | |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 268 | if (Changed) addAllUsesToWorkList(&LI); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 269 | } |
| 270 | |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 271 | void FunctionRepBuilder::visitStoreInst(StoreInst &SI) { |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 272 | // The only stores that are interesting are stores the store pointers |
| 273 | // into data structures... |
| 274 | // |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 275 | if (!isa<PointerType>(SI.getOperand(0)->getType())) return; |
| 276 | if (!ValueMap.count(SI.getOperand(0))) return; // Src scalar has no values! |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 277 | |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 278 | const PointerValSet &SrcPVS = ValueMap[SI.getOperand(0)]; |
| 279 | const PointerValSet &PtrPVS = ValueMap[SI.getOperand(1)]; |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 280 | |
| 281 | for (unsigned si = 0, se = SrcPVS.size(); si != se; ++si) { |
| 282 | const PointerVal &SrcPtr = SrcPVS[si]; |
| 283 | for (unsigned pi = 0, pe = PtrPVS.size(); pi != pe; ++pi) { |
| 284 | PointerVal Dest = getIndexedPointerDest(PtrPVS[pi], SI); |
| 285 | |
| 286 | #if 0 |
Anand Shukla | a928403 | 2002-06-25 20:35:19 +0000 | [diff] [blame^] | 287 | std::cerr << "Setting Dest:\n"; |
| 288 | Dest.print(std::cerr); |
| 289 | std::cerr << "to point to Src:\n"; |
| 290 | SrcPtr.print(std::cerr); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 291 | #endif |
| 292 | |
| 293 | // Add SrcPtr into the Dest field... |
| 294 | if (getField(Dest).add(SrcPtr)) { |
| 295 | // If we modified the dest field, then invalidate everyone that points |
| 296 | // to Dest. |
| 297 | const std::vector<Value*> &Ptrs = Dest.Node->getPointers(); |
| 298 | for (unsigned i = 0, e = Ptrs.size(); i != e; ++i) |
| 299 | addAllUsesToWorkList(Ptrs[i]); |
| 300 | } |
| 301 | } |
| 302 | } |
| 303 | } |
| 304 | |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 305 | void FunctionRepBuilder::visitCallInst(CallInst &CI) { |
| 306 | CallDSNode *DSN = CallMap[&CI]; |
Chris Lattner | 7650b94 | 2002-04-16 20:39:59 +0000 | [diff] [blame] | 307 | unsigned PtrNum = 0; |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 308 | for (unsigned i = 0, e = CI.getNumOperands(); i != e; ++i) |
| 309 | if (isa<PointerType>(CI.getOperand(i)->getType())) |
| 310 | DSN->addArgValue(PtrNum++, ValueMap[CI.getOperand(i)]); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 311 | } |
| 312 | |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 313 | void FunctionRepBuilder::visitPHINode(PHINode &PN) { |
| 314 | assert(isa<PointerType>(PN.getType()) && "Should only update ptr phis"); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 315 | |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 316 | PointerValSet &PN_PVS = ValueMap[&PN]; |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 317 | bool Changed = false; |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 318 | for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) |
| 319 | Changed |= PN_PVS.add(ValueMap[PN.getIncomingValue(i)], |
| 320 | PN.getIncomingValue(i)); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 321 | |
Chris Lattner | 1896150 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 322 | if (Changed) addAllUsesToWorkList(&PN); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 323 | } |
| 324 | |
| 325 | |
| 326 | |
| 327 | |
| 328 | // FunctionDSGraph constructor - Perform the global analysis to determine |
| 329 | // what the data structure usage behavior or a method looks like. |
| 330 | // |
| 331 | FunctionDSGraph::FunctionDSGraph(Function *F) : Func(F) { |
| 332 | FunctionRepBuilder Builder(this); |
Chris Lattner | 1120c8b | 2002-03-28 17:56:03 +0000 | [diff] [blame] | 333 | AllocNodes = Builder.getAllocNodes(); |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 334 | ShadowNodes = Builder.getShadowNodes(); |
Chris Lattner | 1120c8b | 2002-03-28 17:56:03 +0000 | [diff] [blame] | 335 | GlobalNodes = Builder.getGlobalNodes(); |
| 336 | CallNodes = Builder.getCallNodes(); |
| 337 | RetNode = Builder.getRetNode(); |
| 338 | ValueMap = Builder.getValueMap(); |
Chris Lattner | f4066b3 | 2002-03-27 19:45:12 +0000 | [diff] [blame] | 339 | |
Chris Lattner | 7650b94 | 2002-04-16 20:39:59 +0000 | [diff] [blame] | 340 | // Remove all entries in the value map that consist of global values pointing |
| 341 | // at things. They can only point to their node, so there is no use keeping |
| 342 | // them. |
| 343 | // |
Anand Shukla | a928403 | 2002-06-25 20:35:19 +0000 | [diff] [blame^] | 344 | for (std::map<Value*, PointerValSet>::iterator I = ValueMap.begin(), |
Chris Lattner | 7650b94 | 2002-04-16 20:39:59 +0000 | [diff] [blame] | 345 | E = ValueMap.end(); I != E;) |
| 346 | if (isa<GlobalValue>(I->first)) { |
| 347 | #if MAP_DOESNT_HAVE_BROKEN_ERASE_MEMBER |
| 348 | I = ValueMap.erase(I); |
| 349 | #else |
| 350 | ValueMap.erase(I); // This is really lame. |
| 351 | I = ValueMap.begin(); // GCC's stdc++ lib doesn't return an it! |
| 352 | #endif |
| 353 | } else |
| 354 | ++I; |
| 355 | |
Chris Lattner | f4066b3 | 2002-03-27 19:45:12 +0000 | [diff] [blame] | 356 | bool Changed = true; |
| 357 | while (Changed) { |
| 358 | // Eliminate shadow nodes that are not distinguishable from some other |
| 359 | // node in the graph... |
| 360 | // |
Chris Lattner | 7d093d4 | 2002-03-28 19:16:48 +0000 | [diff] [blame] | 361 | Changed = UnlinkUndistinguishableNodes(); |
Chris Lattner | f4066b3 | 2002-03-27 19:45:12 +0000 | [diff] [blame] | 362 | |
| 363 | // Eliminate shadow nodes that are now extraneous due to linking... |
Chris Lattner | 7d093d4 | 2002-03-28 19:16:48 +0000 | [diff] [blame] | 364 | Changed |= RemoveUnreachableNodes(); |
Chris Lattner | f4066b3 | 2002-03-27 19:45:12 +0000 | [diff] [blame] | 365 | } |
Chris Lattner | bb2a28f | 2002-03-26 22:39:06 +0000 | [diff] [blame] | 366 | } |