#ifndef LLVM_CODEGEN_REGALLOCPBQP_H
#define LLVM_CODEGEN_REGALLOCPBQP_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/PBQP/RegAllocSolver.h"
#include <map>
#include <set>
namespace llvm {
class LiveIntervals;
class MachineBlockFrequencyInfo;
class MachineFunction;
class TargetRegisterInfo;
typedef PBQP::RegAlloc::Graph PBQPRAGraph;
class PBQPRAProblem {
public:
typedef SmallVector<unsigned, 16> AllowedSet;
PBQPRAGraph& getGraph() { return graph; }
const PBQPRAGraph& getGraph() const { return graph; }
template <typename AllowedRegsItr>
void recordVReg(unsigned vreg, PBQPRAGraph::NodeId nodeId,
AllowedRegsItr arBegin, AllowedRegsItr arEnd) {
assert(node2VReg.find(nodeId) == node2VReg.end() && "Re-mapping node.");
assert(vreg2Node.find(vreg) == vreg2Node.end() && "Re-mapping vreg.");
assert(allowedSets[vreg].empty() && "vreg already has pregs.");
node2VReg[nodeId] = vreg;
vreg2Node[vreg] = nodeId;
std::copy(arBegin, arEnd, std::back_inserter(allowedSets[vreg]));
}
unsigned getVRegForNode(PBQPRAGraph::NodeId nodeId) const;
PBQPRAGraph::NodeId getNodeForVReg(unsigned vreg) const;
bool isPRegOption(unsigned vreg, unsigned option) const {
return !isSpillOption(vreg, option);
}
bool isSpillOption(unsigned vreg, unsigned option) const {
return option == 0;
}
const AllowedSet& getAllowedSet(unsigned vreg) const;
unsigned getPRegForOption(unsigned vreg, unsigned option) const;
private:
typedef std::map<PBQPRAGraph::NodeId, unsigned> Node2VReg;
typedef DenseMap<unsigned, PBQPRAGraph::NodeId> VReg2Node;
typedef DenseMap<unsigned, AllowedSet> AllowedSetMap;
PBQPRAGraph graph;
Node2VReg node2VReg;
VReg2Node vreg2Node;
AllowedSetMap allowedSets;
};
class PBQPBuilder {
private:
PBQPBuilder(const PBQPBuilder&) LLVM_DELETED_FUNCTION;
void operator=(const PBQPBuilder&) LLVM_DELETED_FUNCTION;
public:
typedef std::set<unsigned> RegSet;
PBQPBuilder() {}
virtual ~PBQPBuilder() {}
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);
};
class PBQPBuilderWithCoalescing : public PBQPBuilder {
public:
PBQPRAProblem *build(MachineFunction *mf, const LiveIntervals *lis,
const MachineBlockFrequencyInfo *mbfi,
const RegSet &vregs) override;
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(std::unique_ptr<PBQPBuilder> builder,
char *customPassID = nullptr);
}
#endif