1 //===- llvm/Analysis/InstForest.h - Partition Method into forest -*- C++ -*--=//
3 // This interface is used to partition a method into a forest of instruction
4 // trees, where the following invariants hold:
6 // 1. The instructions in a tree are all related to each other through use
8 // 2. All instructions in a tree are members of the same basic block
9 // 3. All instructions in a tree (with the exception of the root), may have only
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_ANALYSIS_INSTFOREST_H
15 #define LLVM_ANALYSIS_INSTFOREST_H
17 #include "llvm/Support/Tree.h"
18 #include "llvm/Instruction.h"
23 template <class Payload> class InstTreeNode;
24 template<class Payload> class InstForest;
27 //===----------------------------------------------------------------------===//
29 //===----------------------------------------------------------------------===//
31 // There is an instance of this class for each node in the instruction forest.
32 // There should be a node for every instruction in the tree, as well as
33 // Temporary nodes that correspond to other trees in the forest and to variables
34 // and global variables. Constants have their own special node.
36 template<class Payload>
38 public Tree<InstTreeNode<Payload>, pair<pair<Value*, char>, Payload> > {
40 friend class InstForest<Payload>;
41 typedef Tree<InstTreeNode<Payload>, pair<pair<Value*, char>, Payload> > super;
43 // Constants used for the node type value
45 ConstNode = Value::ConstantVal,
46 BasicBlockNode = Value::BasicBlockVal,
47 InstructionNode = Value::InstructionVal,
51 // Helper functions to make accessing our data nicer...
52 const Value *getValue() const { return getTreeData().first.first; }
53 Value *getValue() { return getTreeData().first.first; }
54 enum NodeTypeTy getNodeType() const {
55 return (enum NodeTypeTy)getTreeData().first.second;
58 InstTreeNode(const InstTreeNode &); // Do not implement
59 void operator=(const InstTreeNode &); // Do not implement
61 // Only creatable by InstForest
62 InstTreeNode(InstForest<Payload> &IF, Value *V, InstTreeNode *Parent);
63 bool CanMergeInstIntoTree(Instruction *Inst);
65 // Accessor functions...
66 inline Payload &getData() { return getTreeData().second; }
67 inline const Payload &getData() const { return getTreeData().second; }
69 // Type checking functions...
70 inline bool isConstant() const { return getNodeType() == ConstNode; }
71 inline bool isBasicBlock() const { return getNodeType() == BasicBlockNode; }
72 inline bool isInstruction() const { return getNodeType() == InstructionNode; }
73 inline bool isTemporary() const { return getNodeType() == TemporaryNode; }
75 // Accessors for different node types...
76 inline ConstPoolVal *getConstant() {
77 return getValue()->castConstantAsserting();
79 inline const ConstPoolVal *getConstant() const {
80 return getValue()->castConstantAsserting();
82 inline BasicBlock *getBasicBlock() {
83 return getValue()->castBasicBlockAsserting();
85 inline const BasicBlock *getBasicBlock() const {
86 return getValue()->castBasicBlockAsserting();
88 inline Instruction *getInstruction() {
89 assert(isInstruction() && "getInstruction() on non instruction node!");
90 return getValue()->castInstructionAsserting();
92 inline const Instruction *getInstruction() const {
93 assert(isInstruction() && "getInstruction() on non instruction node!");
94 return getValue()->castInstructionAsserting();
96 inline Instruction *getTemporary() {
97 assert(isTemporary() && "getTemporary() on non temporary node!");
98 return getValue()->castInstructionAsserting();
100 inline const Instruction *getTemporary() const {
101 assert(isTemporary() && "getTemporary() on non temporary node!");
102 return getValue()->castInstructionAsserting();
106 // print - Called by operator<< below...
107 void print(ostream &o, unsigned Indent) const {
108 o << string(Indent*2, ' ');
109 switch (getNodeType()) {
110 case ConstNode : o << "Constant : "; break;
111 case BasicBlockNode : o << "BasicBlock : " << getValue()->getName() << endl;
113 case InstructionNode: o << "Instruction: "; break;
114 case TemporaryNode : o << "Temporary : "; break;
115 default: o << "UNKNOWN NODE TYPE: " << getNodeType() << endl; abort();
119 if (!getValue()->isInstruction()) o << "\n";
121 for (unsigned i = 0; i < getNumChildren(); ++i)
122 getChild(i)->print(o, Indent+1);
126 template<class Payload>
127 inline ostream &operator<<(ostream &o, const InstTreeNode<Payload> *N) {
128 N->print(o, 0); return o;
131 //===----------------------------------------------------------------------===//
133 //===----------------------------------------------------------------------===//
135 // This class represents the instruction forest itself. It exposes iterators
136 // to an underlying vector of Instruction Trees. Each root of the tree is
137 // guaranteed to be an instruction node. The constructor builds the forest.
139 template<class Payload>
140 class InstForest : public vector<InstTreeNode<Payload> *> {
141 friend class InstTreeNode<Payload>;
143 // InstMap - Map contains entries for ALL instructions in the method and the
144 // InstTreeNode that they correspond to.
146 map<Instruction*, InstTreeNode<Payload> *> InstMap;
148 void addInstMapping(Instruction *I, InstTreeNode<Payload> *IN) {
149 InstMap.insert(make_pair(I, IN));
152 void removeInstFromRootList(Instruction *I) {
153 for (unsigned i = size(); i > 0; --i)
154 if (operator[](i-1)->getValue() == I) {
161 // ctor - Create an instruction forest for the specified method...
162 InstForest(Method *M) {
163 for (Method::inst_iterator I = M->inst_begin(), E = M->inst_end();
165 Instruction *Inst = *I;
166 if (!getInstNode(Inst)) // Do we already have a tree for this inst?
167 push_back(new InstTreeNode<Payload>(*this, Inst, 0)); // No create one!
168 // InstTreeNode ctor automatically adds the created node into our InstMap
172 // dtor - Free the trees...
174 for (unsigned i = size(); i > 0; --i)
175 delete operator[](i-1);
178 // getInstNode - Return the instruction node that corresponds to the specified
179 // instruction... This node may be embeded in a larger tree, in which case
180 // the parent pointer can be used to find the root of the tree.
182 inline InstTreeNode<Payload> *getInstNode(Instruction *Inst) {
183 map<Instruction*, InstTreeNode<Payload> *>::iterator I = InstMap.find(Inst);
184 if (I != InstMap.end()) return I->second;
187 inline const InstTreeNode<Payload> *getInstNode(const Instruction *Inst)const{
188 map<Instruction*, InstTreeNode<Payload>*>::const_iterator I =
190 if (I != InstMap.end()) return I->second;
194 // print - Called by operator<< below...
195 void print(ostream &out) const {
196 for (const_iterator I = begin(), E = end(); I != E; ++I)
201 template<class Payload>
202 inline ostream &operator<<(ostream &o, const InstForest<Payload> &IF) {
203 IF.print(o); return o;
207 //===----------------------------------------------------------------------===//
208 // Method Implementations
209 //===----------------------------------------------------------------------===//
211 // CanMergeInstIntoTree - Return true if it is allowed to merge the specified
212 // instruction into 'this' instruction tree. This is allowed iff:
213 // 1. The instruction is in the same basic block as the current one
214 // 2. The instruction has only one use
216 template <class Payload>
217 bool InstTreeNode<Payload>::CanMergeInstIntoTree(Instruction *I) {
218 if (I->use_size() > 1) return false;
219 return I->getParent() == getValue()->castInstructionAsserting()->getParent();
223 // InstTreeNode ctor - This constructor creates the instruction tree for the
224 // specified value. If the value is an instruction, it recursively creates the
225 // internal/child nodes and adds them to the instruction forest.
227 template <class Payload>
228 InstTreeNode<Payload>::InstTreeNode(InstForest<Payload> &IF, Value *V,
229 InstTreeNode *Parent) : super(Parent) {
230 getTreeData().first.first = V; // Save tree node
232 if (!V->isInstruction()) {
233 assert((V->isConstant() || V->isBasicBlock() ||
234 V->isMethodArgument() || V->isGlobal()) &&
235 "Unrecognized value type for InstForest Partition!");
237 getTreeData().first.second = ConstNode;
238 else if (V->isBasicBlock())
239 getTreeData().first.second = BasicBlockNode;
241 getTreeData().first.second = TemporaryNode;
246 // Must be an instruction then... see if we can include it in this tree!
247 Instruction *I = V->castInstructionAsserting();
248 if (Parent && !Parent->CanMergeInstIntoTree(I)) {
249 // Not root node of tree, but mult uses?
250 getTreeData().first.second = TemporaryNode; // Must be a temporary!
254 // Otherwise, we are an internal instruction node. We must process our
255 // uses and add them as children of this node.
257 vector<InstTreeNode*> Children;
259 // Make sure that the forest knows about us!
260 IF.addInstMapping(I, this);
262 // Walk the operands of the instruction adding children for all of the uses
263 // of the instruction...
265 for (Instruction::op_iterator OI = I->op_begin(); OI != I->op_end(); ++OI) {
266 Value *Operand = *OI;
267 InstTreeNode<Payload> *IN = IF.getInstNode(Operand->castInstruction());
268 if (IN && CanMergeInstIntoTree(Operand->castInstructionAsserting())) {
269 Children.push_back(IN);
270 IF.removeInstFromRootList(Operand->castInstructionAsserting());
272 // No node for this child yet... create one now!
273 Children.push_back(new InstTreeNode(IF, *OI, this));
277 setChildren(Children);
278 getTreeData().first.second = InstructionNode;
281 } // End namespace analysis