Changes in directory llvm/lib/CodeGen/SelectionDAG:
SelectionDAGISel.cpp updated: 1.91 -> 1.92 --- Log message: Significantly simplify this code and make it more aggressive. Instead of having a special case hack for X86, make the hack more general: if an incoming argument register is not used in any block other than the entry block, don't copy it to a vreg. This helps us compile code like this: %struct.foo = type { int, int, [0 x ubyte] } int %test(%struct.foo* %X) { %tmp1 = getelementptr %struct.foo* %X, int 0, uint 2, int 100 %tmp = load ubyte* %tmp1 ; <ubyte> [#uses=1] %tmp2 = cast ubyte %tmp to int ; <int> [#uses=1] ret int %tmp2 } to: _test: lbz r3, 108(r3) blr instead of: _test: lbz r2, 108(r3) or r3, r2, r2 blr The (dead) copy emitted to copy r3 into a vreg for extra-block uses was increasing the live range of r3 past the load, preventing the coallescing. This implements CodeGen/PowerPC/reg-coallesce-simple.ll --- Diffs of the changes: (+49 -102) SelectionDAGISel.cpp | 151 ++++++++++++++++----------------------------------- 1 files changed, 49 insertions(+), 102 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.91 llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.92 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.91 Tue Oct 18 18:23:37 2005 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Sun Oct 30 13:42:35 2005 @@ -72,14 +72,6 @@ /// anywhere in the function. std::map<const AllocaInst*, int> StaticAllocaMap; - /// BlockLocalArguments - If any arguments are only used in a single basic - /// block, and if the target can access the arguments without side-effects, - /// avoid emitting CopyToReg nodes for those arguments. This map keeps - /// track of which arguments are local to each BB. - std::multimap<BasicBlock*, std::pair<Argument*, - unsigned> > BlockLocalArguments; - - unsigned MakeReg(MVT::ValueType VT) { return RegMap->createVirtualRegister(TLI.getRegClassFor(VT)); } @@ -125,17 +117,30 @@ return false; } +/// isOnlyUsedInEntryBlock - If the specified argument is only used in the +/// entry block, return true. +static bool isOnlyUsedInEntryBlock(Argument *A) { + BasicBlock *Entry = A->getParent()->begin(); + for (Value::use_iterator UI = A->use_begin(), E = A->use_end(); UI != E; ++UI) + if (cast<Instruction>(*UI)->getParent() != Entry) + return false; // Use not in entry block. + return true; +} + FunctionLoweringInfo::FunctionLoweringInfo(TargetLowering &tli, Function &fn, MachineFunction &mf) : TLI(tli), Fn(fn), MF(mf), RegMap(MF.getSSARegMap()) { - // Initialize the mapping of values to registers. This is only set up for - // instruction values that are used outside of the block that defines - // them. + // Create a vreg for each argument register that is not dead and is used + // outside of the entry block for the function. for (Function::arg_iterator AI = Fn.arg_begin(), E = Fn.arg_end(); AI != E; ++AI) - InitializeRegForValue(AI); + if (!isOnlyUsedInEntryBlock(AI)) + InitializeRegForValue(AI); + // Initialize the mapping of values to registers. This is only set up for + // instruction values that are used outside of the block that defines + // them. Function::iterator BB = Fn.begin(), EB = Fn.end(); for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) @@ -1072,104 +1077,45 @@ } } -/// IsOnlyUsedInOneBasicBlock - If the specified argument is only used in a -/// single basic block, return that block. Otherwise, return a null pointer. -static BasicBlock *IsOnlyUsedInOneBasicBlock(Argument *A) { - if (A->use_empty()) return 0; - BasicBlock *BB = cast<Instruction>(A->use_back())->getParent(); - for (Argument::use_iterator UI = A->use_begin(), E = A->use_end(); UI != E; - ++UI) - if (isa<PHINode>(*UI) || cast<Instruction>(*UI)->getParent() != BB) - return 0; // Disagreement among the users? - - // Okay, there is a single BB user. Only permit this optimization if this is - // the entry block, otherwise, we might sink argument loads into loops and - // stuff. Later, when we have global instruction selection, this won't be an - // issue clearly. - if (BB == BB->getParent()->begin()) - return BB; - return 0; -} - void SelectionDAGISel:: LowerArguments(BasicBlock *BB, SelectionDAGLowering &SDL, std::vector<SDOperand> &UnorderedChains) { // If this is the entry block, emit arguments. Function &F = *BB->getParent(); FunctionLoweringInfo &FuncInfo = SDL.FuncInfo; + SDOperand OldRoot = SDL.DAG.getRoot(); + std::vector<SDOperand> Args = TLI.LowerArguments(F, SDL.DAG); - if (BB == &F.front()) { - SDOperand OldRoot = SDL.DAG.getRoot(); - - std::vector<SDOperand> Args = TLI.LowerArguments(F, SDL.DAG); - - // If there were side effects accessing the argument list, do not do - // anything special. - if (OldRoot != SDL.DAG.getRoot()) { - unsigned a = 0; - for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); - AI != E; ++AI,++a) - if (!AI->use_empty()) { - SDL.setValue(AI, Args[a]); - - SDOperand Copy = - CopyValueToVirtualRegister(SDL, AI, FuncInfo.ValueMap[AI]); - UnorderedChains.push_back(Copy); - } - } else { - // Otherwise, if any argument is only accessed in a single basic block, - // emit that argument only to that basic block. - unsigned a = 0; - for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); - AI != E; ++AI,++a) - if (!AI->use_empty()) { - if (BasicBlock *BBU = IsOnlyUsedInOneBasicBlock(AI)) { - FuncInfo.BlockLocalArguments.insert(std::make_pair(BBU, - std::make_pair(AI, a))); - } else { - SDL.setValue(AI, Args[a]); - SDOperand Copy = - CopyValueToVirtualRegister(SDL, AI, FuncInfo.ValueMap[AI]); - UnorderedChains.push_back(Copy); - } - } - } - - // Next, if the function has live ins that need to be copied into vregs, - // emit the copies now, into the top of the block. - MachineFunction &MF = SDL.DAG.getMachineFunction(); - if (MF.livein_begin() != MF.livein_end()) { - SSARegMap *RegMap = MF.getSSARegMap(); - const MRegisterInfo &MRI = *MF.getTarget().getRegisterInfo(); - for (MachineFunction::livein_iterator LI = MF.livein_begin(), - E = MF.livein_end(); LI != E; ++LI) - if (LI->second) - MRI.copyRegToReg(*MF.begin(), MF.begin()->end(), LI->second, - LI->first, RegMap->getRegClass(LI->second)); - } + unsigned a = 0; + for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); + AI != E; ++AI, ++a) + if (!AI->use_empty()) { + SDL.setValue(AI, Args[a]); - // Finally, if the target has anything special to do, allow it to do so. - EmitFunctionEntryCode(F, SDL.DAG.getMachineFunction()); - } - - // See if there are any block-local arguments that need to be emitted in this - // block. - - if (!FuncInfo.BlockLocalArguments.empty()) { - std::multimap<BasicBlock*, std::pair<Argument*, unsigned> >::iterator BLAI = - FuncInfo.BlockLocalArguments.lower_bound(BB); - if (BLAI != FuncInfo.BlockLocalArguments.end() && BLAI->first == BB) { - // Lower the arguments into this block. - std::vector<SDOperand> Args = TLI.LowerArguments(F, SDL.DAG); - - // Set up the value mapping for the local arguments. - for (; BLAI != FuncInfo.BlockLocalArguments.end() && BLAI->first == BB; - ++BLAI) - SDL.setValue(BLAI->second.first, Args[BLAI->second.second]); - - // Any dead arguments will just be ignored here. + // If this argument is live outside of the entry block, insert a copy from + // whereever we got it to the vreg that other BB's will reference it as. + if (FuncInfo.ValueMap.count(AI)) { + SDOperand Copy = + CopyValueToVirtualRegister(SDL, AI, FuncInfo.ValueMap[AI]); + UnorderedChains.push_back(Copy); + } } + + // Next, if the function has live ins that need to be copied into vregs, + // emit the copies now, into the top of the block. + MachineFunction &MF = SDL.DAG.getMachineFunction(); + if (MF.livein_begin() != MF.livein_end()) { + SSARegMap *RegMap = MF.getSSARegMap(); + const MRegisterInfo &MRI = *MF.getTarget().getRegisterInfo(); + for (MachineFunction::livein_iterator LI = MF.livein_begin(), + E = MF.livein_end(); LI != E; ++LI) + if (LI->second) + MRI.copyRegToReg(*MF.begin(), MF.begin()->end(), LI->second, + LI->first, RegMap->getRegClass(LI->second)); } + + // Finally, if the target has anything special to do, allow it to do so. + EmitFunctionEntryCode(F, SDL.DAG.getMachineFunction()); } @@ -1180,8 +1126,9 @@ std::vector<SDOperand> UnorderedChains; - // Lower any arguments needed in this block. - LowerArguments(LLVMBB, SDL, UnorderedChains); + // Lower any arguments needed in this block if this is the entry block. + if (LLVMBB == &LLVMBB->getParent()->front()) + LowerArguments(LLVMBB, SDL, UnorderedChains); BB = FuncInfo.MBBMap[LLVMBB]; SDL.setCurrentBasicBlock(BB); _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits