From 4c31fb5fbb9c2a3feaf9d8cc565f85cb805a8125 Mon Sep 17 00:00:00 2001 From: "Vikram S. Adve" Date: Tue, 18 Sep 2001 12:54:27 +0000 Subject: [PATCH] Don't add instructions to subtree for Phi or Call. Free tree nodes when done. Avoid obscuring code with for_each and bind_obj :-) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@612 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/InstrSelection/InstrForest.cpp | 333 +++++++++++------- .../SparcV9/InstrSelection/InstrForest.cpp | 333 +++++++++++------- 2 files changed, 402 insertions(+), 264 deletions(-) diff --git a/lib/CodeGen/InstrSelection/InstrForest.cpp b/lib/CodeGen/InstrSelection/InstrForest.cpp index 0ecf1c2fe99..efea63c3f1a 100644 --- a/lib/CodeGen/InstrSelection/InstrForest.cpp +++ b/lib/CodeGen/InstrSelection/InstrForest.cpp @@ -35,62 +35,79 @@ // class InstrTreeNode //------------------------------------------------------------------------ -void InstrTreeNode::dump(int dumpChildren, int indent) const { +void +InstrTreeNode::dump(int dumpChildren, int indent) const +{ dumpNode(indent); - if (dumpChildren) { - if (leftChild()) - leftChild()->dump(dumpChildren, indent+1); - if (rightChild()) - rightChild()->dump(dumpChildren, indent+1); - } + if (dumpChildren) + { + if (LeftChild) + LeftChild->dump(dumpChildren, indent+1); + if (RightChild) + RightChild->dump(dumpChildren, indent+1); + } } InstructionNode::InstructionNode(Instruction* I) - : InstrTreeNode(NTInstructionNode, I) { + : InstrTreeNode(NTInstructionNode, I) +{ opLabel = I->getOpcode(); // Distinguish special cases of some instructions such as Ret and Br // - if (opLabel == Instruction::Ret && ((ReturnInst*)I)->getReturnValue()) { - opLabel = RetValueOp; // ret(value) operation - } else if (opLabel == Instruction::Br && - !((BranchInst*)I)->isUnconditional()) { - opLabel = BrCondOp; // br(cond) operation - } else if (opLabel >= Instruction::SetEQ && opLabel <= Instruction::SetGT) { - opLabel = SetCCOp; // common label for all SetCC ops - } else if (opLabel == Instruction::Alloca && I->getNumOperands() > 0) { - opLabel = AllocaN; // Alloca(ptr, N) operation - } else if ((opLabel == Instruction::Load || - opLabel == Instruction::GetElementPtr) && - ((MemAccessInst*)I)->getFirstOffsetIdx() > 0) { - opLabel = opLabel + 100; // load/getElem with index vector - } else if (opLabel == Instruction::Cast) { - const Type *ITy = I->getType(); - switch(ITy->getPrimitiveID()) { - case Type::BoolTyID: opLabel = ToBoolTy; break; - case Type::UByteTyID: opLabel = ToUByteTy; break; - case Type::SByteTyID: opLabel = ToSByteTy; break; - case Type::UShortTyID: opLabel = ToUShortTy; break; - case Type::ShortTyID: opLabel = ToShortTy; break; - case Type::UIntTyID: opLabel = ToUIntTy; break; - case Type::IntTyID: opLabel = ToIntTy; break; - case Type::ULongTyID: opLabel = ToULongTy; break; - case Type::LongTyID: opLabel = ToLongTy; break; - case Type::FloatTyID: opLabel = ToFloatTy; break; - case Type::DoubleTyID: opLabel = ToDoubleTy; break; - case Type::ArrayTyID: opLabel = ToArrayTy; break; - case Type::PointerTyID: opLabel = ToPointerTy; break; - default: - // Just use `Cast' opcode otherwise. It's probably ignored. - break; + if (opLabel == Instruction::Ret && ((ReturnInst*)I)->getReturnValue()) + { + opLabel = RetValueOp; // ret(value) operation + } + else if (opLabel == Instruction::Br && ! ((BranchInst*)I)->isUnconditional()) + { + opLabel = BrCondOp; // br(cond) operation + } + else if (opLabel >= Instruction::SetEQ && opLabel <= Instruction::SetGT) + { + opLabel = SetCCOp; // common label for all SetCC ops + } + else if (opLabel == Instruction::Alloca && I->getNumOperands() > 0) + { + opLabel = AllocaN; // Alloca(ptr, N) operation + } + else if ((opLabel == Instruction::Load || + opLabel == Instruction::GetElementPtr) && + ((MemAccessInst*)I)->getFirstOffsetIdx() > 0) + { + opLabel = opLabel + 100; // load/getElem with index vector + } + else if (opLabel == Instruction::Cast) + { + const Type *ITy = I->getType(); + switch(ITy->getPrimitiveID()) + { + case Type::BoolTyID: opLabel = ToBoolTy; break; + case Type::UByteTyID: opLabel = ToUByteTy; break; + case Type::SByteTyID: opLabel = ToSByteTy; break; + case Type::UShortTyID: opLabel = ToUShortTy; break; + case Type::ShortTyID: opLabel = ToShortTy; break; + case Type::UIntTyID: opLabel = ToUIntTy; break; + case Type::IntTyID: opLabel = ToIntTy; break; + case Type::ULongTyID: opLabel = ToULongTy; break; + case Type::LongTyID: opLabel = ToLongTy; break; + case Type::FloatTyID: opLabel = ToFloatTy; break; + case Type::DoubleTyID: opLabel = ToDoubleTy; break; + case Type::ArrayTyID: opLabel = ToArrayTy; break; + case Type::PointerTyID: opLabel = ToPointerTy; break; + default: + // Just use `Cast' opcode otherwise. It's probably ignored. + break; + } } - } } -void InstructionNode::dumpNode(int indent) const { +void +InstructionNode::dumpNode(int indent) const +{ for (int i=0; i < indent; i++) cout << " "; @@ -99,17 +116,20 @@ void InstructionNode::dumpNode(int indent) const { const vector &mvec = getInstruction()->getMachineInstrVec(); if (mvec.size() > 0) cout << "\tMachine Instructions: "; - for (unsigned int i=0; i < mvec.size(); i++) { - mvec[i]->dump(0); - if (i < mvec.size() - 1) - cout << "; "; - } + for (unsigned int i=0; i < mvec.size(); i++) + { + mvec[i]->dump(0); + if (i < mvec.size() - 1) + cout << "; "; + } cout << endl; } -void VRegListNode::dumpNode(int indent) const { +void +VRegListNode::dumpNode(int indent) const +{ for (int i=0; i < indent; i++) cout << " "; @@ -117,7 +137,9 @@ void VRegListNode::dumpNode(int indent) const { } -void VRegNode::dumpNode(int indent) const { +void +VRegNode::dumpNode(int indent) const +{ for (int i=0; i < indent; i++) cout << " "; @@ -125,7 +147,9 @@ void VRegNode::dumpNode(int indent) const { << (int) getValue()->getValueType() << ")" << endl; } -void ConstantNode::dumpNode(int indent) const { +void +ConstantNode::dumpNode(int indent) const +{ for (int i=0; i < indent; i++) cout << " "; @@ -133,7 +157,9 @@ void ConstantNode::dumpNode(int indent) const { << (int) getValue()->getValueType() << ")" << endl; } -void LabelNode::dumpNode(int indent) const { +void +LabelNode::dumpNode(int indent) const +{ for (int i=0; i < indent; i++) cout << " "; @@ -146,29 +172,53 @@ void LabelNode::dumpNode(int indent) const { // A forest of instruction trees, usually for a single method. //------------------------------------------------------------------------ -void InstrForest::dump() const { +InstrForest::InstrForest(Method *M) +{ + for (Method::inst_iterator I = M->inst_begin(); I != M->inst_end(); ++I) + this->buildTreeForInstruction(*I); +} + +InstrForest::~InstrForest() +{ + for (hash_map:: iterator I = begin(); + I != end(); ++I) + { + InstructionNode* node = (*I).second; + if (node) + delete node; + } +} + +void +InstrForest::dump() const +{ for (hash_set::const_iterator I = treeRoots.begin(); I != treeRoots.end(); ++I) (*I)->dump(/*dumpChildren*/ 1, /*indent*/ 0); } -inline void InstrForest::noteTreeNodeForInstr(Instruction *instr, - InstructionNode *treeNode) { +inline void +InstrForest::noteTreeNodeForInstr(Instruction *instr, + InstructionNode *treeNode) +{ assert(treeNode->getNodeType() == InstrTreeNode::NTInstructionNode); (*this)[instr] = treeNode; treeRoots.insert(treeNode); // mark node as root of a new tree } -inline void InstrForest::setLeftChild(InstrTreeNode *Par, InstrTreeNode *Chld) { +inline void +InstrForest::setLeftChild(InstrTreeNode *Par, InstrTreeNode *Chld) +{ Par->LeftChild = Chld; Chld->Parent = Par; if (Chld->getNodeType() == InstrTreeNode::NTInstructionNode) treeRoots.erase((InstructionNode*)Chld); // no longer a tree root } - -inline void InstrForest::setRightChild(InstrTreeNode *Par, InstrTreeNode *Chld){ +inline void +InstrForest::setRightChild(InstrTreeNode *Par, InstrTreeNode *Chld) +{ Par->RightChild = Chld; Chld->Parent = Par; if (Chld->getNodeType() == InstrTreeNode::NTInstructionNode) @@ -176,22 +226,30 @@ inline void InstrForest::setRightChild(InstrTreeNode *Par, InstrTreeNode *Chld){ } -InstructionNode *InstrForest::buildTreeForInstruction(Instruction *Inst) { - InstructionNode *treeNode = getTreeNodeForInstr(Inst); - if (treeNode) { - // treeNode has already been constructed for this instruction - assert(treeNode->getInstruction() == Inst); - return treeNode; - } +InstructionNode* +InstrForest::buildTreeForInstruction(Instruction *instr) +{ + InstructionNode *treeNode = getTreeNodeForInstr(instr); + if (treeNode) + { + // treeNode has already been constructed for this instruction + assert(treeNode->getInstruction() == instr); + return treeNode; + } // Otherwise, create a new tree node for this instruction. // - treeNode = new InstructionNode(Inst); - noteTreeNodeForInstr(Inst, treeNode); + treeNode = new InstructionNode(instr); + noteTreeNodeForInstr(instr, treeNode); + + if (instr->getOpcode() == Instruction::Call) + { // Operands of call instruction + return treeNode; + } // If the instruction has more than 2 instruction operands, // then we need to create artificial list nodes to hold them. - // (Note that we only not count operands that get tree nodes, and not + // (Note that we only count operands that get tree nodes, and not // others such as branch labels for a branch or switch instruction.) // // To do this efficiently, we'll walk all operands, build treeNodes @@ -204,57 +262,70 @@ InstructionNode *InstrForest::buildTreeForInstruction(Instruction *Inst) { const unsigned int MAX_CHILD = 8; static InstrTreeNode *fixedChildArray[MAX_CHILD]; InstrTreeNode **childArray = - (Inst->getNumOperands() > MAX_CHILD) - ? new (InstrTreeNode*)[Inst->getNumOperands()] : fixedChildArray; + (instr->getNumOperands() > MAX_CHILD) + ? new (InstrTreeNode*)[instr->getNumOperands()] : fixedChildArray; // // Walk the operands of the instruction // - for (Instruction::op_iterator O = Inst->op_begin(); O != Inst->op_end(); ++O){ - Value* operand = *O; + for (Instruction::op_iterator O = instr->op_begin(); O!=instr->op_end(); ++O) + { + Value* operand = *O; - // Check if the operand is a data value, not an branch label, type, - // method or module. If the operand is an address type (i.e., label - // or method) that is used in an non-branching operation, e.g., `add'. - // that should be considered a data value. + // Check if the operand is a data value, not an branch label, type, + // method or module. If the operand is an address type (i.e., label + // or method) that is used in an non-branching operation, e.g., `add'. + // that should be considered a data value. - // Check latter condition here just to simplify the next IF. - bool includeAddressOperand = - (operand->isBasicBlock() || operand->isMethod()) - && !Inst->isTerminator(); + // Check latter condition here just to simplify the next IF. + bool includeAddressOperand = + (operand->isBasicBlock() || operand->isMethod()) + && !instr->isTerminator(); - if (includeAddressOperand || operand->isInstruction() || - operand->isConstant() || operand->isMethodArgument()) { - // This operand is a data value + if (includeAddressOperand || operand->isInstruction() || + operand->isConstant() || operand->isMethodArgument() || + operand->isGlobal()) + { + // This operand is a data value - // An instruction that computes the incoming value is added as a - // child of the current instruction if: - // the value has only a single use - // AND both instructions are in the same basic block. - // - // (Note that if the value has only a single use (viz., `instr'), - // the def of the value can be safely moved just before instr - // and therefore it is safe to combine these two instructions.) - // - // In all other cases, the virtual register holding the value - // is used directly, i.e., made a child of the instruction node. - // - InstrTreeNode* opTreeNode; - if (operand->isInstruction() && operand->use_size() == 1 && - ((Instruction*)operand)->getParent() == Inst->getParent()) { - // Recursively create a treeNode for it. - opTreeNode = buildTreeForInstruction((Instruction*)operand); - } else if (ConstPoolVal *CPV = operand->castConstant()) { - // Create a leaf node for a constant - opTreeNode = new ConstantNode(CPV); - } else { - // Create a leaf node for the virtual register - opTreeNode = new VRegNode(operand); - } + // An instruction that computes the incoming value is added as a + // child of the current instruction if: + // the value has only a single use + // AND both instructions are in the same basic block. + // AND the current instruction is not a PHI (because the incoming + // value is conceptually in a predecessor block, + // even though it may be in the same static block) + // + // (Note that if the value has only a single use (viz., `instr'), + // the def of the value can be safely moved just before instr + // and therefore it is safe to combine these two instructions.) + // + // In all other cases, the virtual register holding the value + // is used directly, i.e., made a child of the instruction node. + // + InstrTreeNode* opTreeNode; + if (operand->isInstruction() && operand->use_size() == 1 && + ((Instruction*)operand)->getParent() == instr->getParent() && + ! instr->isPHINode() && + ! instr->getOpcode() == Instruction::Call) + { + // Recursively create a treeNode for it. + opTreeNode = buildTreeForInstruction((Instruction*)operand); + } + else if (ConstPoolVal *CPV = operand->castConstant()) + { + // Create a leaf node for a constant + opTreeNode = new ConstantNode(CPV); + } + else + { + // Create a leaf node for the virtual register + opTreeNode = new VRegNode(operand); + } - childArray[numChildren++] = opTreeNode; + childArray[numChildren++] = opTreeNode; + } } - } //-------------------------------------------------------------------- // Add any selected operands as children in the tree. @@ -267,14 +338,15 @@ InstructionNode *InstrForest::buildTreeForInstruction(Instruction *Inst) { InstrTreeNode *parent = treeNode; - if (numChildren > 2) { - unsigned instrOpcode = treeNode->getInstruction()->getOpcode(); - assert(instrOpcode == Instruction::PHINode || - instrOpcode == Instruction::Call || - instrOpcode == Instruction::Load || - instrOpcode == Instruction::Store || - instrOpcode == Instruction::GetElementPtr); - } + if (numChildren > 2) + { + unsigned instrOpcode = treeNode->getInstruction()->getOpcode(); + assert(instrOpcode == Instruction::PHINode || + instrOpcode == Instruction::Call || + instrOpcode == Instruction::Load || + instrOpcode == Instruction::Store || + instrOpcode == Instruction::GetElementPtr); + } // Insert the first child as a direct child if (numChildren >= 1) @@ -283,19 +355,21 @@ InstructionNode *InstrForest::buildTreeForInstruction(Instruction *Inst) { int n; // Create a list node for children 2 .. N-1, if any - for (n = numChildren-1; n >= 2; n--) { - // We have more than two children - InstrTreeNode *listNode = new VRegListNode(); - setRightChild(parent, listNode); - setLeftChild(listNode, childArray[numChildren - n]); - parent = listNode; - } + for (n = numChildren-1; n >= 2; n--) + { + // We have more than two children + InstrTreeNode *listNode = new VRegListNode(); + setRightChild(parent, listNode); + setLeftChild(listNode, childArray[numChildren - n]); + parent = listNode; + } // Now insert the last remaining child (if any). - if (numChildren >= 2) { - assert(n == 1); - setRightChild(parent, childArray[numChildren - 1]); - } + if (numChildren >= 2) + { + assert(n == 1); + setRightChild(parent, childArray[numChildren - 1]); + } if (childArray != fixedChildArray) delete [] childArray; @@ -303,8 +377,3 @@ InstructionNode *InstrForest::buildTreeForInstruction(Instruction *Inst) { return treeNode; } - -InstrForest::InstrForest(Method *M) { - for_each(M->inst_begin(), M->inst_end(), - bind_obj(this, &InstrForest::buildTreeForInstruction)); -} diff --git a/lib/Target/SparcV9/InstrSelection/InstrForest.cpp b/lib/Target/SparcV9/InstrSelection/InstrForest.cpp index 0ecf1c2fe99..efea63c3f1a 100644 --- a/lib/Target/SparcV9/InstrSelection/InstrForest.cpp +++ b/lib/Target/SparcV9/InstrSelection/InstrForest.cpp @@ -35,62 +35,79 @@ // class InstrTreeNode //------------------------------------------------------------------------ -void InstrTreeNode::dump(int dumpChildren, int indent) const { +void +InstrTreeNode::dump(int dumpChildren, int indent) const +{ dumpNode(indent); - if (dumpChildren) { - if (leftChild()) - leftChild()->dump(dumpChildren, indent+1); - if (rightChild()) - rightChild()->dump(dumpChildren, indent+1); - } + if (dumpChildren) + { + if (LeftChild) + LeftChild->dump(dumpChildren, indent+1); + if (RightChild) + RightChild->dump(dumpChildren, indent+1); + } } InstructionNode::InstructionNode(Instruction* I) - : InstrTreeNode(NTInstructionNode, I) { + : InstrTreeNode(NTInstructionNode, I) +{ opLabel = I->getOpcode(); // Distinguish special cases of some instructions such as Ret and Br // - if (opLabel == Instruction::Ret && ((ReturnInst*)I)->getReturnValue()) { - opLabel = RetValueOp; // ret(value) operation - } else if (opLabel == Instruction::Br && - !((BranchInst*)I)->isUnconditional()) { - opLabel = BrCondOp; // br(cond) operation - } else if (opLabel >= Instruction::SetEQ && opLabel <= Instruction::SetGT) { - opLabel = SetCCOp; // common label for all SetCC ops - } else if (opLabel == Instruction::Alloca && I->getNumOperands() > 0) { - opLabel = AllocaN; // Alloca(ptr, N) operation - } else if ((opLabel == Instruction::Load || - opLabel == Instruction::GetElementPtr) && - ((MemAccessInst*)I)->getFirstOffsetIdx() > 0) { - opLabel = opLabel + 100; // load/getElem with index vector - } else if (opLabel == Instruction::Cast) { - const Type *ITy = I->getType(); - switch(ITy->getPrimitiveID()) { - case Type::BoolTyID: opLabel = ToBoolTy; break; - case Type::UByteTyID: opLabel = ToUByteTy; break; - case Type::SByteTyID: opLabel = ToSByteTy; break; - case Type::UShortTyID: opLabel = ToUShortTy; break; - case Type::ShortTyID: opLabel = ToShortTy; break; - case Type::UIntTyID: opLabel = ToUIntTy; break; - case Type::IntTyID: opLabel = ToIntTy; break; - case Type::ULongTyID: opLabel = ToULongTy; break; - case Type::LongTyID: opLabel = ToLongTy; break; - case Type::FloatTyID: opLabel = ToFloatTy; break; - case Type::DoubleTyID: opLabel = ToDoubleTy; break; - case Type::ArrayTyID: opLabel = ToArrayTy; break; - case Type::PointerTyID: opLabel = ToPointerTy; break; - default: - // Just use `Cast' opcode otherwise. It's probably ignored. - break; + if (opLabel == Instruction::Ret && ((ReturnInst*)I)->getReturnValue()) + { + opLabel = RetValueOp; // ret(value) operation + } + else if (opLabel == Instruction::Br && ! ((BranchInst*)I)->isUnconditional()) + { + opLabel = BrCondOp; // br(cond) operation + } + else if (opLabel >= Instruction::SetEQ && opLabel <= Instruction::SetGT) + { + opLabel = SetCCOp; // common label for all SetCC ops + } + else if (opLabel == Instruction::Alloca && I->getNumOperands() > 0) + { + opLabel = AllocaN; // Alloca(ptr, N) operation + } + else if ((opLabel == Instruction::Load || + opLabel == Instruction::GetElementPtr) && + ((MemAccessInst*)I)->getFirstOffsetIdx() > 0) + { + opLabel = opLabel + 100; // load/getElem with index vector + } + else if (opLabel == Instruction::Cast) + { + const Type *ITy = I->getType(); + switch(ITy->getPrimitiveID()) + { + case Type::BoolTyID: opLabel = ToBoolTy; break; + case Type::UByteTyID: opLabel = ToUByteTy; break; + case Type::SByteTyID: opLabel = ToSByteTy; break; + case Type::UShortTyID: opLabel = ToUShortTy; break; + case Type::ShortTyID: opLabel = ToShortTy; break; + case Type::UIntTyID: opLabel = ToUIntTy; break; + case Type::IntTyID: opLabel = ToIntTy; break; + case Type::ULongTyID: opLabel = ToULongTy; break; + case Type::LongTyID: opLabel = ToLongTy; break; + case Type::FloatTyID: opLabel = ToFloatTy; break; + case Type::DoubleTyID: opLabel = ToDoubleTy; break; + case Type::ArrayTyID: opLabel = ToArrayTy; break; + case Type::PointerTyID: opLabel = ToPointerTy; break; + default: + // Just use `Cast' opcode otherwise. It's probably ignored. + break; + } } - } } -void InstructionNode::dumpNode(int indent) const { +void +InstructionNode::dumpNode(int indent) const +{ for (int i=0; i < indent; i++) cout << " "; @@ -99,17 +116,20 @@ void InstructionNode::dumpNode(int indent) const { const vector &mvec = getInstruction()->getMachineInstrVec(); if (mvec.size() > 0) cout << "\tMachine Instructions: "; - for (unsigned int i=0; i < mvec.size(); i++) { - mvec[i]->dump(0); - if (i < mvec.size() - 1) - cout << "; "; - } + for (unsigned int i=0; i < mvec.size(); i++) + { + mvec[i]->dump(0); + if (i < mvec.size() - 1) + cout << "; "; + } cout << endl; } -void VRegListNode::dumpNode(int indent) const { +void +VRegListNode::dumpNode(int indent) const +{ for (int i=0; i < indent; i++) cout << " "; @@ -117,7 +137,9 @@ void VRegListNode::dumpNode(int indent) const { } -void VRegNode::dumpNode(int indent) const { +void +VRegNode::dumpNode(int indent) const +{ for (int i=0; i < indent; i++) cout << " "; @@ -125,7 +147,9 @@ void VRegNode::dumpNode(int indent) const { << (int) getValue()->getValueType() << ")" << endl; } -void ConstantNode::dumpNode(int indent) const { +void +ConstantNode::dumpNode(int indent) const +{ for (int i=0; i < indent; i++) cout << " "; @@ -133,7 +157,9 @@ void ConstantNode::dumpNode(int indent) const { << (int) getValue()->getValueType() << ")" << endl; } -void LabelNode::dumpNode(int indent) const { +void +LabelNode::dumpNode(int indent) const +{ for (int i=0; i < indent; i++) cout << " "; @@ -146,29 +172,53 @@ void LabelNode::dumpNode(int indent) const { // A forest of instruction trees, usually for a single method. //------------------------------------------------------------------------ -void InstrForest::dump() const { +InstrForest::InstrForest(Method *M) +{ + for (Method::inst_iterator I = M->inst_begin(); I != M->inst_end(); ++I) + this->buildTreeForInstruction(*I); +} + +InstrForest::~InstrForest() +{ + for (hash_map:: iterator I = begin(); + I != end(); ++I) + { + InstructionNode* node = (*I).second; + if (node) + delete node; + } +} + +void +InstrForest::dump() const +{ for (hash_set::const_iterator I = treeRoots.begin(); I != treeRoots.end(); ++I) (*I)->dump(/*dumpChildren*/ 1, /*indent*/ 0); } -inline void InstrForest::noteTreeNodeForInstr(Instruction *instr, - InstructionNode *treeNode) { +inline void +InstrForest::noteTreeNodeForInstr(Instruction *instr, + InstructionNode *treeNode) +{ assert(treeNode->getNodeType() == InstrTreeNode::NTInstructionNode); (*this)[instr] = treeNode; treeRoots.insert(treeNode); // mark node as root of a new tree } -inline void InstrForest::setLeftChild(InstrTreeNode *Par, InstrTreeNode *Chld) { +inline void +InstrForest::setLeftChild(InstrTreeNode *Par, InstrTreeNode *Chld) +{ Par->LeftChild = Chld; Chld->Parent = Par; if (Chld->getNodeType() == InstrTreeNode::NTInstructionNode) treeRoots.erase((InstructionNode*)Chld); // no longer a tree root } - -inline void InstrForest::setRightChild(InstrTreeNode *Par, InstrTreeNode *Chld){ +inline void +InstrForest::setRightChild(InstrTreeNode *Par, InstrTreeNode *Chld) +{ Par->RightChild = Chld; Chld->Parent = Par; if (Chld->getNodeType() == InstrTreeNode::NTInstructionNode) @@ -176,22 +226,30 @@ inline void InstrForest::setRightChild(InstrTreeNode *Par, InstrTreeNode *Chld){ } -InstructionNode *InstrForest::buildTreeForInstruction(Instruction *Inst) { - InstructionNode *treeNode = getTreeNodeForInstr(Inst); - if (treeNode) { - // treeNode has already been constructed for this instruction - assert(treeNode->getInstruction() == Inst); - return treeNode; - } +InstructionNode* +InstrForest::buildTreeForInstruction(Instruction *instr) +{ + InstructionNode *treeNode = getTreeNodeForInstr(instr); + if (treeNode) + { + // treeNode has already been constructed for this instruction + assert(treeNode->getInstruction() == instr); + return treeNode; + } // Otherwise, create a new tree node for this instruction. // - treeNode = new InstructionNode(Inst); - noteTreeNodeForInstr(Inst, treeNode); + treeNode = new InstructionNode(instr); + noteTreeNodeForInstr(instr, treeNode); + + if (instr->getOpcode() == Instruction::Call) + { // Operands of call instruction + return treeNode; + } // If the instruction has more than 2 instruction operands, // then we need to create artificial list nodes to hold them. - // (Note that we only not count operands that get tree nodes, and not + // (Note that we only count operands that get tree nodes, and not // others such as branch labels for a branch or switch instruction.) // // To do this efficiently, we'll walk all operands, build treeNodes @@ -204,57 +262,70 @@ InstructionNode *InstrForest::buildTreeForInstruction(Instruction *Inst) { const unsigned int MAX_CHILD = 8; static InstrTreeNode *fixedChildArray[MAX_CHILD]; InstrTreeNode **childArray = - (Inst->getNumOperands() > MAX_CHILD) - ? new (InstrTreeNode*)[Inst->getNumOperands()] : fixedChildArray; + (instr->getNumOperands() > MAX_CHILD) + ? new (InstrTreeNode*)[instr->getNumOperands()] : fixedChildArray; // // Walk the operands of the instruction // - for (Instruction::op_iterator O = Inst->op_begin(); O != Inst->op_end(); ++O){ - Value* operand = *O; + for (Instruction::op_iterator O = instr->op_begin(); O!=instr->op_end(); ++O) + { + Value* operand = *O; - // Check if the operand is a data value, not an branch label, type, - // method or module. If the operand is an address type (i.e., label - // or method) that is used in an non-branching operation, e.g., `add'. - // that should be considered a data value. + // Check if the operand is a data value, not an branch label, type, + // method or module. If the operand is an address type (i.e., label + // or method) that is used in an non-branching operation, e.g., `add'. + // that should be considered a data value. - // Check latter condition here just to simplify the next IF. - bool includeAddressOperand = - (operand->isBasicBlock() || operand->isMethod()) - && !Inst->isTerminator(); + // Check latter condition here just to simplify the next IF. + bool includeAddressOperand = + (operand->isBasicBlock() || operand->isMethod()) + && !instr->isTerminator(); - if (includeAddressOperand || operand->isInstruction() || - operand->isConstant() || operand->isMethodArgument()) { - // This operand is a data value + if (includeAddressOperand || operand->isInstruction() || + operand->isConstant() || operand->isMethodArgument() || + operand->isGlobal()) + { + // This operand is a data value - // An instruction that computes the incoming value is added as a - // child of the current instruction if: - // the value has only a single use - // AND both instructions are in the same basic block. - // - // (Note that if the value has only a single use (viz., `instr'), - // the def of the value can be safely moved just before instr - // and therefore it is safe to combine these two instructions.) - // - // In all other cases, the virtual register holding the value - // is used directly, i.e., made a child of the instruction node. - // - InstrTreeNode* opTreeNode; - if (operand->isInstruction() && operand->use_size() == 1 && - ((Instruction*)operand)->getParent() == Inst->getParent()) { - // Recursively create a treeNode for it. - opTreeNode = buildTreeForInstruction((Instruction*)operand); - } else if (ConstPoolVal *CPV = operand->castConstant()) { - // Create a leaf node for a constant - opTreeNode = new ConstantNode(CPV); - } else { - // Create a leaf node for the virtual register - opTreeNode = new VRegNode(operand); - } + // An instruction that computes the incoming value is added as a + // child of the current instruction if: + // the value has only a single use + // AND both instructions are in the same basic block. + // AND the current instruction is not a PHI (because the incoming + // value is conceptually in a predecessor block, + // even though it may be in the same static block) + // + // (Note that if the value has only a single use (viz., `instr'), + // the def of the value can be safely moved just before instr + // and therefore it is safe to combine these two instructions.) + // + // In all other cases, the virtual register holding the value + // is used directly, i.e., made a child of the instruction node. + // + InstrTreeNode* opTreeNode; + if (operand->isInstruction() && operand->use_size() == 1 && + ((Instruction*)operand)->getParent() == instr->getParent() && + ! instr->isPHINode() && + ! instr->getOpcode() == Instruction::Call) + { + // Recursively create a treeNode for it. + opTreeNode = buildTreeForInstruction((Instruction*)operand); + } + else if (ConstPoolVal *CPV = operand->castConstant()) + { + // Create a leaf node for a constant + opTreeNode = new ConstantNode(CPV); + } + else + { + // Create a leaf node for the virtual register + opTreeNode = new VRegNode(operand); + } - childArray[numChildren++] = opTreeNode; + childArray[numChildren++] = opTreeNode; + } } - } //-------------------------------------------------------------------- // Add any selected operands as children in the tree. @@ -267,14 +338,15 @@ InstructionNode *InstrForest::buildTreeForInstruction(Instruction *Inst) { InstrTreeNode *parent = treeNode; - if (numChildren > 2) { - unsigned instrOpcode = treeNode->getInstruction()->getOpcode(); - assert(instrOpcode == Instruction::PHINode || - instrOpcode == Instruction::Call || - instrOpcode == Instruction::Load || - instrOpcode == Instruction::Store || - instrOpcode == Instruction::GetElementPtr); - } + if (numChildren > 2) + { + unsigned instrOpcode = treeNode->getInstruction()->getOpcode(); + assert(instrOpcode == Instruction::PHINode || + instrOpcode == Instruction::Call || + instrOpcode == Instruction::Load || + instrOpcode == Instruction::Store || + instrOpcode == Instruction::GetElementPtr); + } // Insert the first child as a direct child if (numChildren >= 1) @@ -283,19 +355,21 @@ InstructionNode *InstrForest::buildTreeForInstruction(Instruction *Inst) { int n; // Create a list node for children 2 .. N-1, if any - for (n = numChildren-1; n >= 2; n--) { - // We have more than two children - InstrTreeNode *listNode = new VRegListNode(); - setRightChild(parent, listNode); - setLeftChild(listNode, childArray[numChildren - n]); - parent = listNode; - } + for (n = numChildren-1; n >= 2; n--) + { + // We have more than two children + InstrTreeNode *listNode = new VRegListNode(); + setRightChild(parent, listNode); + setLeftChild(listNode, childArray[numChildren - n]); + parent = listNode; + } // Now insert the last remaining child (if any). - if (numChildren >= 2) { - assert(n == 1); - setRightChild(parent, childArray[numChildren - 1]); - } + if (numChildren >= 2) + { + assert(n == 1); + setRightChild(parent, childArray[numChildren - 1]); + } if (childArray != fixedChildArray) delete [] childArray; @@ -303,8 +377,3 @@ InstructionNode *InstrForest::buildTreeForInstruction(Instruction *Inst) { return treeNode; } - -InstrForest::InstrForest(Method *M) { - for_each(M->inst_begin(), M->inst_end(), - bind_obj(this, &InstrForest::buildTreeForInstruction)); -}