mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-29 10:32:47 +00:00
4eed756153
The main advantages here are way better heuristics, taking into account not just loop depth but also __builtin_expect and other static heuristics and will eventually learn how to use profile info. Most of the work in this patch is pushing the MachineBlockFrequencyInfo analysis into the right places. This is good for a 5% speedup on zlib's deflate (x86_64), there were some very unfortunate spilling decisions in its hottest loop in longest_match(). Other benchmarks I tried were mostly neutral. This changes register allocation in subtle ways, update the tests for it. 2012-02-20-MachineCPBug.ll was deleted as it's very fragile and the instruction it looked for was gone already (but the FileCheck pattern picked up unrelated stuff). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184105 91177308-0d34-0410-b5e6-96231b3b80d8
166 lines
5.9 KiB
C++
166 lines
5.9 KiB
C++
//===-- RegAllocPBQP.h ------------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the PBQPBuilder interface, for classes which build PBQP
|
|
// instances to represent register allocation problems, and the RegAllocPBQP
|
|
// interface.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CODEGEN_REGALLOCPBQP_H
|
|
#define LLVM_CODEGEN_REGALLOCPBQP_H
|
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
|
#include "llvm/CodeGen/PBQP/Graph.h"
|
|
#include "llvm/CodeGen/PBQP/Solution.h"
|
|
#include <map>
|
|
#include <set>
|
|
|
|
namespace llvm {
|
|
|
|
class LiveIntervals;
|
|
class MachineBlockFrequencyInfo;
|
|
class MachineFunction;
|
|
class TargetRegisterInfo;
|
|
template<class T> class OwningPtr;
|
|
|
|
/// This class wraps up a PBQP instance representing a register allocation
|
|
/// problem, plus the structures necessary to map back from the PBQP solution
|
|
/// to a register allocation solution. (i.e. The PBQP-node <--> vreg map,
|
|
/// and the PBQP option <--> storage location map).
|
|
|
|
class PBQPRAProblem {
|
|
public:
|
|
|
|
typedef SmallVector<unsigned, 16> AllowedSet;
|
|
|
|
PBQP::Graph& getGraph() { return graph; }
|
|
|
|
const PBQP::Graph& getGraph() const { return graph; }
|
|
|
|
/// Record the mapping between the given virtual register and PBQP node,
|
|
/// and the set of allowed pregs for the vreg.
|
|
///
|
|
/// If you are extending
|
|
/// PBQPBuilder you are unlikely to need this: Nodes and options for all
|
|
/// vregs will already have been set up for you by the base class.
|
|
template <typename AllowedRegsItr>
|
|
void recordVReg(unsigned vreg, PBQP::Graph::NodeItr node,
|
|
AllowedRegsItr arBegin, AllowedRegsItr arEnd) {
|
|
assert(node2VReg.find(node) == node2VReg.end() && "Re-mapping node.");
|
|
assert(vreg2Node.find(vreg) == vreg2Node.end() && "Re-mapping vreg.");
|
|
assert(allowedSets[vreg].empty() && "vreg already has pregs.");
|
|
|
|
node2VReg[node] = vreg;
|
|
vreg2Node[vreg] = node;
|
|
std::copy(arBegin, arEnd, std::back_inserter(allowedSets[vreg]));
|
|
}
|
|
|
|
/// Get the virtual register corresponding to the given PBQP node.
|
|
unsigned getVRegForNode(PBQP::Graph::ConstNodeItr node) const;
|
|
|
|
/// Get the PBQP node corresponding to the given virtual register.
|
|
PBQP::Graph::NodeItr getNodeForVReg(unsigned vreg) const;
|
|
|
|
/// Returns true if the given PBQP option represents a physical register,
|
|
/// false otherwise.
|
|
bool isPRegOption(unsigned vreg, unsigned option) const {
|
|
// At present we only have spills or pregs, so anything that's not a
|
|
// spill is a preg. (This might be extended one day to support remat).
|
|
return !isSpillOption(vreg, option);
|
|
}
|
|
|
|
/// Returns true if the given PBQP option represents spilling, false
|
|
/// otherwise.
|
|
bool isSpillOption(unsigned vreg, unsigned option) const {
|
|
// We hardcode option zero as the spill option.
|
|
return option == 0;
|
|
}
|
|
|
|
/// Returns the allowed set for the given virtual register.
|
|
const AllowedSet& getAllowedSet(unsigned vreg) const;
|
|
|
|
/// Get PReg for option.
|
|
unsigned getPRegForOption(unsigned vreg, unsigned option) const;
|
|
|
|
private:
|
|
|
|
typedef std::map<PBQP::Graph::ConstNodeItr, unsigned,
|
|
PBQP::NodeItrComparator> Node2VReg;
|
|
typedef DenseMap<unsigned, PBQP::Graph::NodeItr> VReg2Node;
|
|
typedef DenseMap<unsigned, AllowedSet> AllowedSetMap;
|
|
|
|
PBQP::Graph graph;
|
|
Node2VReg node2VReg;
|
|
VReg2Node vreg2Node;
|
|
|
|
AllowedSetMap allowedSets;
|
|
|
|
};
|
|
|
|
/// Builds PBQP instances to represent register allocation problems. Includes
|
|
/// spill, interference and coalescing costs by default. You can extend this
|
|
/// class to support additional constraints for your architecture.
|
|
class PBQPBuilder {
|
|
private:
|
|
PBQPBuilder(const PBQPBuilder&) LLVM_DELETED_FUNCTION;
|
|
void operator=(const PBQPBuilder&) LLVM_DELETED_FUNCTION;
|
|
public:
|
|
|
|
typedef std::set<unsigned> RegSet;
|
|
|
|
/// Default constructor.
|
|
PBQPBuilder() {}
|
|
|
|
/// Clean up a PBQPBuilder.
|
|
virtual ~PBQPBuilder() {}
|
|
|
|
/// Build a PBQP instance to represent the register allocation problem for
|
|
/// the given MachineFunction.
|
|
virtual PBQPRAProblem *build(MachineFunction *mf, const LiveIntervals *lis,
|
|
const MachineBlockFrequencyInfo *mbfi,
|
|
const RegSet &vregs);
|
|
private:
|
|
|
|
void addSpillCosts(PBQP::Vector &costVec, PBQP::PBQPNum spillCost);
|
|
|
|
void addInterferenceCosts(PBQP::Matrix &costMat,
|
|
const PBQPRAProblem::AllowedSet &vr1Allowed,
|
|
const PBQPRAProblem::AllowedSet &vr2Allowed,
|
|
const TargetRegisterInfo *tri);
|
|
};
|
|
|
|
/// Extended builder which adds coalescing constraints to a problem.
|
|
class PBQPBuilderWithCoalescing : public PBQPBuilder {
|
|
public:
|
|
|
|
/// Build a PBQP instance to represent the register allocation problem for
|
|
/// the given MachineFunction.
|
|
virtual PBQPRAProblem *build(MachineFunction *mf, const LiveIntervals *lis,
|
|
const MachineBlockFrequencyInfo *mbfi,
|
|
const RegSet &vregs);
|
|
|
|
private:
|
|
|
|
void addPhysRegCoalesce(PBQP::Vector &costVec, unsigned pregOption,
|
|
PBQP::PBQPNum benefit);
|
|
|
|
void addVirtRegCoalesce(PBQP::Matrix &costMat,
|
|
const PBQPRAProblem::AllowedSet &vr1Allowed,
|
|
const PBQPRAProblem::AllowedSet &vr2Allowed,
|
|
PBQP::PBQPNum benefit);
|
|
};
|
|
|
|
FunctionPass* createPBQPRegisterAllocator(OwningPtr<PBQPBuilder> &builder,
|
|
char *customPassID=0);
|
|
}
|
|
|
|
#endif /* LLVM_CODEGEN_REGALLOCPBQP_H */
|