[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sun Oct 30 11:42:47 PST 2005
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);
More information about the llvm-commits
mailing list