From 4a12da7912a908b9494dcf777225bbe3995604d8 Mon Sep 17 00:00:00 2001 From: "Vikram S. Adve" Date: Mon, 18 Mar 2002 03:47:26 +0000 Subject: [PATCH] Fixed several problems with handling arguments to Phis. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1910 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/LiveVar/BBLiveVar.cpp | 83 ++++++++++++++---------- lib/Analysis/LiveVar/BBLiveVar.h | 11 ++-- lib/Target/SparcV9/LiveVar/BBLiveVar.cpp | 83 ++++++++++++++---------- lib/Target/SparcV9/LiveVar/BBLiveVar.h | 11 ++-- 4 files changed, 108 insertions(+), 80 deletions(-) diff --git a/lib/Analysis/LiveVar/BBLiveVar.cpp b/lib/Analysis/LiveVar/BBLiveVar.cpp index c6b8a3b8f2c..66d9f32457d 100644 --- a/lib/Analysis/LiveVar/BBLiveVar.cpp +++ b/lib/Analysis/LiveVar/BBLiveVar.cpp @@ -58,7 +58,7 @@ void BBLiveVar::calcDefUseSets() { MIE = MIVec.rend(); MII != MIE; ++MII) { const MachineInstr *MI = *MII; - if (DEBUG_LV > 1) { // debug msg + if (DEBUG_LV >= LV_DEBUG_Verbose) { // debug msg cerr << " *Iterating over machine instr "; MI->dump(); cerr << "\n"; @@ -75,8 +75,6 @@ void BBLiveVar::calcDefUseSets() { if (MI->implicitRefIsDefined(i)) addDef(MI->getImplicitRef(i)); - bool IsPhi = MI->getOpCode() == PHI; - // iterate over MI operands to find uses for (MachineInstr::const_val_op_iterator OpI = MI->begin(), OpE = MI->end(); OpI != OpE; ++OpI) { @@ -85,26 +83,37 @@ void BBLiveVar::calcDefUseSets() { if (isa(Op)) continue; // don't process labels - if (!OpI.isDef()) { // add to Defs only if this operand is a use - addUse(Op); + if (!OpI.isDef()) { // add to Uses only if this operand is a use - if (IsPhi) { // for a phi node - // put args into the PhiArgMap (Val -> BB) + // + // *** WARNING: The following code for handling dummy PHI machine + // instructions is untested. The previous code was broken and I + // fixed it, but it turned out to be unused as long as Phi elimination + // is performed during instruction selection. + // + // Put Phi operands in UseSet for the incoming edge, not node. + // They must not "hide" later defs, and must be handled specially + // during set propagation over the CFG. + if (MI->getOpCode() == PHI) { // for a phi node const Value *ArgVal = Op; - const Value *BBVal = *++OpI; // increment to point to BB of value + const BasicBlock *PredBB = cast(*++OpI); // next ptr is BB - PhiArgMap[ArgVal] = cast(BBVal); + PredToEdgeInSetMap[PredBB].insert(ArgVal); - if (DEBUG_LV > 1) + if (DEBUG_LV >= LV_DEBUG_Verbose) cerr << " - phi operand " << RAV(ArgVal) << " came from BB " - << RAV(PhiArgMap[ArgVal]) << "\n"; + << RAV(PredBB) << endl; } // if( IsPhi ) + else { + // It is not a Phi use: add to regular use set and remove later defs. + addUse(Op); + } } // if a use } // for all operands // do for implicit operands as well for (unsigned i = 0; i < MI->getNumImplicitRefs(); ++i) { - assert(!IsPhi && "Phi cannot have implicit opeands"); + assert(MI->getOpCode() != PHI && "Phi cannot have implicit opeands"); const Value *Op = MI->getImplicitRef(i); if (Op->getType()->isLabelType()) // don't process labels @@ -123,10 +132,10 @@ void BBLiveVar::calcDefUseSets() { //----------------------------------------------------------------------------- void BBLiveVar::addDef(const Value *Op) { DefSet.insert(Op); // operand is a def - so add to def set - InSet.erase(Op); // this definition kills any uses + InSet.erase(Op); // this definition kills any later uses InSetChanged = true; - if (DEBUG_LV > 1) cerr << " +Def: " << RAV(Op) << "\n"; + if (DEBUG_LV >= LV_DEBUG_Verbose) cerr << " +Def: " << RAV(Op) << "\n"; } @@ -135,16 +144,16 @@ void BBLiveVar::addDef(const Value *Op) { //----------------------------------------------------------------------------- void BBLiveVar::addUse(const Value *Op) { InSet.insert(Op); // An operand is a use - so add to use set - OutSet.erase(Op); // remove if there is a def below this use + DefSet.erase(Op); // remove if there is a def below this use InSetChanged = true; - if (DEBUG_LV > 1) cerr << " Use: " << RAV(Op) << "\n"; + if (DEBUG_LV >= LV_DEBUG_Verbose) cerr << " Use: " << RAV(Op) << "\n"; } //----------------------------------------------------------------------------- // Applies the transfer function to a basic block to produce the InSet using -// the outset. +// the OutSet. //----------------------------------------------------------------------------- bool BBLiveVar::applyTransferFunc() { @@ -160,28 +169,32 @@ bool BBLiveVar::applyTransferFunc() { //----------------------------------------------------------------------------- -// calculates Out set using In sets of the predecessors +// calculates Out set using In sets of the successors //----------------------------------------------------------------------------- bool BBLiveVar::setPropagate(ValueSet *OutSet, const ValueSet *InSet, const BasicBlock *PredBB) { bool Changed = false; - - // for all all elements in InSet + + // merge all members of InSet into OutSet of the predecessor for (ValueSet::const_iterator InIt = InSet->begin(), InE = InSet->end(); - InIt != InE; ++InIt) { - const BasicBlock *PredBBOfPhiArg = PhiArgMap[*InIt]; - - // Only propogate liveness of the value if it is either not an argument of - // a PHI node, or if it IS an argument, AND 'PredBB' is the basic block - // that it is coming in from. THIS IS BROKEN because the same value can - // come in from multiple predecessors (and it's not a multimap)! - // - if (PredBBOfPhiArg == 0 || PredBBOfPhiArg == PredBB) - if (OutSet->insert(*InIt).second) - Changed = true; - } - + InIt != InE; ++InIt) + if ((OutSet->insert(*InIt)).second) + Changed = true; + + // + //**** WARNING: The following code for handling dummy PHI machine + // instructions is untested. See explanation above. + // + // then merge all members of the EdgeInSet for the predecessor into the OutSet + const ValueSet& EdgeInSet = PredToEdgeInSetMap[PredBB]; + for (ValueSet::const_iterator InIt = EdgeInSet.begin(), InE = EdgeInSet.end(); + InIt != InE; ++InIt) + if ((OutSet->insert(*InIt)).second) + Changed = true; + // + //**** + return Changed; } @@ -193,13 +206,13 @@ bool BBLiveVar::setPropagate(ValueSet *OutSet, const ValueSet *InSet, bool BBLiveVar::applyFlowFunc() { // IMPORTANT: caller should check whether inset changed // (else no point in calling) - + // If this BB changed any OutSets of preds whose POID is lower, than we need // another iteration... // bool needAnotherIt = false; - for (pred_const_iterator PI = pred_begin(BB), PE = pred_begin(BB); + for (pred_const_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE ; ++PI) { BBLiveVar *PredLVBB = BBLiveVar::GetFromBB(*PI); diff --git a/lib/Analysis/LiveVar/BBLiveVar.h b/lib/Analysis/LiveVar/BBLiveVar.h index db5ac8f8d8f..6eac8fb7c47 100644 --- a/lib/Analysis/LiveVar/BBLiveVar.h +++ b/lib/Analysis/LiveVar/BBLiveVar.h @@ -19,14 +19,15 @@ class BBLiveVar : public Annotation { const BasicBlock *BB; // pointer to BasicBlock unsigned POID; // Post-Order ID - ValueSet DefSet; // Def set for LV analysis + ValueSet DefSet; // Def set (with no preceding uses) for LV analysis ValueSet InSet, OutSet; // In & Out for LV analysis bool InSetChanged, OutSetChanged; // set if the InSet/OutSet is modified - // map that contains phi args->BB they came - // set by calcDefUseSets & used by setPropagate - std::map PhiArgMap; - + // map that contains PredBB -> Phi arguments + // coming in on that edge. such uses have to be + // treated differently from ordinary uses. + std::map PredToEdgeInSetMap; + // method to propogate an InSet to OutSet of a predecessor bool setPropagate(ValueSet *OutSetOfPred, const ValueSet *InSetOfThisBB, diff --git a/lib/Target/SparcV9/LiveVar/BBLiveVar.cpp b/lib/Target/SparcV9/LiveVar/BBLiveVar.cpp index c6b8a3b8f2c..66d9f32457d 100644 --- a/lib/Target/SparcV9/LiveVar/BBLiveVar.cpp +++ b/lib/Target/SparcV9/LiveVar/BBLiveVar.cpp @@ -58,7 +58,7 @@ void BBLiveVar::calcDefUseSets() { MIE = MIVec.rend(); MII != MIE; ++MII) { const MachineInstr *MI = *MII; - if (DEBUG_LV > 1) { // debug msg + if (DEBUG_LV >= LV_DEBUG_Verbose) { // debug msg cerr << " *Iterating over machine instr "; MI->dump(); cerr << "\n"; @@ -75,8 +75,6 @@ void BBLiveVar::calcDefUseSets() { if (MI->implicitRefIsDefined(i)) addDef(MI->getImplicitRef(i)); - bool IsPhi = MI->getOpCode() == PHI; - // iterate over MI operands to find uses for (MachineInstr::const_val_op_iterator OpI = MI->begin(), OpE = MI->end(); OpI != OpE; ++OpI) { @@ -85,26 +83,37 @@ void BBLiveVar::calcDefUseSets() { if (isa(Op)) continue; // don't process labels - if (!OpI.isDef()) { // add to Defs only if this operand is a use - addUse(Op); + if (!OpI.isDef()) { // add to Uses only if this operand is a use - if (IsPhi) { // for a phi node - // put args into the PhiArgMap (Val -> BB) + // + // *** WARNING: The following code for handling dummy PHI machine + // instructions is untested. The previous code was broken and I + // fixed it, but it turned out to be unused as long as Phi elimination + // is performed during instruction selection. + // + // Put Phi operands in UseSet for the incoming edge, not node. + // They must not "hide" later defs, and must be handled specially + // during set propagation over the CFG. + if (MI->getOpCode() == PHI) { // for a phi node const Value *ArgVal = Op; - const Value *BBVal = *++OpI; // increment to point to BB of value + const BasicBlock *PredBB = cast(*++OpI); // next ptr is BB - PhiArgMap[ArgVal] = cast(BBVal); + PredToEdgeInSetMap[PredBB].insert(ArgVal); - if (DEBUG_LV > 1) + if (DEBUG_LV >= LV_DEBUG_Verbose) cerr << " - phi operand " << RAV(ArgVal) << " came from BB " - << RAV(PhiArgMap[ArgVal]) << "\n"; + << RAV(PredBB) << endl; } // if( IsPhi ) + else { + // It is not a Phi use: add to regular use set and remove later defs. + addUse(Op); + } } // if a use } // for all operands // do for implicit operands as well for (unsigned i = 0; i < MI->getNumImplicitRefs(); ++i) { - assert(!IsPhi && "Phi cannot have implicit opeands"); + assert(MI->getOpCode() != PHI && "Phi cannot have implicit opeands"); const Value *Op = MI->getImplicitRef(i); if (Op->getType()->isLabelType()) // don't process labels @@ -123,10 +132,10 @@ void BBLiveVar::calcDefUseSets() { //----------------------------------------------------------------------------- void BBLiveVar::addDef(const Value *Op) { DefSet.insert(Op); // operand is a def - so add to def set - InSet.erase(Op); // this definition kills any uses + InSet.erase(Op); // this definition kills any later uses InSetChanged = true; - if (DEBUG_LV > 1) cerr << " +Def: " << RAV(Op) << "\n"; + if (DEBUG_LV >= LV_DEBUG_Verbose) cerr << " +Def: " << RAV(Op) << "\n"; } @@ -135,16 +144,16 @@ void BBLiveVar::addDef(const Value *Op) { //----------------------------------------------------------------------------- void BBLiveVar::addUse(const Value *Op) { InSet.insert(Op); // An operand is a use - so add to use set - OutSet.erase(Op); // remove if there is a def below this use + DefSet.erase(Op); // remove if there is a def below this use InSetChanged = true; - if (DEBUG_LV > 1) cerr << " Use: " << RAV(Op) << "\n"; + if (DEBUG_LV >= LV_DEBUG_Verbose) cerr << " Use: " << RAV(Op) << "\n"; } //----------------------------------------------------------------------------- // Applies the transfer function to a basic block to produce the InSet using -// the outset. +// the OutSet. //----------------------------------------------------------------------------- bool BBLiveVar::applyTransferFunc() { @@ -160,28 +169,32 @@ bool BBLiveVar::applyTransferFunc() { //----------------------------------------------------------------------------- -// calculates Out set using In sets of the predecessors +// calculates Out set using In sets of the successors //----------------------------------------------------------------------------- bool BBLiveVar::setPropagate(ValueSet *OutSet, const ValueSet *InSet, const BasicBlock *PredBB) { bool Changed = false; - - // for all all elements in InSet + + // merge all members of InSet into OutSet of the predecessor for (ValueSet::const_iterator InIt = InSet->begin(), InE = InSet->end(); - InIt != InE; ++InIt) { - const BasicBlock *PredBBOfPhiArg = PhiArgMap[*InIt]; - - // Only propogate liveness of the value if it is either not an argument of - // a PHI node, or if it IS an argument, AND 'PredBB' is the basic block - // that it is coming in from. THIS IS BROKEN because the same value can - // come in from multiple predecessors (and it's not a multimap)! - // - if (PredBBOfPhiArg == 0 || PredBBOfPhiArg == PredBB) - if (OutSet->insert(*InIt).second) - Changed = true; - } - + InIt != InE; ++InIt) + if ((OutSet->insert(*InIt)).second) + Changed = true; + + // + //**** WARNING: The following code for handling dummy PHI machine + // instructions is untested. See explanation above. + // + // then merge all members of the EdgeInSet for the predecessor into the OutSet + const ValueSet& EdgeInSet = PredToEdgeInSetMap[PredBB]; + for (ValueSet::const_iterator InIt = EdgeInSet.begin(), InE = EdgeInSet.end(); + InIt != InE; ++InIt) + if ((OutSet->insert(*InIt)).second) + Changed = true; + // + //**** + return Changed; } @@ -193,13 +206,13 @@ bool BBLiveVar::setPropagate(ValueSet *OutSet, const ValueSet *InSet, bool BBLiveVar::applyFlowFunc() { // IMPORTANT: caller should check whether inset changed // (else no point in calling) - + // If this BB changed any OutSets of preds whose POID is lower, than we need // another iteration... // bool needAnotherIt = false; - for (pred_const_iterator PI = pred_begin(BB), PE = pred_begin(BB); + for (pred_const_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE ; ++PI) { BBLiveVar *PredLVBB = BBLiveVar::GetFromBB(*PI); diff --git a/lib/Target/SparcV9/LiveVar/BBLiveVar.h b/lib/Target/SparcV9/LiveVar/BBLiveVar.h index db5ac8f8d8f..6eac8fb7c47 100644 --- a/lib/Target/SparcV9/LiveVar/BBLiveVar.h +++ b/lib/Target/SparcV9/LiveVar/BBLiveVar.h @@ -19,14 +19,15 @@ class BBLiveVar : public Annotation { const BasicBlock *BB; // pointer to BasicBlock unsigned POID; // Post-Order ID - ValueSet DefSet; // Def set for LV analysis + ValueSet DefSet; // Def set (with no preceding uses) for LV analysis ValueSet InSet, OutSet; // In & Out for LV analysis bool InSetChanged, OutSetChanged; // set if the InSet/OutSet is modified - // map that contains phi args->BB they came - // set by calcDefUseSets & used by setPropagate - std::map PhiArgMap; - + // map that contains PredBB -> Phi arguments + // coming in on that edge. such uses have to be + // treated differently from ordinary uses. + std::map PredToEdgeInSetMap; + // method to propogate an InSet to OutSet of a predecessor bool setPropagate(ValueSet *OutSetOfPred, const ValueSet *InSetOfThisBB,