On Wednesday 11 July 2007 15:07, Christopher Lamb wrote:
> Could it be possible for there to be a harness type interface that
> would allow coalescers that support both modes to be hooked into the
> pass registration, and those that depend on the allocator not be
> registered as passes?
I have a patch for this kind of thing attached. Please take a look and let
me know if it looks reasonable. It's not complete yet. I'm about to
embark
on implementing a new coalescer that will not be managed by PassManager
and as I do that I'll figure out any additional interfaces that are needed.
If this looks good, I'll commit it and later on I'll commit any
additions I
make to this basic interface.
-Dave
-------------- next part --------------
Index: llvm/include/llvm/CodeGen/RegisterAllocator.h
==================================================================---
llvm/include/llvm/CodeGen/RegisterAllocator.h (revision 0)
+++ llvm/include/llvm/CodeGen/RegisterAllocator.h (revision 0)
@@ -0,0 +1,41 @@
+//===-- RegisterAllocator.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 allocators,
+// allowing them to provide information to coalescers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_REGISTER_ALLOCATOR_H
+#define LLVM_CODEGEN_REGISTER_ALLOCATOR_H
+
+#include <llvm/CodeGen/LiveInterval.h>
+
+namespace llvm
+{
+ class MachineInstruction;
+
+ class RegisterAllocator {
+ public:
+ /// Return whether this copy should be considered for coalescing.
+ virtual bool coalesceThisCopy(const MachineInstruction &) {
+ // Be aggressive, but possibly bad
+ return(true);
+ };
+
+ /// Return whether two live ranges interfere.
+ virtual bool interfere(const LiveInterval &a,
+ const LiveInterval &b) {
+ // A naive test
+ return(a.overlaps(b));
+ };
+ };
+}
+
+#endif
Property changes on: llvm/include/llvm/CodeGen/RegisterAllocator.h
___________________________________________________________________
Name: svn:eol-style
+ LF
Index: llvm/include/llvm/CodeGen/RegisterCoalescer.h
==================================================================---
llvm/include/llvm/CodeGen/RegisterCoalescer.h (revision 0)
+++ llvm/include/llvm/CodeGen/RegisterCoalescer.h (revision 0)
@@ -0,0 +1,58 @@
+//===-- 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"
+
+#ifndef LLVM_CODEGEN_REGISTER_COALESCER_H
+#define LLVM_CODEGEN_REGISTER_COALESCER_H
+
+namespace llvm
+{
+ class MachineFunction;
+ class RegisterAllocator;
+ class AnalysisUsage;
+
+ 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 the register
+ /// allocator for queries.
+ virtual void invoke(MachineFunction &mf, RegisterAllocator &ra) =
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.
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {};
+ };
+}
+
+// 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
Property changes on: llvm/include/llvm/CodeGen/RegisterCoalescer.h
___________________________________________________________________
Name: svn:eol-style
+ LF
Index: llvm/include/llvm/CodeGen/SimpleRegisterCoalescing.h
==================================================================---
llvm/include/llvm/CodeGen/SimpleRegisterCoalescing.h (revision 58818)
+++ llvm/include/llvm/CodeGen/SimpleRegisterCoalescing.h (working copy)
@@ -17,17 +17,22 @@
#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"
+#include <map>
+
namespace llvm {
class LiveVariables;
class MRegisterInfo;
class TargetInstrInfo;
class VirtRegMap;
-
- class SimpleRegisterCoalescing : public MachineFunctionPass {
+ class RegisterAllocator;
+
+ class SimpleRegisterCoalescing : public MachineFunctionPass,
+ public RegisterCoalescer {
MachineFunction* mf_;
const TargetMachine* tm_;
const MRegisterInfo* mri_;
@@ -45,10 +50,35 @@
/// with other intervals.
BitVector JoinedLIs;
+ /// didWork - Tell whether we have run on this function already.
+ /// This allows the coalescer to either run independently or from
+ /// within a register allocator.
+ typedef std::map<const MachineFunction *, bool> WorkMap;
+ WorkMap didWork;
+ void doWork(MachineFunction &mf);
+
public:
static char ID; // Pass identifcation, replacement for typeid
SimpleRegisterCoalescing() : MachineFunctionPass((intptr_t)&ID) {};
+ const char *getPassName() const{
+ return "Simple Register Coalescing";
+ };
+
+ /// Allow a register allocator to re-run this on a function
+ void reset(const MachineFunction &mf) {
+ didWork[&mf] = false;
+ };
+
+ // TODO: Because PassManager didn't invoke this, how does it know
+ // if analyses were invalidated? This works for this
+ // implementation because it derives from PassManager and will be
+ // run before register allocation if the allocator specifies
+ // addRequiredTransitive of it.
+ void invoke(MachineFunction &mf, RegisterAllocator &) {
+ doWork(mf);
+ };
+
struct CopyRec {
MachineInstr *MI;
unsigned SrcReg, DstReg;
@@ -74,7 +104,9 @@
virtual void releaseMemory();
/// runOnMachineFunction - pass entry point
- virtual bool runOnMachineFunction(MachineFunction&);
+ virtual bool runOnMachineFunction(MachineFunction&mf) {
+ doWork(mf);
+ }
/// print - Implement the dump method.
virtual void print(std::ostream &O, const Module* = 0) const;
Index: llvm/lib/CodeGen/RegAllocBigBlock.cpp
==================================================================---
llvm/lib/CodeGen/RegAllocBigBlock.cpp (revision 58818)
+++ llvm/lib/CodeGen/RegAllocBigBlock.cpp (working copy)
@@ -36,6 +36,7 @@
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
+#include "llvm/CodeGen/RegisterAllocator.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/CommandLine.h"
@@ -79,7 +80,8 @@
/// - break ties when picking regs? (probably not worth it in a
/// JIT context)
///
- class VISIBILITY_HIDDEN RABigBlock : public MachineFunctionPass {
+ class VISIBILITY_HIDDEN RABigBlock : public MachineFunctionPass,
+ public RegisterAllocator {
public:
static char ID;
RABigBlock() : MachineFunctionPass((intptr_t)&ID) {}
Index: llvm/lib/CodeGen/RegAllocLinearScan.cpp
==================================================================---
llvm/lib/CodeGen/RegAllocLinearScan.cpp (revision 58818)
+++ llvm/lib/CodeGen/RegAllocLinearScan.cpp (working copy)
@@ -21,6 +21,8 @@
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
+#include "llvm/CodeGen/RegisterAllocator.h"
+#include "llvm/CodeGen/RegisterCoalescer.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetMachine.h"
@@ -47,7 +49,8 @@
static unsigned numIterations = 0;
static unsigned numIntervals = 0;
- struct VISIBILITY_HIDDEN RALinScan : public MachineFunctionPass {
+ struct VISIBILITY_HIDDEN RALinScan : public MachineFunctionPass,
+ public RegisterAllocator {
static char ID;
RALinScan() : MachineFunctionPass((intptr_t)&ID) {}
@@ -96,7 +99,10 @@
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<LiveIntervals>();
- AU.addRequiredID(SimpleRegisterCoalescingID);
+ AU.addRequiredTransitive<RegisterCoalescer>();
+ // Make sure PassManager knows which analyses to make available
+ // to coalescing and which analyses coalescing invalidates.
+ getAnalysis<RegisterCoalescer>().getAnalysisUsage(AU);
MachineFunctionPass::getAnalysisUsage(AU);
}
@@ -194,6 +200,10 @@
mri_ = tm_->getRegisterInfo();
li_ = &getAnalysis<LiveIntervals>();
+ RegisterCoalescer &coalescer = getAnalysis<RegisterCoalescer>();
+
+ coalescer.invoke(fn, *this);
+
// If this is the first function compiled, compute the related reg classes.
if (RelatedRegClasses.empty())
ComputeRelatedRegClasses();
Index: llvm/lib/CodeGen/RegAllocLocal.cpp
==================================================================---
llvm/lib/CodeGen/RegAllocLocal.cpp (revision 58818)
+++ llvm/lib/CodeGen/RegAllocLocal.cpp (working copy)
@@ -21,6 +21,7 @@
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
+#include "llvm/CodeGen/RegisterAllocator.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/CommandLine.h"
@@ -42,7 +43,8 @@
createLocalRegisterAllocator);
- class VISIBILITY_HIDDEN RALocal : public MachineFunctionPass {
+ class VISIBILITY_HIDDEN RALocal : public MachineFunctionPass,
+ public RegisterAllocator {
public:
static char ID;
RALocal() : MachineFunctionPass((intptr_t)&ID) {}
@@ -129,7 +131,7 @@
}
}
- public:
+ public:
virtual const char *getPassName() const {
return "Local Register Allocator";
}
Index: llvm/lib/CodeGen/RegAllocSimple.cpp
==================================================================---
llvm/lib/CodeGen/RegAllocSimple.cpp (revision 58818)
+++ llvm/lib/CodeGen/RegAllocSimple.cpp (working copy)
@@ -21,6 +21,7 @@
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
+#include "llvm/CodeGen/RegisterAllocator.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Debug.h"
@@ -37,7 +38,8 @@
simpleRegAlloc("simple", " simple register allocator",
createSimpleRegisterAllocator);
- class VISIBILITY_HIDDEN RegAllocSimple : public MachineFunctionPass {
+ class VISIBILITY_HIDDEN RegAllocSimple : public MachineFunctionPass,
+ public RegisterAllocator {
public:
static char ID;
RegAllocSimple() : MachineFunctionPass((intptr_t)&ID) {}
Index: llvm/lib/CodeGen/RegisterCoalescer.cpp
==================================================================---
llvm/lib/CodeGen/RegisterCoalescer.cpp (revision 0)
+++ llvm/lib/CodeGen/RegisterCoalescer.cpp (revision 0)
@@ -0,0 +1,40 @@
+//===- 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/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)
Property changes on: llvm/lib/CodeGen/RegisterCoalescer.cpp
___________________________________________________________________
Name: svn:eol-style
+ LF
Index: llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp
==================================================================---
llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp (revision 58818)
+++ llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp (working copy)
@@ -46,13 +46,15 @@
cl::desc("Coallesce copies (default=true)"),
cl::init(true));
+ // Need to register with PassManager so getAnalysis works
RegisterPass<SimpleRegisterCoalescing>
X("simple-register-coalescing",
- "Simple register coalescing to eliminate all possible register
copies");
+ "Simple register coalescing to eliminate all possible register copies
(default RC impl)");
+
+ // Declare that we implement the RegisterCoalescer interface
+ RegisterAnalysisGroup<RegisterCoalescer, true/*The Default*/> V(X);
}
-const PassInfo *llvm::SimpleRegisterCoalescingID = X.getPassInfo();
-
void SimpleRegisterCoalescing::getAnalysisUsage(AnalysisUsage &AU) const {
//AU.addPreserved<LiveVariables>();
AU.addPreserved<LiveIntervals>();
@@ -1020,7 +1022,16 @@
return true;
}
-bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
+void SimpleRegisterCoalescing::doWork(MachineFunction &fn) {
+ std::pair<WorkMap::iterator, bool> w +
didWork.insert(std::make_pair(&fn, false));
+
+ assert(w.first != didWork.end() && "Insert failed");
+
+ if (w.first->second) {
+ return;
+ }
+
mf_ = &fn;
tm_ = &fn.getTarget();
mri_ = tm_->getRegisterInfo();
@@ -1133,10 +1144,13 @@
}
DEBUG(dump());
- return true;
+ w.first->second = true;
}
/// print - Implement the dump method.
void SimpleRegisterCoalescing::print(std::ostream &O, const Module* m)
const {
li_->print(O, m);
}
+
+// Make sure that anything that uses RegisterCoalescer pulls in this file...
+DEFINING_FILE_FOR(SimpleRegisterCoalescing)