aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/LiveVar/FunctionLiveVarInfo.cpp
blob: 5de35ff1be58da22dc614d7cc7ff54dff658f1ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
/* Title:   MethodLiveVarInfo.cpp
   Author:  Ruchira Sasanka
   Date:    Jun 30, 01
   Purpose: 

   This is the interface for live variable info of a method that is required 
   by any other part of the compiler.

*/


#include "llvm/Analysis/LiveVar/MethodLiveVarInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "Support/PostOrderIterator.h"
#include <iostream>
using std::cout;
using std::endl;

//************************** Constructor/Destructor ***************************


MethodLiveVarInfo::MethodLiveVarInfo(const Method *const M) : Meth(M) {
  assert(!M->isExternal() && "Cannot be a prototype declaration");
  HasAnalyzed = false;                  // still we haven't called analyze()
}



MethodLiveVarInfo:: ~MethodLiveVarInfo()
{
  // First delete all BBLiveVar objects created in constructBBs(). A new object
  // of type  BBLiveVa is created for every BasicBlock in the method

  // hash map iterator for BB2BBLVMap
  //
  BBToBBLiveVarMapType::iterator HMI = BB2BBLVMap.begin(); 

  for( ; HMI != BB2BBLVMap.end() ; HMI ++ ) {  
    if( (*HMI).first )                // delete all BBLiveVar in BB2BBLVMap
      delete (*HMI).second;
   }


  // Then delete all objects of type LiveVarSet created in calcLiveVarSetsForBB
  // and entered into  MInst2LVSetBI and  MInst2LVSetAI (these are caches
  // to return LiveVarSet's before/after a machine instruction quickly). It
  // is sufficient to free up all LiveVarSet using only one cache since 
  // both caches refer to the same sets

  // hash map iterator for MInst2LVSetBI
  //
  MInstToLiveVarSetMapType::iterator MI =  MInst2LVSetBI.begin(); 

  for( ; MI !=  MInst2LVSetBI.end() ; MI ++ ) {  
    if( (*MI).first )              // delete all LiveVarSets in  MInst2LVSetBI
      delete (*MI).second;
   }
}


// ************************* support functions ********************************


//-----------------------------------------------------------------------------
// constructs BBLiveVars and init Def and In sets
//-----------------------------------------------------------------------------

void MethodLiveVarInfo::constructBBs()   
{
  unsigned int POId = 0;                // Reverse Depth-first Order ID

  po_iterator<const Method*> BBI = po_begin(Meth);

  for(  ; BBI != po_end(Meth) ; ++BBI, ++POId) 
  { 

    const BasicBlock *BB = *BBI;        // get the current BB 

    if(DEBUG_LV) { cout << " For BB "; printValue(BB); cout << ":" << endl; }

                                        // create a new BBLiveVar
    BBLiveVar * LVBB = new BBLiveVar( BB, POId );  
    
    BB2BBLVMap[ BB ] = LVBB;            // insert the pair to Map
    
    LVBB->calcDefUseSets();             // calculates the def and in set

    if(DEBUG_LV) 
      LVBB->printAllSets();
  }

  // Since the PO iterator does not discover unreachable blocks,
  // go over the random iterator and init those blocks as well.
  // However, LV info is not correct for those blocks (they are not
  // analyzed)

  Method::const_iterator BBRI = Meth->begin();  // random iterator for BBs   

  for( ; BBRI != Meth->end(); ++BBRI, ++POId) {     

    if(   ! BB2BBLVMap[ *BBRI ] )
      BB2BBLVMap[ *BBRI ] = new BBLiveVar( *BBRI, POId );

  }


}


//-----------------------------------------------------------------------------
// do one backward pass over the CFG (for iterative analysis)
//-----------------------------------------------------------------------------
bool MethodLiveVarInfo::doSingleBackwardPass()  
{
  bool ResultFlow, NeedAnotherIteration = false;

  if(DEBUG_LV) 
    cout << endl <<  " After Backward Pass ..." << endl;

  po_iterator<const Method*> BBI = po_begin(Meth);

  for( ; BBI != po_end(Meth) ; ++BBI) 
  { 

    BBLiveVar* LVBB = BB2BBLVMap[*BBI];
    assert( LVBB );

    if(DEBUG_LV) cout << " For BB " << (*BBI)->getName() << ":"  << endl;
    // cout << " (POId=" << LVBB->getPOId() << ")" << endl ;

    ResultFlow = false;

    if( LVBB->isOutSetChanged() ) 
      LVBB->applyTransferFunc();        // apply the Tran Func to calc InSet

    if( LVBB->isInSetChanged() )        // to calc Outsets of preds
      ResultFlow = LVBB->applyFlowFunc(BB2BBLVMap); 

    if(DEBUG_LV) LVBB->printInOutSets();


    if( ResultFlow ) NeedAnotherIteration = true;

  }

  // true if we need to reiterate over the CFG
  return NeedAnotherIteration;         
}




//-----------------------------------------------------------------------------
// performs live var anal for a method
//-----------------------------------------------------------------------------
void MethodLiveVarInfo::analyze()        
{
  // Don't analyze the same method twice!
  // Later, we need to add change notification here.

  
  if (HasAnalyzed)
    return;
    

  if( DEBUG_LV) cout << "Analysing live variables ..." << endl;

  // create and initialize all the BBLiveVars of the CFG
  constructBBs();        

  bool NeedAnotherIteration = false;
  do {                                // do one  pass over  CFG
    NeedAnotherIteration = doSingleBackwardPass( );   
  } while (NeedAnotherIteration );    // repeat until we need more iterations

  
  HasAnalyzed  = true;                // finished analysing

  if( DEBUG_LV) cout << "Live Variable Analysis complete!" << endl;
}



//-----------------------------------------------------------------------------
/* Following functions will give the LiveVar info for any machine instr in
   a method. It should be called after a call to analyze().

   Thsese functions calucluates live var info for all the machine instrs in a 
   BB when LVInfo for one inst is requested. Hence, this function is useful 
   when live var info is required for many (or all) instructions in a basic 
   block. Also, the arguments to this method does not require specific 
   iterators.
*/
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Gives live variable information before a machine instruction
//-----------------------------------------------------------------------------
const LiveVarSet * 
MethodLiveVarInfo::getLiveVarSetBeforeMInst(const MachineInstr *const MInst,
					    const BasicBlock *const CurBB) 
{
  const LiveVarSet *LVSet = MInst2LVSetBI[MInst];

  if( LVSet  ) return LVSet;              // if found, just return the set
  else { 
    calcLiveVarSetsForBB( CurBB );        // else, calc for all instrs in BB

    /*if(  ! MInst2LVSetBI[ MInst ] ) {
      cerr << "\nFor BB "; printValue( CurBB);
      cerr << "\nRequested LVSet for inst: " << *MInst;
      }*/

    assert( MInst2LVSetBI[ MInst ] );
    return  MInst2LVSetBI[ MInst ];
  }
}


//-----------------------------------------------------------------------------
// Gives live variable information after a machine instruction
//-----------------------------------------------------------------------------
const LiveVarSet * 
MethodLiveVarInfo::getLiveVarSetAfterMInst(const MachineInstr *const MInst,
					    const BasicBlock *const CurBB) 
{
  const LiveVarSet *LVSet = MInst2LVSetAI[MInst];

  if( LVSet  ) return LVSet;              // if found, just return the set
  else { 
    calcLiveVarSetsForBB( CurBB );        // else, calc for all instrs in BB
    assert( MInst2LVSetAI[ MInst ] );
    return  MInst2LVSetAI[ MInst ];
  }
}



//-----------------------------------------------------------------------------
// This method calculates the live variable information for all the 
// instructions in a basic block and enter the newly constructed live
// variable sets into a the caches ( MInst2LVSetAI,  MInst2LVSetBI)
//-----------------------------------------------------------------------------
void MethodLiveVarInfo::calcLiveVarSetsForBB(const BasicBlock *const BB)
{
  const MachineCodeForBasicBlock& MIVec = BB->getMachineInstrVec();
  MachineCodeForBasicBlock::const_reverse_iterator 
    MInstIterator = MIVec.rbegin();

  LiveVarSet *CurSet = new LiveVarSet();
  const LiveVarSet *SetAI = getOutSetOfBB(BB); // init SetAI with OutSet
  CurSet->setUnion(SetAI);                     // CurSet now contains OutSet

  // iterate over all the machine instructions in BB
  for( ; MInstIterator != MIVec.rend(); MInstIterator++) {  

    // MInst is cur machine inst
    const MachineInstr * MInst  = *MInstIterator;  

    MInst2LVSetAI[MInst] = SetAI;              // record in After Inst map
    
    CurSet->applyTranferFuncForMInst( MInst ); // apply the transfer Func
    LiveVarSet *NewSet = new LiveVarSet();     // create a new set and
    NewSet->setUnion( CurSet );                // copy the set after T/F to it
 
    MInst2LVSetBI[MInst] = NewSet;             // record in Before Inst map

    // SetAI will be used in the next iteration
    SetAI = NewSet;                 
  }
  
}