diff options
author | Ruchira Sasanka <sasanka@students.uiuc.edu> | 2001-10-19 17:21:03 +0000 |
---|---|---|
committer | Ruchira Sasanka <sasanka@students.uiuc.edu> | 2001-10-19 17:21:03 +0000 |
commit | 958faf3f5ac0804b264860ddb3d71fb3758aa8c4 (patch) | |
tree | 0fc0fa5512f434d6c92f3ee8426e6b5bb4a18963 | |
parent | ffa6f9ca062d410ff25c8d11907f182d022f274d (diff) | |
download | external_llvm-958faf3f5ac0804b264860ddb3d71fb3758aa8c4.zip external_llvm-958faf3f5ac0804b264860ddb3d71fb3758aa8c4.tar.gz external_llvm-958faf3f5ac0804b264860ddb3d71fb3758aa8c4.tar.bz2 |
Corrected call interference bug
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@916 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/RegAlloc/LiveRangeInfo.cpp | 5 | ||||
-rw-r--r-- | lib/CodeGen/RegAlloc/PhyRegAlloc.cpp | 96 | ||||
-rw-r--r-- | lib/Target/SparcV9/RegAlloc/LiveRangeInfo.cpp | 5 | ||||
-rw-r--r-- | lib/Target/SparcV9/RegAlloc/PhyRegAlloc.cpp | 96 |
4 files changed, 174 insertions, 28 deletions
diff --git a/lib/CodeGen/RegAlloc/LiveRangeInfo.cpp b/lib/CodeGen/RegAlloc/LiveRangeInfo.cpp index c137e67..a4c3aab 100644 --- a/lib/CodeGen/RegAlloc/LiveRangeInfo.cpp +++ b/lib/CodeGen/RegAlloc/LiveRangeInfo.cpp @@ -36,6 +36,11 @@ void LiveRangeInfo::unionAndUpdateLRs(LiveRange *const L1, LiveRange *L2) if(L2->hasSuggestedColor()) L1->setSuggestedColor( L2->getSuggestedColor() ); + + if( L2->isCallInterference() ) + L1->setCallInterference(); + + delete ( L2 ); // delete L2 as it is no longer needed } diff --git a/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp b/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp index 4b6a0f9..9830049 100644 --- a/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp +++ b/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp @@ -125,25 +125,84 @@ void PhyRegAlloc::addInterference(const Value *const Def, } - //the live range of this var interferes with this call - if( isCallInst ) { - LROfVar->addCallInterference( (const Instruction *const) Def ); - if( DEBUG_RA) { - cout << "\n ++Added Call Interf to set:"; - LROfVar->printSet(); - } - } - } else if(DEBUG_RA > 1) { // we will not have LRs for values not explicitly allocated in the // instruction stream (e.g., constants) cout << " warning: no live range for " ; printValue( *LIt); cout << endl; } - } + } + } + } + +//---------------------------------------------------------------------------- +// For a call instruction, this method sets the CallInterference flag in +// the LR of each variable live int the Live Variable Set live after the +// call instruction (except the return value of the call instruction - since +// the return value does not interfere with that call itself). +//---------------------------------------------------------------------------- + +void PhyRegAlloc::setCallInterferences(const MachineInstr *MInst, + const LiveVarSet *const LVSetAft ) +{ + // Now find the LR of the return value of the call + // The last *implicit operand* is the return value of a call + + // We do this because, we look at the LV set *after* the instruction + // to determine, which LRs must be saved across calls. The return value + // of the call is live in this set - but it does not interfere with call + // (i.e., we can allocate a volatile register to the return value) + + LiveRange *RetValLR = NULL; + + unsigned NumOfImpRefs = MInst->getNumImplicitRefs(); + if( NumOfImpRefs > 0 ) { + + if( MInst->implicitRefIsDefined(NumOfImpRefs-1) ) { + + const Value *RetVal = MInst->getImplicitRef(NumOfImpRefs-1); + RetValLR = LRI.getLiveRangeForValue( RetVal ); + assert( RetValLR && "No LR for RetValue of call"); + } + + } + + + if( DEBUG_RA) + cout << "\n For call inst: " << *MInst; + + LiveVarSet::const_iterator LIt = LVSetAft->begin(); + + // for each live var in live variable set after machine inst + for( ; LIt != LVSetAft->end(); ++LIt) { + + // get the live range corresponding to live var + LiveRange *const LR = LRI.getLiveRangeForValue(*LIt ); + + if( LR && DEBUG_RA) { + cout << "\n\tLR Aft Call: "; + LR->printSet(); + } + + + // LR can be null if it is a const since a const + // doesn't have a dominating def - see Assumptions above + if( LR && (LR != RetValLR) ) { + LR->setCallInterference(); + if( DEBUG_RA) { + cout << "\n ++Added call interf for LR: " ; + LR->printSet(); + } + } + + } + +} + + //---------------------------------------------------------------------------- // This method will walk thru code and create interferences in the IG of // each RegClass. @@ -174,7 +233,16 @@ void PhyRegAlloc::buildInterferenceGraphs() const bool isCallInst = TM.getInstrInfo().isCall(MInst->getOpCode()); - // if( isCallInst) cout << "\n%%% Found call Inst:\n"; + if( isCallInst ) { + //cout << "\nFor call inst: " << *MInst; + + // set the isCallInterference flag of each live range wich extends + // accross this call instruction. This information is used by graph + // coloring algo to avoid allocating volatile colors to live ranges + // that span across calls (since they have to be saved/restored) + setCallInterferences( MInst, LVSetAI); + } + // iterate over MI operands to find defs for( MachineInstr::val_op_const_iterator OpI(MInst);!OpI.done(); ++OpI) { @@ -275,7 +343,7 @@ void PhyRegAlloc::addInterferencesForArgs() void PhyRegAlloc::insertCallerSavingCode(const MachineInstr *MInst, const BasicBlock *BB ) { - assert( (TM.getInstrInfo()).isCall( MInst->getOpCode() ) ); + // assert( (TM.getInstrInfo()).isCall( MInst->getOpCode() ) ); int StackOff = -8; // ****TODO : Change hash_set<unsigned> PushedRegSet; @@ -315,7 +383,7 @@ void PhyRegAlloc::insertCallerSavingCode(const MachineInstr *MInst, // get the live range corresponding to live var LiveRange *const LR = LRI.getLiveRangeForValue(*LIt ); - // LROfVar can be null if it is a const since a const + // LR can be null if it is a const since a const // doesn't have a dominating def - see Assumptions above if( LR ) { @@ -354,7 +422,7 @@ void PhyRegAlloc::insertCallerSavingCode(const MachineInstr *MInst, StackOff -= 8; // ****TODO: Correct ?????? if(DEBUG_RA) { - cout << "For callee save call inst:" << *MInst << endl; + cerr << "\nFor callee save call inst:" << *MInst; cerr << "\n -inserted caller saving instrs:\n\t "; cerr << *AdIBef << "\n\t" << *AdIAft ; } diff --git a/lib/Target/SparcV9/RegAlloc/LiveRangeInfo.cpp b/lib/Target/SparcV9/RegAlloc/LiveRangeInfo.cpp index c137e67..a4c3aab 100644 --- a/lib/Target/SparcV9/RegAlloc/LiveRangeInfo.cpp +++ b/lib/Target/SparcV9/RegAlloc/LiveRangeInfo.cpp @@ -36,6 +36,11 @@ void LiveRangeInfo::unionAndUpdateLRs(LiveRange *const L1, LiveRange *L2) if(L2->hasSuggestedColor()) L1->setSuggestedColor( L2->getSuggestedColor() ); + + if( L2->isCallInterference() ) + L1->setCallInterference(); + + delete ( L2 ); // delete L2 as it is no longer needed } diff --git a/lib/Target/SparcV9/RegAlloc/PhyRegAlloc.cpp b/lib/Target/SparcV9/RegAlloc/PhyRegAlloc.cpp index 4b6a0f9..9830049 100644 --- a/lib/Target/SparcV9/RegAlloc/PhyRegAlloc.cpp +++ b/lib/Target/SparcV9/RegAlloc/PhyRegAlloc.cpp @@ -125,25 +125,84 @@ void PhyRegAlloc::addInterference(const Value *const Def, } - //the live range of this var interferes with this call - if( isCallInst ) { - LROfVar->addCallInterference( (const Instruction *const) Def ); - if( DEBUG_RA) { - cout << "\n ++Added Call Interf to set:"; - LROfVar->printSet(); - } - } - } else if(DEBUG_RA > 1) { // we will not have LRs for values not explicitly allocated in the // instruction stream (e.g., constants) cout << " warning: no live range for " ; printValue( *LIt); cout << endl; } - } + } + } + } + +//---------------------------------------------------------------------------- +// For a call instruction, this method sets the CallInterference flag in +// the LR of each variable live int the Live Variable Set live after the +// call instruction (except the return value of the call instruction - since +// the return value does not interfere with that call itself). +//---------------------------------------------------------------------------- + +void PhyRegAlloc::setCallInterferences(const MachineInstr *MInst, + const LiveVarSet *const LVSetAft ) +{ + // Now find the LR of the return value of the call + // The last *implicit operand* is the return value of a call + + // We do this because, we look at the LV set *after* the instruction + // to determine, which LRs must be saved across calls. The return value + // of the call is live in this set - but it does not interfere with call + // (i.e., we can allocate a volatile register to the return value) + + LiveRange *RetValLR = NULL; + + unsigned NumOfImpRefs = MInst->getNumImplicitRefs(); + if( NumOfImpRefs > 0 ) { + + if( MInst->implicitRefIsDefined(NumOfImpRefs-1) ) { + + const Value *RetVal = MInst->getImplicitRef(NumOfImpRefs-1); + RetValLR = LRI.getLiveRangeForValue( RetVal ); + assert( RetValLR && "No LR for RetValue of call"); + } + + } + + + if( DEBUG_RA) + cout << "\n For call inst: " << *MInst; + + LiveVarSet::const_iterator LIt = LVSetAft->begin(); + + // for each live var in live variable set after machine inst + for( ; LIt != LVSetAft->end(); ++LIt) { + + // get the live range corresponding to live var + LiveRange *const LR = LRI.getLiveRangeForValue(*LIt ); + + if( LR && DEBUG_RA) { + cout << "\n\tLR Aft Call: "; + LR->printSet(); + } + + + // LR can be null if it is a const since a const + // doesn't have a dominating def - see Assumptions above + if( LR && (LR != RetValLR) ) { + LR->setCallInterference(); + if( DEBUG_RA) { + cout << "\n ++Added call interf for LR: " ; + LR->printSet(); + } + } + + } + +} + + //---------------------------------------------------------------------------- // This method will walk thru code and create interferences in the IG of // each RegClass. @@ -174,7 +233,16 @@ void PhyRegAlloc::buildInterferenceGraphs() const bool isCallInst = TM.getInstrInfo().isCall(MInst->getOpCode()); - // if( isCallInst) cout << "\n%%% Found call Inst:\n"; + if( isCallInst ) { + //cout << "\nFor call inst: " << *MInst; + + // set the isCallInterference flag of each live range wich extends + // accross this call instruction. This information is used by graph + // coloring algo to avoid allocating volatile colors to live ranges + // that span across calls (since they have to be saved/restored) + setCallInterferences( MInst, LVSetAI); + } + // iterate over MI operands to find defs for( MachineInstr::val_op_const_iterator OpI(MInst);!OpI.done(); ++OpI) { @@ -275,7 +343,7 @@ void PhyRegAlloc::addInterferencesForArgs() void PhyRegAlloc::insertCallerSavingCode(const MachineInstr *MInst, const BasicBlock *BB ) { - assert( (TM.getInstrInfo()).isCall( MInst->getOpCode() ) ); + // assert( (TM.getInstrInfo()).isCall( MInst->getOpCode() ) ); int StackOff = -8; // ****TODO : Change hash_set<unsigned> PushedRegSet; @@ -315,7 +383,7 @@ void PhyRegAlloc::insertCallerSavingCode(const MachineInstr *MInst, // get the live range corresponding to live var LiveRange *const LR = LRI.getLiveRangeForValue(*LIt ); - // LROfVar can be null if it is a const since a const + // LR can be null if it is a const since a const // doesn't have a dominating def - see Assumptions above if( LR ) { @@ -354,7 +422,7 @@ void PhyRegAlloc::insertCallerSavingCode(const MachineInstr *MInst, StackOff -= 8; // ****TODO: Correct ?????? if(DEBUG_RA) { - cout << "For callee save call inst:" << *MInst << endl; + cerr << "\nFor callee save call inst:" << *MInst; cerr << "\n -inserted caller saving instrs:\n\t "; cerr << *AdIBef << "\n\t" << *AdIAft ; } |