[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