Pluggable coalescers inplementation.
authorDavid Greene <greened@obbligato.org>
Thu, 6 Sep 2007 16:18:45 +0000 (16:18 +0000)
committerDavid Greene <greened@obbligato.org>
Thu, 6 Sep 2007 16:18:45 +0000 (16:18 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41743 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/LinkAllCodegenComponents.h
include/llvm/CodeGen/Passes.h
include/llvm/CodeGen/RegisterCoalescer.h [new file with mode: 0644]
include/llvm/CodeGen/SimpleRegisterCoalescing.h
lib/CodeGen/RegAllocLinearScan.cpp
lib/CodeGen/RegisterCoalescer.cpp [new file with mode: 0644]
lib/CodeGen/SimpleRegisterCoalescing.cpp

index 15021c1eb5d63277c9d23800f7f1dc9f45cbb871..c3cc906cb8da448f7e71b9dc67b9d8b9db8ade13 100644 (file)
@@ -32,6 +32,8 @@ namespace {
       (void) llvm::createLocalRegisterAllocator();
       (void) llvm::createBigBlockRegisterAllocator();
       (void) llvm::createLinearScanRegisterAllocator();
+
+      (void) llvm::createSimpleRegisterCoalescer();
       
       (void) llvm::createBFS_DAGScheduler(NULL, NULL, NULL);
       (void) llvm::createSimpleDAGScheduler(NULL, NULL, NULL);
index 45129829038e800c4926c7cd3f45ded33aa51179..ed96b40a1093275187f24070740b43b20ce154b7 100644 (file)
@@ -23,6 +23,7 @@ namespace llvm {
   class FunctionPass;
   class PassInfo;
   class TargetMachine;
+  class RegisterCoalescer;
 
   /// createUnreachableBlockEliminationPass - The LLVM code generator does not
   /// work well with unreachable basic blocks (what live ranges make sense for a
@@ -84,6 +85,11 @@ namespace llvm {
   ///
   FunctionPass *createLinearScanRegisterAllocator();
 
+  /// SimpleRegisterCoalescing Pass - Coalesce all copies possible.  Can run
+  /// independently of the register allocator.
+  ///
+  RegisterCoalescer *createSimpleRegisterCoalescer();
+
   /// PrologEpilogCodeInserter Pass - This pass inserts prolog and epilog code,
   /// and eliminates abstract frame references.
   ///
diff --git a/include/llvm/CodeGen/RegisterCoalescer.h b/include/llvm/CodeGen/RegisterCoalescer.h
new file mode 100644 (file)
index 0000000..e7727d5
--- /dev/null
@@ -0,0 +1,159 @@
+//===-- RegisterCoalescer.h - Register Coalescing Interface ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the abstract interface for register coalescers, 
+// allowing them to interact with and query register allocators.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/System/IncludeFile.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/LiveIntervalAnalysis.h"
+#include "llvm/CodeGen/LiveVariables.h"
+#include "llvm/Target/MRegisterInfo.h"
+#include "llvm/Support/Debug.h"
+
+#ifndef LLVM_CODEGEN_REGISTER_COALESCER_H
+#define LLVM_CODEGEN_REGISTER_COALESCER_H
+
+namespace llvm 
+{
+  class MachineFunction;
+  class RegallocQuery;
+  class AnalysisUsage;
+  class LiveIntervals;
+  class MachineInstr;
+  class MRegisterInfo;
+
+  /// An abstract interface for register coalescers.  Coalescers must
+  /// implement this interface to be part of the coalescer analysis
+  /// group.
+  class RegisterCoalescer {
+  public:
+    static char ID; // Class identification, replacement for typeinfo
+    RegisterCoalescer() {}
+    virtual ~RegisterCoalescer();  // We want to be subclassed
+
+    /// Run the coalescer on this function, providing interference
+    /// data to query.  Return whether we removed any copies.
+    virtual bool coalesceFunction(MachineFunction &mf,
+                                  RegallocQuery &ifd) = 0;
+
+    /// Reset state.  Can be used to allow a coalescer run by
+    /// PassManager to be run again by the register allocator.
+    virtual void reset(MachineFunction &mf) {};
+
+    /// Register allocators must call this from their own
+    /// getAnalysisUsage to cover the case where the coalescer is not
+    /// a Pass in the proper sense and isn't managed by PassManager.
+    /// PassManager needs to know which analyses to make available and
+    /// which to invalidate when running the register allocator or any
+    /// pass that might call coalescing.  The long-term solution is to
+    /// allow hierarchies of PassManagers.
+    virtual void getAnalysisUsage(AnalysisUsage &AU) const {};
+  }; 
+
+  /// An abstract interface for register allocators to interact with
+  /// coalescers
+  ///
+  /// Example:
+  ///
+  /// This is simply an example of how to use the RegallocQuery
+  /// interface.  It is not meant to be used in production.
+  ///
+  ///   class LinearScanRegallocQuery : public RegallocQuery {
+  ///   private:
+  ///     const LiveIntervals &li;
+  ///
+  ///   public:
+  ///     LinearScanRegallocQuery(LiveIntervals &intervals) 
+  ///         : li(intervals) {};
+  ///
+  ///     /// This is pretty slow and conservative, but since linear scan
+  ///     /// allocation doesn't pre-compute interference information it's
+  ///     /// the best we can do.  Coalescers are always free to ignore this
+  ///     /// and implement their own discovery strategy.  See
+  ///     /// SimpleRegisterCoalescing for an example.
+  ///     void getInterferences(IntervalSet &interferences,
+  ///                           const LiveInterval &a) const {
+  ///       for(LiveIntervals::const_iterator iv = li.begin(),
+  ///             ivend = li.end();
+  ///           iv != ivend;
+  ///           ++iv) {
+  ///         if (interfere(a, iv->second)) {
+  ///           interferences.insert(&iv->second);
+  ///         }
+  ///       }
+  ///     };
+  ///
+  ///     /// This is *really* slow and stupid.  See above.
+  ///     int getNumberOfInterferences(const LiveInterval &a) const {
+  ///       IntervalSet intervals;
+  ///       getInterferences(intervals, a);
+  ///       return(intervals.size());
+  ///     };
+  ///   };  
+  ///
+  ///   In the allocator:
+  ///
+  ///   RegisterCoalescer &coalescer = getAnalysis<RegisterCoalescer>();
+  ///
+  ///   // We don't reset the coalescer so if it's already been run this
+  ///   // takes almost no time.
+  ///   LinearScanRegallocQuery ifd(*li_);
+  ///   coalescer.coalesceFunction(fn, ifd);
+  ///
+  class RegallocQuery {
+  public:
+    typedef SmallPtrSet<const LiveInterval *, 8> IntervalSet;
+
+    virtual ~RegallocQuery() {};
+    
+    /// Return whether two live ranges interfere.
+    virtual bool interfere(const LiveInterval &a,
+                           const LiveInterval &b) const {
+      // A naive test
+      return(a.overlaps(b));
+    };
+
+    /// Return the set of intervals that interfere with this one.
+    virtual void getInterferences(IntervalSet &interferences,
+                                  const LiveInterval &a) const = 0;
+
+    /// This can often be cheaper than actually returning the
+    /// interferences.
+    virtual int getNumberOfInterferences(const LiveInterval &a) const = 0;
+
+    /// Make any data structure updates necessary to reflect
+    /// coalescing or other modifications.
+    virtual void updateDataForMerge(const LiveInterval &a,
+                                    const LiveInterval &b,
+                                    const MachineInstr &copy) {};
+
+    /// Allow the register allocator to communicate when it doesn't
+    /// want a copy coalesced.  This may be due to assumptions made by
+    /// the allocator about various invariants and so this question is
+    /// a matter of legality, not performance.  Performance decisions
+    /// about which copies to coalesce should be made by the
+    /// coalescer.
+    virtual bool isLegalToCoalesce(const MachineInstr &inst) const {
+      return(true);
+    }
+  };
+}
+
+// Because of the way .a files work, we must force the SimpleRC
+// implementation to be pulled in if the RegisterCoalescing header is
+// included.  Otherwise we run the risk of RegisterCoalescing being
+// used, but the default implementation not being linked into the tool
+// that uses it.
+FORCE_DEFINING_FILE_TO_BE_LINKED(RegisterCoalescer)
+FORCE_DEFINING_FILE_TO_BE_LINKED(SimpleRegisterCoalescing)
+
+#endif
index 2f363d585eac774acca364949b759a648dac497c..4e760815b9cce86d52edc7d922f2285daabf2b5f 100644 (file)
@@ -17,6 +17,7 @@
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/LiveInterval.h"
 #include "llvm/CodeGen/LiveIntervalAnalysis.h"
+#include "llvm/CodeGen/RegisterCoalescer.h"
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/IndexedMap.h"
 
@@ -27,7 +28,8 @@ namespace llvm {
   class TargetInstrInfo;
   class VirtRegMap;
 
-  class SimpleRegisterCoalescing : public MachineFunctionPass {
+  class SimpleRegisterCoalescing : public MachineFunctionPass,
+                                   public RegisterCoalescer {
     MachineFunction* mf_;
     const TargetMachine* tm_;
     const MRegisterInfo* mri_;
@@ -76,6 +78,11 @@ namespace llvm {
     /// runOnMachineFunction - pass entry point
     virtual bool runOnMachineFunction(MachineFunction&);
 
+    bool coalesceFunction(MachineFunction &mf, RegallocQuery &) {
+      // This runs as an independent pass, so don't do anything.
+      return(false);
+    };
+
     /// print - Implement the dump method.
     virtual void print(std::ostream &O, const Module* = 0) const;
     void print(std::ostream *O, const Module* M = 0) const {
index 6929b91645f9fee23e26522c932ab6fa07e5361b..2859c24743e96c381f3ad4fadeef5e8b8ad21171 100644 (file)
@@ -21,6 +21,7 @@
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/CodeGen/RegAllocRegistry.h"
+#include "llvm/CodeGen/RegisterCoalescer.h"
 #include "llvm/CodeGen/SSARegMap.h"
 #include "llvm/Target/MRegisterInfo.h"
 #include "llvm/Target/TargetMachine.h"
@@ -96,7 +97,9 @@ namespace {
 
     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
       AU.addRequired<LiveIntervals>();
-      AU.addRequiredID(SimpleRegisterCoalescingID);
+      // Make sure PassManager knows which analyses to make available
+      // to coalescing and which analyses coalescing invalidates.
+      AU.addRequiredTransitive<RegisterCoalescer>();
       MachineFunctionPass::getAnalysisUsage(AU);
     }
 
@@ -194,6 +197,11 @@ bool RALinScan::runOnMachineFunction(MachineFunction &fn) {
   mri_ = tm_->getRegisterInfo();
   li_ = &getAnalysis<LiveIntervals>();
 
+  // We don't run the coalescer here because we have no reason to
+  // interact with it.  If the coalescer requires interaction, it
+  // won't do anything.  If it doesn't require interaction, we assume
+  // it was run as a separate pass.
+
   // If this is the first function compiled, compute the related reg classes.
   if (RelatedRegClasses.empty())
     ComputeRelatedRegClasses();
diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp
new file mode 100644 (file)
index 0000000..cffc2e0
--- /dev/null
@@ -0,0 +1,43 @@
+//===- RegisterCoalescer.cpp - Generic Register Coalescing Interface -------==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the generic RegisterCoalescer interface which
+// is used as the common interface used by all clients and
+// implementations of register coalescing.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/RegisterCoalescer.h"
+#include "llvm/CodeGen/LiveIntervalAnalysis.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/Target/MRegisterInfo.h"
+#include "llvm/Pass.h"
+
+using namespace llvm;
+
+// Register the RegisterCoalescer interface, providing a nice name to refer to.
+namespace {
+  RegisterAnalysisGroup<RegisterCoalescer> Z("Register Coalescer");
+}
+char RegisterCoalescer::ID = 0;
+
+// RegisterCoalescer destructor: DO NOT move this to the header file
+// for RegisterCoalescer or else clients of the RegisterCoalescer
+// class may not depend on the RegisterCoalescer.o file in the current
+// .a file, causing alias analysis support to not be included in the
+// tool correctly!
+//
+RegisterCoalescer::~RegisterCoalescer() {}
+
+// Because of the way .a files work, we must force the SimpleRC
+// implementation to be pulled in if the RegisterCoalescer classes are
+// pulled in.  Otherwise we run the risk of RegisterCoalescer being
+// used, but the default implementation not being linked into the tool
+// that uses it.
+DEFINING_FILE_FOR(RegisterCoalescer)
index 4d5c0819ad07ce02e20401746446e980702edcff..779c36a21272b6b2bb9d9ae3c5005e9c5750d532 100644 (file)
@@ -23,6 +23,7 @@
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/CodeGen/SSARegMap.h"
+#include "llvm/CodeGen/RegisterCoalescer.h"
 #include "llvm/Target/MRegisterInfo.h"
 #include "llvm/Target/TargetInstrInfo.h"
 #include "llvm/Target/TargetMachine.h"
@@ -48,6 +49,9 @@ namespace {
 
   RegisterPass<SimpleRegisterCoalescing> 
   X("simple-register-coalescing", "Simple Register Coalescing");
+
+  // Declare that we implement the RegisterCoalescer interface
+  RegisterAnalysisGroup<RegisterCoalescer, true/*The Default*/> V(X);
 }
 
 const PassInfo *llvm::SimpleRegisterCoalescingID = X.getPassInfo();
@@ -1191,3 +1195,10 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
 void SimpleRegisterCoalescing::print(std::ostream &O, const Module* m) const {
    li_->print(O, m);
 }
+
+RegisterCoalescer* llvm::createSimpleRegisterCoalescer() {
+  return new SimpleRegisterCoalescing();
+}
+
+// Make sure that anything that uses RegisterCoalescer pulls in this file...
+DEFINING_FILE_FOR(SimpleRegisterCoalescing)