blob: 7302baa2864e01c28421880608ae92f5adc81057 [file] [log] [blame]
Ruchira Sasanka8e604792001-09-14 21:18:34 +00001#include "llvm/CodeGen/LiveRangeInfo.h"
Chris Lattner0a8ed942002-02-04 05:56:09 +00002#include "llvm/CodeGen/RegClass.h"
3#include "llvm/CodeGen/MachineInstr.h"
4#include "llvm/Target/TargetMachine.h"
5#include "llvm/Method.h"
Chris Lattner7471a7b2002-02-05 03:35:53 +00006#include "Support/SetOperations.h"
Chris Lattner697954c2002-01-20 22:54:45 +00007#include <iostream>
8using std::cerr;
Ruchira Sasanka8e604792001-09-14 21:18:34 +00009
Chris Lattner2f898d22002-02-05 06:02:59 +000010LiveRangeInfo::LiveRangeInfo(const Method *M, const TargetMachine &tm,
Chris Lattner697954c2002-01-20 22:54:45 +000011 std::vector<RegClass *> &RCL)
Chris Lattner2f898d22002-02-05 06:02:59 +000012 : Meth(M), TM(tm), RegClassList(RCL), MRI(tm.getRegInfo()) { }
Ruchira Sasanka8e604792001-09-14 21:18:34 +000013
14
Ruchira Sasanka4f3eb222002-01-07 19:19:18 +000015LiveRangeInfo::~LiveRangeInfo() {
Chris Lattner2f898d22002-02-05 06:02:59 +000016 for (LiveRangeMapType::iterator MI = LiveRangeMap.begin();
17 MI != LiveRangeMap.end(); ++MI) {
Ruchira Sasanka4f3eb222002-01-07 19:19:18 +000018
Chris Lattner697954c2002-01-20 22:54:45 +000019 if (MI->first && MI->second) {
20 LiveRange *LR = MI->second;
21
22 // we need to be careful in deleting LiveRanges in LiveRangeMap
23 // since two/more Values in the live range map can point to the same
24 // live range. We have to make the other entries NULL when we delete
25 // a live range.
26
Chris Lattner2f898d22002-02-05 06:02:59 +000027 for(LiveRange::iterator LI = LR->begin(); LI != LR->end(); ++LI)
Chris Lattner697954c2002-01-20 22:54:45 +000028 LiveRangeMap[*LI] = 0;
29
30 delete LR;
Ruchira Sasanka4f3eb222002-01-07 19:19:18 +000031 }
32 }
Ruchira Sasanka4f3eb222002-01-07 19:19:18 +000033}
34
35
36//---------------------------------------------------------------------------
Ruchira Sasanka8e604792001-09-14 21:18:34 +000037// union two live ranges into one. The 2nd LR is deleted. Used for coalescing.
Ruchira Sasankaa5ab9642001-09-30 23:11:59 +000038// Note: the caller must make sure that L1 and L2 are distinct and both
39// LRs don't have suggested colors
Ruchira Sasanka4f3eb222002-01-07 19:19:18 +000040//---------------------------------------------------------------------------
Ruchira Sasanka8e604792001-09-14 21:18:34 +000041
Chris Lattner296b7732002-02-05 02:52:05 +000042void LiveRangeInfo::unionAndUpdateLRs(LiveRange *L1, LiveRange *L2) {
43 assert(L1 != L2 && (!L1->hasSuggestedColor() || !L2->hasSuggestedColor()));
44 set_union(*L1, *L2); // add elements of L2 to L1
Ruchira Sasanka8e604792001-09-14 21:18:34 +000045
Chris Lattner296b7732002-02-05 02:52:05 +000046 for(ValueSet::iterator L2It = L2->begin(); L2It != L2->end(); ++L2It) {
Ruchira Sasanka8e604792001-09-14 21:18:34 +000047 //assert(( L1->getTypeID() == L2->getTypeID()) && "Merge:Different types");
48
Chris Lattner30adeb62002-02-04 16:36:59 +000049 L1->insert(*L2It); // add the var in L2 to L1
Chris Lattner296b7732002-02-05 02:52:05 +000050 LiveRangeMap[*L2It] = L1; // now the elements in L2 should map
Ruchira Sasanka4f3eb222002-01-07 19:19:18 +000051 //to L1
Ruchira Sasanka8e604792001-09-14 21:18:34 +000052 }
Ruchira Sasankaa5ab9642001-09-30 23:11:59 +000053
54
55 // Now if LROfDef(L1) has a suggested color, it will remain.
56 // But, if LROfUse(L2) has a suggested color, the new range
57 // must have the same color.
58
59 if(L2->hasSuggestedColor())
Chris Lattner296b7732002-02-05 02:52:05 +000060 L1->setSuggestedColor(L2->getSuggestedColor());
Ruchira Sasankaa5ab9642001-09-30 23:11:59 +000061
Ruchira Sasanka958faf32001-10-19 17:21:03 +000062
Chris Lattner296b7732002-02-05 02:52:05 +000063 if (L2->isCallInterference())
Ruchira Sasanka958faf32001-10-19 17:21:03 +000064 L1->setCallInterference();
65
Chris Lattner296b7732002-02-05 02:52:05 +000066 // add the spill costs
67 L1->addSpillCost(L2->getSpillCost());
68
Chris Lattner697954c2002-01-20 22:54:45 +000069 delete L2; // delete L2 as it is no longer needed
Ruchira Sasanka8e604792001-09-14 21:18:34 +000070}
71
72
73
Ruchira Sasanka4f3eb222002-01-07 19:19:18 +000074//---------------------------------------------------------------------------
75// Method for constructing all live ranges in a method. It creates live
76// ranges for all values defined in the instruction stream. Also, it
77// creates live ranges for all incoming arguments of the method.
78//---------------------------------------------------------------------------
Chris Lattner2f898d22002-02-05 06:02:59 +000079void LiveRangeInfo::constructLiveRanges() {
Ruchira Sasanka8e604792001-09-14 21:18:34 +000080
Chris Lattner2f898d22002-02-05 06:02:59 +000081 if (DEBUG_RA)
Chris Lattner697954c2002-01-20 22:54:45 +000082 cerr << "Consturcting Live Ranges ...\n";
Ruchira Sasanka8e604792001-09-14 21:18:34 +000083
84 // first find the live ranges for all incoming args of the method since
85 // those LRs start from the start of the method
86
87 // get the argument list
88 const Method::ArgumentListType& ArgList = Meth->getArgumentList();
89 // get an iterator to arg list
90 Method::ArgumentListType::const_iterator ArgIt = ArgList.begin();
91
92
93 for( ; ArgIt != ArgList.end() ; ++ArgIt) { // for each argument
Ruchira Sasanka8e604792001-09-14 21:18:34 +000094 LiveRange * ArgRange = new LiveRange(); // creates a new LR and
Chris Lattner30adeb62002-02-04 16:36:59 +000095 const Value *Val = (const Value *) *ArgIt;
Ruchira Sasanka8e604792001-09-14 21:18:34 +000096
Chris Lattner30adeb62002-02-04 16:36:59 +000097 ArgRange->insert(Val); // add the arg (def) to it
Chris Lattner697954c2002-01-20 22:54:45 +000098 LiveRangeMap[Val] = ArgRange;
Ruchira Sasanka8e604792001-09-14 21:18:34 +000099
100 // create a temp machine op to find the register class of value
101 //const MachineOperand Op(MachineOperand::MO_VirtualRegister);
102
Ruchira Sasankaa5ab9642001-09-30 23:11:59 +0000103 unsigned rcid = MRI.getRegClassIDOfValue( Val );
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000104 ArgRange->setRegClass(RegClassList[ rcid ] );
105
106
107 if( DEBUG_RA > 1) {
Chris Lattner0665a5f2002-02-05 01:43:49 +0000108 cerr << " adding LiveRange for argument "
109 << RAV((const Value *)*ArgIt) << "\n";
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000110 }
111 }
112
Ruchira Sasankaa5ab9642001-09-30 23:11:59 +0000113 // Now suggest hardware registers for these method args
114 MRI.suggestRegs4MethodArgs(Meth, *this);
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000115
Ruchira Sasankaa5ab9642001-09-30 23:11:59 +0000116
117
118 // Now find speical LLVM instructions (CALL, RET) and LRs in machine
119 // instructions.
Chris Lattner2f898d22002-02-05 06:02:59 +0000120 //
121 for (Method::const_iterator BBI = Meth->begin(); BBI != Meth->end(); ++BBI) {
Ruchira Sasankaa5ab9642001-09-30 23:11:59 +0000122 // Now find all LRs for machine the instructions. A new LR will be created
123 // only for defs in the machine instr since, we assume that all Values are
124 // defined before they are used. However, there can be multiple defs for
125 // the same Value in machine instructions.
126
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000127 // get the iterator for machine instructions
128 const MachineCodeForBasicBlock& MIVec = (*BBI)->getMachineInstrVec();
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000129
130 // iterate over all the machine instructions in BB
Chris Lattner2f898d22002-02-05 06:02:59 +0000131 for(MachineCodeForBasicBlock::const_iterator MInstIterator = MIVec.begin();
132 MInstIterator != MIVec.end(); ++MInstIterator) {
133 const MachineInstr *MInst = *MInstIterator;
Ruchira Sasankaa5ab9642001-09-30 23:11:59 +0000134
Ruchira Sasankaa90e7702001-10-15 16:26:38 +0000135 // Now if the machine instruction is a call/return instruction,
136 // add it to CallRetInstrList for processing its implicit operands
Ruchira Sasankaa5ab9642001-09-30 23:11:59 +0000137
Chris Lattner697954c2002-01-20 22:54:45 +0000138 if(TM.getInstrInfo().isReturn(MInst->getOpCode()) ||
139 TM.getInstrInfo().isCall(MInst->getOpCode()))
Ruchira Sasankaa90e7702001-10-15 16:26:38 +0000140 CallRetInstrList.push_back( MInst );
141
142
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000143 // iterate over MI operands to find defs
Chris Lattner2f898d22002-02-05 06:02:59 +0000144 for (MachineInstr::const_val_op_iterator OpI = MInst->begin(),
145 OpE = MInst->end(); OpI != OpE; ++OpI) {
Chris Lattner697954c2002-01-20 22:54:45 +0000146 if(DEBUG_RA) {
Ruchira Sasankaa90e7702001-10-15 16:26:38 +0000147 MachineOperand::MachineOperandType OpTyp =
148 OpI.getMachineOperand().getOperandType();
Ruchira Sasankae727f852001-09-18 22:43:57 +0000149
Chris Lattner0665a5f2002-02-05 01:43:49 +0000150 if (OpTyp == MachineOperand::MO_CCRegister)
151 cerr << "\n**CC reg found. Is Def=" << OpI.isDef() << " Val:"
152 << RAV(OpI.getMachineOperand().getVRegValue()) << "\n";
Ruchira Sasankae727f852001-09-18 22:43:57 +0000153 }
Ruchira Sasankae727f852001-09-18 22:43:57 +0000154
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000155 // create a new LR iff this operand is a def
Chris Lattner30adeb62002-02-04 16:36:59 +0000156 if (OpI.isDef()) {
157 const Value *Def = *OpI;
Ruchira Sasankaa5ab9642001-09-30 23:11:59 +0000158
Ruchira Sasankaa5ab9642001-09-30 23:11:59 +0000159 // Only instruction values are accepted for live ranges here
Chris Lattner0665a5f2002-02-05 01:43:49 +0000160 if (Def->getValueType() != Value::InstructionVal ) {
161 cerr << "\n**%%Error: Def is not an instruction val. Def="
162 << RAV(Def) << "\n";
Ruchira Sasankaa5ab9642001-09-30 23:11:59 +0000163 continue;
164 }
165
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000166 LiveRange *DefRange = LiveRangeMap[Def];
167
168 // see LR already there (because of multiple defs)
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000169 if( !DefRange) { // if it is not in LiveRangeMap
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000170 DefRange = new LiveRange(); // creates a new live range and
Chris Lattner30adeb62002-02-04 16:36:59 +0000171 DefRange->insert(Def); // add the instruction (def) to it
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000172 LiveRangeMap[ Def ] = DefRange; // update the map
173
Chris Lattner0665a5f2002-02-05 01:43:49 +0000174 if (DEBUG_RA > 1)
175 cerr << " creating a LR for def: " << RAV(Def) << "\n";
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000176
177 // set the register class of the new live range
178 //assert( RegClassList.size() );
179 MachineOperand::MachineOperandType OpTy =
180 OpI.getMachineOperand().getOperandType();
181
182 bool isCC = ( OpTy == MachineOperand::MO_CCRegister);
Ruchira Sasankaa5ab9642001-09-30 23:11:59 +0000183 unsigned rcid = MRI.getRegClassIDOfValue(
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000184 OpI.getMachineOperand().getVRegValue(), isCC );
185
186
Chris Lattner0665a5f2002-02-05 01:43:49 +0000187 if (isCC && DEBUG_RA)
188 cerr << "\a**created a LR for a CC reg:"
189 << RAV(OpI.getMachineOperand().getVRegValue());
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000190
Chris Lattner0665a5f2002-02-05 01:43:49 +0000191 DefRange->setRegClass(RegClassList[rcid]);
192 } else {
Chris Lattner30adeb62002-02-04 16:36:59 +0000193 DefRange->insert(Def); // add the opearand to def range
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000194 // update the map - Operand points
195 // to the merged set
Chris Lattner0665a5f2002-02-05 01:43:49 +0000196 LiveRangeMap[Def] = DefRange;
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000197
Chris Lattner0665a5f2002-02-05 01:43:49 +0000198 if (DEBUG_RA > 1)
199 cerr << " added to an existing LR for def: "
200 << RAV(Def) << "\n";
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000201 }
202
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000203 } // if isDef()
204
205 } // for all opereands in machine instructions
206
207 } // for all machine instructions in the BB
208
Ruchira Sasankaa5ab9642001-09-30 23:11:59 +0000209 } // for all BBs in method
210
Ruchira Sasankaa5ab9642001-09-30 23:11:59 +0000211
Ruchira Sasankaa90e7702001-10-15 16:26:38 +0000212 // Now we have to suggest clors for call and return arg live ranges.
213 // Also, if there are implicit defs (e.g., retun value of a call inst)
214 // they must be added to the live range list
Ruchira Sasankaa5ab9642001-09-30 23:11:59 +0000215
Ruchira Sasankaa90e7702001-10-15 16:26:38 +0000216 suggestRegs4CallRets();
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000217
218 if( DEBUG_RA)
Chris Lattner697954c2002-01-20 22:54:45 +0000219 cerr << "Initial Live Ranges constructed!\n";
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000220
221}
222
223
Ruchira Sasanka4f3eb222002-01-07 19:19:18 +0000224//---------------------------------------------------------------------------
225// If some live ranges must be colored with specific hardware registers
226// (e.g., for outgoing call args), suggesting of colors for such live
227// ranges is done using target specific method. Those methods are called
228// from this function. The target specific methods must:
229// 1) suggest colors for call and return args.
230// 2) create new LRs for implicit defs in machine instructions
231//---------------------------------------------------------------------------
Ruchira Sasankaa90e7702001-10-15 16:26:38 +0000232void LiveRangeInfo::suggestRegs4CallRets()
233{
234
235 CallRetInstrListType::const_iterator It = CallRetInstrList.begin();
236
237 for( ; It != CallRetInstrList.end(); ++It ) {
238
239 const MachineInstr *MInst = *It;
240 MachineOpCode OpCode = MInst->getOpCode();
241
242 if( (TM.getInstrInfo()).isReturn(OpCode) )
243 MRI.suggestReg4RetValue( MInst, *this);
244
245 else if( (TM.getInstrInfo()).isCall( OpCode ) )
246 MRI.suggestRegs4CallArgs( MInst, *this, RegClassList );
247
248 else
249 assert( 0 && "Non call/ret instr in CallRetInstrList" );
250 }
251
252}
253
254
Ruchira Sasanka4f3eb222002-01-07 19:19:18 +0000255//--------------------------------------------------------------------------
256// The following method coalesces live ranges when possible. This method
257// must be called after the interference graph has been constructed.
Ruchira Sasankaa90e7702001-10-15 16:26:38 +0000258
259
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000260/* Algorithm:
261 for each BB in method
262 for each machine instruction (inst)
263 for each definition (def) in inst
264 for each operand (op) of inst that is a use
Ruchira Sasankaefaf9be2001-11-10 00:20:24 +0000265 if the def and op are of the same register type
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000266 if the def and op do not interfere //i.e., not simultaneously live
267 if (degree(LR of def) + degree(LR of op)) <= # avail regs
Ruchira Sasankaa5ab9642001-09-30 23:11:59 +0000268 if both LRs do not have suggested colors
269 merge2IGNodes(def, op) // i.e., merge 2 LRs
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000270
271*/
Ruchira Sasanka4f3eb222002-01-07 19:19:18 +0000272//---------------------------------------------------------------------------
273void LiveRangeInfo::coalesceLRs()
274{
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000275 if( DEBUG_RA)
Chris Lattner697954c2002-01-20 22:54:45 +0000276 cerr << "\nCoalscing LRs ...\n";
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000277
278 Method::const_iterator BBI = Meth->begin(); // random iterator for BBs
279
280 for( ; BBI != Meth->end(); ++BBI) { // traverse BBs in random order
281
282 // get the iterator for machine instructions
283 const MachineCodeForBasicBlock& MIVec = (*BBI)->getMachineInstrVec();
Chris Lattner697954c2002-01-20 22:54:45 +0000284 MachineCodeForBasicBlock::const_iterator MInstIterator = MIVec.begin();
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000285
286 // iterate over all the machine instructions in BB
287 for( ; MInstIterator != MIVec.end(); ++MInstIterator) {
288
289 const MachineInstr * MInst = *MInstIterator;
290
291 if( DEBUG_RA > 1) {
Chris Lattner697954c2002-01-20 22:54:45 +0000292 cerr << " *Iterating over machine instr ";
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000293 MInst->dump();
Chris Lattner697954c2002-01-20 22:54:45 +0000294 cerr << "\n";
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000295 }
296
297
298 // iterate over MI operands to find defs
Chris Lattner2f898d22002-02-05 06:02:59 +0000299 for(MachineInstr::const_val_op_iterator DefI = MInst->begin(),
300 DefE = MInst->end(); DefI != DefE; ++DefI) {
301 if (DefI.isDef()) { // iff this operand is a def
302 LiveRange *LROfDef = getLiveRangeForValue( *DefI );
303 RegClass *RCOfDef = LROfDef->getRegClass();
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000304
Chris Lattner2f898d22002-02-05 06:02:59 +0000305 MachineInstr::const_val_op_iterator UseI = MInst->begin(),
306 UseE = MInst->end();
307 for( ; UseI != UseE; ++UseI){ // for all uses
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000308
Chris Lattner2f898d22002-02-05 06:02:59 +0000309 LiveRange *LROfUse = getLiveRangeForValue( *UseI );
310 if (!LROfUse) { // if LR of use is not found
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000311 //don't warn about labels
Chris Lattner37730942002-02-05 03:52:29 +0000312 if (!isa<BasicBlock>(*UseI) && DEBUG_RA)
Chris Lattner0665a5f2002-02-05 01:43:49 +0000313 cerr << " !! Warning: No LR for use " << RAV(*UseI) << "\n";
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000314 continue; // ignore and continue
315 }
316
Chris Lattner2f898d22002-02-05 06:02:59 +0000317 if (LROfUse == LROfDef) // nothing to merge if they are same
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000318 continue;
319
Chris Lattner37730942002-02-05 03:52:29 +0000320 if (MRI.getRegType(LROfDef) == MRI.getRegType(LROfUse)) {
Ruchira Sasankaefaf9be2001-11-10 00:20:24 +0000321
322 // If the two RegTypes are the same
Chris Lattner37730942002-02-05 03:52:29 +0000323 if (!RCOfDef->getInterference(LROfDef, LROfUse) ) {
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000324
325 unsigned CombinedDegree =
326 LROfDef->getUserIGNode()->getNumOfNeighbors() +
327 LROfUse->getUserIGNode()->getNumOfNeighbors();
328
Chris Lattner37730942002-02-05 03:52:29 +0000329 if (CombinedDegree <= RCOfDef->getNumOfAvailRegs()) {
Ruchira Sasankaa5ab9642001-09-30 23:11:59 +0000330 // if both LRs do not have suggested colors
Chris Lattner37730942002-02-05 03:52:29 +0000331 if (!(LROfDef->hasSuggestedColor() &&
332 LROfUse->hasSuggestedColor())) {
Ruchira Sasankaa5ab9642001-09-30 23:11:59 +0000333
334 RCOfDef->mergeIGNodesOfLRs(LROfDef, LROfUse);
335 unionAndUpdateLRs(LROfDef, LROfUse);
336 }
337
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000338 } // if combined degree is less than # of regs
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000339 } // if def and use do not interfere
Ruchira Sasankad33238b2001-10-12 17:48:18 +0000340 }// if reg classes are the same
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000341 } // for all uses
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000342 } // if def
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000343 } // for all defs
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000344 } // for all machine instructions
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000345 } // for all BBs
346
Chris Lattner2f898d22002-02-05 06:02:59 +0000347 if (DEBUG_RA)
Chris Lattner697954c2002-01-20 22:54:45 +0000348 cerr << "\nCoalscing Done!\n";
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000349}
350
351
352
353
354
355/*--------------------------- Debug code for printing ---------------*/
356
357
Chris Lattner0665a5f2002-02-05 01:43:49 +0000358void LiveRangeInfo::printLiveRanges() {
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000359 LiveRangeMapType::iterator HMI = LiveRangeMap.begin(); // hash map iterator
Chris Lattner697954c2002-01-20 22:54:45 +0000360 cerr << "\nPrinting Live Ranges from Hash Map:\n";
Chris Lattner0665a5f2002-02-05 01:43:49 +0000361 for( ; HMI != LiveRangeMap.end(); ++HMI) {
362 if (HMI->first && HMI->second) {
363 cerr << " " << RAV(HMI->first) << "\t: ";
Chris Lattner296b7732002-02-05 02:52:05 +0000364 printSet(*HMI->second); cerr << "\n";
Ruchira Sasanka8e604792001-09-14 21:18:34 +0000365 }
366 }
367}