| Chris Lattner | 4ee3632 | 2004-01-09 18:15:24 +0000 | [diff] [blame] | 1 | //===-- BBLiveVar.cpp - Live Variable Analysis for a BasicBlock -----------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file was developed by the LLVM research group and is distributed under |
| 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This is a wrapper class for BasicBlock which is used by live var analysis. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #include "BBLiveVar.h" |
| 15 | #include "llvm/CodeGen/FunctionLiveVarInfo.h" |
| 16 | #include "llvm/CodeGen/MachineInstr.h" |
| 17 | #include "llvm/CodeGen/MachineBasicBlock.h" |
| 18 | #include "llvm/Support/CFG.h" |
| 19 | #include "Support/SetOperations.h" |
| 20 | #include "../SparcInternals.h" |
| 21 | |
| 22 | namespace llvm { |
| 23 | |
| Alkis Evlogimenos | 8f41426 | 2004-02-11 17:55:09 +0000 | [diff] [blame] | 24 | BBLiveVar::BBLiveVar(const BasicBlock &bb, |
| 25 | const MachineBasicBlock &mbb, |
| 26 | unsigned id) |
| Chris Lattner | 4ee3632 | 2004-01-09 18:15:24 +0000 | [diff] [blame] | 27 | : BB(bb), MBB(mbb), POID(id) { |
| 28 | InSetChanged = OutSetChanged = false; |
| 29 | |
| 30 | calcDefUseSets(); |
| 31 | } |
| 32 | |
| 33 | //----------------------------------------------------------------------------- |
| 34 | // calculates def and use sets for each BB |
| 35 | // There are two passes over operands of a machine instruction. This is |
| 36 | // because, we can have instructions like V = V + 1, since we no longer |
| 37 | // assume single definition. |
| 38 | //----------------------------------------------------------------------------- |
| 39 | |
| 40 | void BBLiveVar::calcDefUseSets() { |
| 41 | // iterate over all the machine instructions in BB |
| 42 | for (MachineBasicBlock::const_reverse_iterator MII = MBB.rbegin(), |
| 43 | MIE = MBB.rend(); MII != MIE; ++MII) { |
| Alkis Evlogimenos | 80da865 | 2004-02-12 02:27:10 +0000 | [diff] [blame] | 44 | const MachineInstr *MI = &*MII; |
| Chris Lattner | 4ee3632 | 2004-01-09 18:15:24 +0000 | [diff] [blame] | 45 | |
| 46 | if (DEBUG_LV >= LV_DEBUG_Verbose) { |
| 47 | std::cerr << " *Iterating over machine instr "; |
| 48 | MI->dump(); |
| 49 | std::cerr << "\n"; |
| 50 | } |
| 51 | |
| 52 | // iterate over MI operands to find defs |
| 53 | for (MachineInstr::const_val_op_iterator OpI = MI->begin(), OpE = MI->end(); |
| 54 | OpI != OpE; ++OpI) |
| 55 | if (OpI.isDef()) // add to Defs if this operand is a def |
| 56 | addDef(*OpI); |
| 57 | |
| 58 | // do for implicit operands as well |
| 59 | for (unsigned i = 0; i < MI->getNumImplicitRefs(); ++i) |
| 60 | if (MI->getImplicitOp(i).isDef()) |
| 61 | addDef(MI->getImplicitRef(i)); |
| 62 | |
| 63 | // iterate over MI operands to find uses |
| 64 | for (MachineInstr::const_val_op_iterator OpI = MI->begin(), OpE = MI->end(); |
| 65 | OpI != OpE; ++OpI) { |
| 66 | const Value *Op = *OpI; |
| 67 | |
| 68 | if (isa<BasicBlock>(Op)) |
| 69 | continue; // don't process labels |
| 70 | |
| 71 | if (OpI.isUse()) { // add to Uses only if this operand is a use |
| 72 | // |
| 73 | // *** WARNING: The following code for handling dummy PHI machine |
| 74 | // instructions is untested. The previous code was broken and I |
| 75 | // fixed it, but it turned out to be unused as long as Phi |
| 76 | // elimination is performed during instruction selection. |
| 77 | // |
| 78 | // Put Phi operands in UseSet for the incoming edge, not node. |
| 79 | // They must not "hide" later defs, and must be handled specially |
| 80 | // during set propagation over the CFG. |
| Brian Gaeke | b22186a | 2004-02-11 20:47:34 +0000 | [diff] [blame] | 81 | if (MI->getOpcode() == V9::PHI) { // for a phi node |
| Chris Lattner | 4ee3632 | 2004-01-09 18:15:24 +0000 | [diff] [blame] | 82 | const Value *ArgVal = Op; |
| 83 | const BasicBlock *PredBB = cast<BasicBlock>(*++OpI); // next ptr is BB |
| 84 | |
| 85 | PredToEdgeInSetMap[PredBB].insert(ArgVal); |
| 86 | |
| 87 | if (DEBUG_LV >= LV_DEBUG_Verbose) |
| 88 | std::cerr << " - phi operand " << RAV(ArgVal) << " came from BB " |
| 89 | << RAV(PredBB) << "\n"; |
| 90 | } // if( IsPhi ) |
| 91 | else { |
| 92 | // It is not a Phi use: add to regular use set and remove later defs. |
| 93 | addUse(Op); |
| 94 | } |
| 95 | } // if a use |
| 96 | } // for all operands |
| 97 | |
| 98 | // do for implicit operands as well |
| 99 | for (unsigned i = 0; i < MI->getNumImplicitRefs(); ++i) { |
| Brian Gaeke | b22186a | 2004-02-11 20:47:34 +0000 | [diff] [blame] | 100 | assert(MI->getOpcode() != V9::PHI && "Phi cannot have implicit operands"); |
| Chris Lattner | 4ee3632 | 2004-01-09 18:15:24 +0000 | [diff] [blame] | 101 | const Value *Op = MI->getImplicitRef(i); |
| 102 | |
| 103 | if (Op->getType() == Type::LabelTy) // don't process labels |
| 104 | continue; |
| 105 | |
| 106 | if (MI->getImplicitOp(i).isUse()) |
| 107 | addUse(Op); |
| 108 | } |
| 109 | } // for all machine instructions |
| 110 | } |
| 111 | |
| 112 | |
| 113 | |
| 114 | //----------------------------------------------------------------------------- |
| 115 | // To add an operand which is a def |
| 116 | //----------------------------------------------------------------------------- |
| 117 | void BBLiveVar::addDef(const Value *Op) { |
| 118 | DefSet.insert(Op); // operand is a def - so add to def set |
| 119 | InSet.erase(Op); // this definition kills any later uses |
| 120 | InSetChanged = true; |
| 121 | |
| 122 | if (DEBUG_LV >= LV_DEBUG_Verbose) std::cerr << " +Def: " << RAV(Op) << "\n"; |
| 123 | } |
| 124 | |
| 125 | |
| 126 | //----------------------------------------------------------------------------- |
| 127 | // To add an operand which is a use |
| 128 | //----------------------------------------------------------------------------- |
| 129 | void BBLiveVar::addUse(const Value *Op) { |
| 130 | InSet.insert(Op); // An operand is a use - so add to use set |
| 131 | DefSet.erase(Op); // remove if there is a def below this use |
| 132 | InSetChanged = true; |
| 133 | |
| 134 | if (DEBUG_LV >= LV_DEBUG_Verbose) std::cerr << " Use: " << RAV(Op) << "\n"; |
| 135 | } |
| 136 | |
| 137 | |
| 138 | //----------------------------------------------------------------------------- |
| 139 | // Applies the transfer function to a basic block to produce the InSet using |
| 140 | // the OutSet. |
| 141 | //----------------------------------------------------------------------------- |
| 142 | |
| 143 | bool BBLiveVar::applyTransferFunc() { |
| 144 | // IMPORTANT: caller should check whether the OutSet changed |
| 145 | // (else no point in calling) |
| 146 | |
| 147 | ValueSet OutMinusDef = set_difference(OutSet, DefSet); |
| 148 | InSetChanged = set_union(InSet, OutMinusDef); |
| 149 | |
| 150 | OutSetChanged = false; // no change to OutSet since transf func applied |
| 151 | return InSetChanged; |
| 152 | } |
| 153 | |
| 154 | |
| 155 | //----------------------------------------------------------------------------- |
| 156 | // calculates Out set using In sets of the successors |
| 157 | //----------------------------------------------------------------------------- |
| 158 | |
| 159 | bool BBLiveVar::setPropagate(ValueSet *OutSet, const ValueSet *InSet, |
| 160 | const BasicBlock *PredBB) { |
| 161 | bool Changed = false; |
| 162 | |
| 163 | // merge all members of InSet into OutSet of the predecessor |
| 164 | for (ValueSet::const_iterator InIt = InSet->begin(), InE = InSet->end(); |
| 165 | InIt != InE; ++InIt) |
| 166 | if ((OutSet->insert(*InIt)).second) |
| 167 | Changed = true; |
| 168 | |
| 169 | // |
| 170 | //**** WARNING: The following code for handling dummy PHI machine |
| 171 | // instructions is untested. See explanation above. |
| 172 | // |
| 173 | // then merge all members of the EdgeInSet for the predecessor into the OutSet |
| 174 | const ValueSet& EdgeInSet = PredToEdgeInSetMap[PredBB]; |
| 175 | for (ValueSet::const_iterator InIt = EdgeInSet.begin(), InE = EdgeInSet.end(); |
| 176 | InIt != InE; ++InIt) |
| 177 | if ((OutSet->insert(*InIt)).second) |
| 178 | Changed = true; |
| 179 | // |
| 180 | //**** |
| 181 | |
| 182 | return Changed; |
| 183 | } |
| 184 | |
| 185 | |
| 186 | //----------------------------------------------------------------------------- |
| 187 | // propagates in set to OutSets of PREDECESSORs |
| 188 | //----------------------------------------------------------------------------- |
| 189 | |
| 190 | bool BBLiveVar::applyFlowFunc(hash_map<const BasicBlock*, |
| 191 | BBLiveVar*> &BBLiveVarInfo) { |
| 192 | // IMPORTANT: caller should check whether inset changed |
| 193 | // (else no point in calling) |
| 194 | |
| 195 | // If this BB changed any OutSets of preds whose POID is lower, than we need |
| 196 | // another iteration... |
| 197 | // |
| 198 | bool needAnotherIt = false; |
| 199 | |
| 200 | for (pred_const_iterator PI = pred_begin(&BB), PE = pred_end(&BB); |
| 201 | PI != PE ; ++PI) { |
| 202 | BBLiveVar *PredLVBB = BBLiveVarInfo[*PI]; |
| 203 | |
| 204 | // do set union |
| 205 | if (setPropagate(&PredLVBB->OutSet, &InSet, *PI)) { |
| 206 | PredLVBB->OutSetChanged = true; |
| 207 | |
| 208 | // if the predec POID is lower than mine |
| 209 | if (PredLVBB->getPOId() <= POID) |
| 210 | needAnotherIt = true; |
| 211 | } |
| 212 | } // for |
| 213 | |
| 214 | return needAnotherIt; |
| 215 | } |
| 216 | |
| 217 | |
| 218 | |
| 219 | // ----------------- Methods For Debugging (Printing) ----------------- |
| 220 | |
| 221 | void BBLiveVar::printAllSets() const { |
| 222 | std::cerr << " Defs: "; printSet(DefSet); std::cerr << "\n"; |
| 223 | std::cerr << " In: "; printSet(InSet); std::cerr << "\n"; |
| 224 | std::cerr << " Out: "; printSet(OutSet); std::cerr << "\n"; |
| 225 | } |
| 226 | |
| 227 | void BBLiveVar::printInOutSets() const { |
| 228 | std::cerr << " In: "; printSet(InSet); std::cerr << "\n"; |
| 229 | std::cerr << " Out: "; printSet(OutSet); std::cerr << "\n"; |
| 230 | } |
| 231 | |
| 232 | } // End llvm namespace |