mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 12:12:47 +01:00
Add a RegisterClassInfo class that lazily caches information about
register classes. It provides information for each register class that cannot be determined statically, like: - The number of allocatable registers in a class after filtering out the reserved and invalid registers. - The preferred allocation order with registers that overlap callee-saved registers last. - The last callee-saved register that overlaps a given physical register. This information usually doesn't change between functions, so it is reused for compiling multiple functions when possible. The many possible combinations of reserved and callee saves registers makes it unfeasible to compute this information statically in TableGen. Use RegisterClassInfo to count available registers in various heuristics in SimpleRegisterCoalescing, making the pass run 4% faster. llvm-svn: 132450
This commit is contained in:
parent
1f91013bcb
commit
24726cedf4
@ -67,6 +67,7 @@ add_llvm_library(LLVMCodeGen
|
||||
RegAllocGreedy.cpp
|
||||
RegAllocLinearScan.cpp
|
||||
RegAllocPBQP.cpp
|
||||
RegisterClassInfo.cpp
|
||||
RegisterCoalescer.cpp
|
||||
RegisterScavenging.cpp
|
||||
RenderMachineFunction.cpp
|
||||
|
105
lib/CodeGen/RegisterClassInfo.cpp
Normal file
105
lib/CodeGen/RegisterClassInfo.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
//===-- RegisterClassInfo.cpp - Dynamic Register Class Info ---------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the RegisterClassInfo class which provides dynamic
|
||||
// information about target register classes. Callee saved and reserved
|
||||
// registers depends on calling conventions and other dynamic information, so
|
||||
// some things cannot be determined statically.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "RegisterClassInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
RegisterClassInfo::RegisterClassInfo() : Tag(0), TRI(0) {}
|
||||
|
||||
void RegisterClassInfo::runOnMachineFunction(const MachineFunction &mf) {
|
||||
bool Update = false;
|
||||
MF = &mf;
|
||||
|
||||
// Allocate new array the first time we see a new target.
|
||||
if (MF->getTarget().getRegisterInfo() != TRI) {
|
||||
TRI = MF->getTarget().getRegisterInfo();
|
||||
RegClass.reset(new RCInfo[TRI->getNumRegClasses()]);
|
||||
Update = true;
|
||||
}
|
||||
|
||||
// Does this MF have different CSRs?
|
||||
const unsigned *CSR = TRI->getCalleeSavedRegs(MF);
|
||||
if (CSR != CalleeSaved) {
|
||||
// Build a CSRNum map. Every CSR alias gets an entry pointing to the last
|
||||
// overlapping CSR.
|
||||
CSRNum.reset(new uint8_t[TRI->getNumRegs()]);
|
||||
for (unsigned N = 0; unsigned Reg = CSR[N]; ++N)
|
||||
for (const unsigned *AS = TRI->getOverlaps(Reg);
|
||||
unsigned Alias = *AS; ++AS)
|
||||
CSRNum[Alias] = N + 1; // 0 means no CSR, 1 means CalleeSaved[0], ...
|
||||
Update = true;
|
||||
}
|
||||
CalleeSaved = CSR;
|
||||
|
||||
// Different reserved registers?
|
||||
BitVector RR = TRI->getReservedRegs(*MF);
|
||||
if (RR != Reserved)
|
||||
Update = true;
|
||||
Reserved = RR;
|
||||
|
||||
// Invalidate cached information from previous function.
|
||||
if (Update)
|
||||
++Tag;
|
||||
}
|
||||
|
||||
/// compute - Compute the preferred allocation order for RC with reserved
|
||||
/// registers filtered out. Volatile registers come first followed by CSR
|
||||
/// aliases ordered according to the CSR order specified by the target.
|
||||
void RegisterClassInfo::compute(const TargetRegisterClass *RC) const {
|
||||
RCInfo &RCI = RegClass[RC->getID()];
|
||||
|
||||
// Raw register count, including all reserved regs.
|
||||
unsigned NumRegs = RC->getNumRegs();
|
||||
|
||||
if (!RCI.Order)
|
||||
RCI.Order.reset(new unsigned[NumRegs]);
|
||||
|
||||
unsigned N = 0;
|
||||
SmallVector<std::pair<unsigned, unsigned>, 8> CSRAlias;
|
||||
|
||||
// FIXME: Once targets reserve registers instead of removing them from the
|
||||
// allocation order, we can simply use begin/end here.
|
||||
TargetRegisterClass::iterator AOB = RC->allocation_order_begin(*MF);
|
||||
TargetRegisterClass::iterator AOE = RC->allocation_order_end(*MF);
|
||||
|
||||
for (TargetRegisterClass::iterator I = AOB; I != AOE; ++I) {
|
||||
unsigned PhysReg = *I;
|
||||
// Remove reserved registers from the allocation order.
|
||||
if (Reserved.test(PhysReg))
|
||||
continue;
|
||||
if (unsigned CSR = CSRNum[PhysReg])
|
||||
// PhysReg aliases a CSR, save it for later.
|
||||
CSRAlias.push_back(std::make_pair(CSR, PhysReg));
|
||||
else
|
||||
RCI.Order[N++] = PhysReg;
|
||||
}
|
||||
RCI.NumRegs = N + CSRAlias.size();
|
||||
assert (RCI.NumRegs <= NumRegs && "Allocation order larger than regclass");
|
||||
|
||||
// Sort CSR aliases acording to the CSR ordering.
|
||||
if (CSRAlias.size() >= 2)
|
||||
array_pod_sort(CSRAlias.begin(), CSRAlias.end());
|
||||
|
||||
for (unsigned i = 0, e = CSRAlias.size(); i != e; ++i)
|
||||
RCI.Order[N++] = CSRAlias[i].second;
|
||||
|
||||
// RCI is now up-to-date.
|
||||
RCI.Tag = Tag;
|
||||
}
|
||||
|
102
lib/CodeGen/RegisterClassInfo.h
Normal file
102
lib/CodeGen/RegisterClassInfo.h
Normal file
@ -0,0 +1,102 @@
|
||||
//===-- RegisterClassInfo.h - Dynamic Register Class Info -*- C++ -*-------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the RegisterClassInfo class which provides dynamic
|
||||
// information about target register classes. Callee saved and reserved
|
||||
// registers depends on calling conventions and other dynamic information, so
|
||||
// some things cannot be determined statically.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CODEGEN_REGISTERCLASSINFO_H
|
||||
#define LLVM_CODEGEN_REGISTERCLASSINFO_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class RegisterClassInfo {
|
||||
struct RCInfo {
|
||||
unsigned Tag;
|
||||
unsigned NumRegs;
|
||||
OwningArrayPtr<unsigned> Order;
|
||||
|
||||
RCInfo() : Tag(0), NumRegs(0) {}
|
||||
operator ArrayRef<unsigned>() const {
|
||||
return ArrayRef<unsigned>(Order.get(), NumRegs);
|
||||
}
|
||||
};
|
||||
|
||||
// Brief cached information for each register class.
|
||||
OwningArrayPtr<RCInfo> RegClass;
|
||||
|
||||
// Tag changes whenever cached information needs to be recomputed. An RCInfo
|
||||
// entry is valid when its tag matches.
|
||||
unsigned Tag;
|
||||
|
||||
const MachineFunction *MF;
|
||||
const TargetRegisterInfo *TRI;
|
||||
|
||||
// Callee saved registers of last MF. Assumed to be valid until the next
|
||||
// runOnFunction() call.
|
||||
const unsigned *CalleeSaved;
|
||||
|
||||
// Map register number to CalleeSaved index + 1;
|
||||
OwningArrayPtr<uint8_t> CSRNum;
|
||||
|
||||
// Reserved registers in the current MF.
|
||||
BitVector Reserved;
|
||||
|
||||
// Compute all information about RC.
|
||||
void compute(const TargetRegisterClass *RC) const;
|
||||
|
||||
// Return an up-to-date RCInfo for RC.
|
||||
const RCInfo &get(const TargetRegisterClass *RC) const {
|
||||
const RCInfo &RCI = RegClass[RC->getID()];
|
||||
if (Tag != RCI.Tag)
|
||||
compute(RC);
|
||||
return RCI;
|
||||
}
|
||||
|
||||
public:
|
||||
RegisterClassInfo();
|
||||
|
||||
/// runOnFunction - Prepare to answer questions about MF. This must be called
|
||||
/// before any other methods are used.
|
||||
void runOnMachineFunction(const MachineFunction &MF);
|
||||
|
||||
/// getNumAllocatableRegs - Returns the number of actually allocatable
|
||||
/// registers in RC in the current function.
|
||||
unsigned getNumAllocatableRegs(const TargetRegisterClass *RC) const {
|
||||
return get(RC).NumRegs;
|
||||
}
|
||||
|
||||
/// getOrder - Returns the preferred allocation order for RC. The order
|
||||
/// contains no reserved registers, and registers that alias callee saved
|
||||
/// registers come last.
|
||||
ArrayRef<unsigned> getOrder(const TargetRegisterClass *RC) const {
|
||||
return get(RC);
|
||||
}
|
||||
|
||||
/// getLastCalleeSavedAlias - Returns the last callee saved register that
|
||||
/// overlaps PhysReg, or 0 if Reg doesn't overlap a CSR.
|
||||
unsigned getLastCalleeSavedAlias(unsigned PhysReg) const {
|
||||
assert(TargetRegisterInfo::isPhysicalRegister(PhysReg));
|
||||
if (unsigned N = CSRNum[PhysReg])
|
||||
return CalleeSaved[N-1];
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
@ -772,7 +772,7 @@ bool SimpleRegisterCoalescing::shouldJoinPhys(CoalescerPair &CP) {
|
||||
// CodeGen/X86/phys_subreg_coalesce-3.ll needs it.
|
||||
if (!CP.isPartial()) {
|
||||
const TargetRegisterClass *RC = mri_->getRegClass(CP.getSrcReg());
|
||||
unsigned Threshold = allocatableRCRegs_[RC].count() * 2;
|
||||
unsigned Threshold = RegClassInfo.getNumAllocatableRegs(RC) * 2;
|
||||
unsigned Length = li_->getApproximateInstructionCount(JoinVInt);
|
||||
if (Length > Threshold) {
|
||||
++numAborts;
|
||||
@ -791,7 +791,7 @@ SimpleRegisterCoalescing::isWinToJoinCrossClass(unsigned SrcReg,
|
||||
const TargetRegisterClass *SrcRC,
|
||||
const TargetRegisterClass *DstRC,
|
||||
const TargetRegisterClass *NewRC) {
|
||||
unsigned NewRCCount = allocatableRCRegs_[NewRC].count();
|
||||
unsigned NewRCCount = RegClassInfo.getNumAllocatableRegs(NewRC);
|
||||
// This heuristics is good enough in practice, but it's obviously not *right*.
|
||||
// 4 is a magic number that works well enough for x86, ARM, etc. It filter
|
||||
// out all but the most restrictive register classes.
|
||||
@ -821,12 +821,12 @@ SimpleRegisterCoalescing::isWinToJoinCrossClass(unsigned SrcReg,
|
||||
unsigned NewUses = SrcUses + DstUses;
|
||||
unsigned NewSize = SrcSize + DstSize;
|
||||
if (SrcRC != NewRC && SrcSize > ThresSize) {
|
||||
unsigned SrcRCCount = allocatableRCRegs_[SrcRC].count();
|
||||
unsigned SrcRCCount = RegClassInfo.getNumAllocatableRegs(SrcRC);
|
||||
if (NewUses*SrcSize*SrcRCCount > 2*SrcUses*NewSize*NewRCCount)
|
||||
return false;
|
||||
}
|
||||
if (DstRC != NewRC && DstSize > ThresSize) {
|
||||
unsigned DstRCCount = allocatableRCRegs_[DstRC].count();
|
||||
unsigned DstRCCount = RegClassInfo.getNumAllocatableRegs(DstRC);
|
||||
if (NewUses*DstSize*DstRCCount > 2*DstUses*NewSize*NewRCCount)
|
||||
return false;
|
||||
}
|
||||
@ -1400,10 +1400,7 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
|
||||
if (VerifyCoalescing)
|
||||
mf_->verify(this, "Before register coalescing");
|
||||
|
||||
for (TargetRegisterInfo::regclass_iterator I = tri_->regclass_begin(),
|
||||
E = tri_->regclass_end(); I != E; ++I)
|
||||
allocatableRCRegs_.insert(std::make_pair(*I,
|
||||
tri_->getAllocatableSet(fn, *I)));
|
||||
RegClassInfo.runOnMachineFunction(fn);
|
||||
|
||||
// Join (coalesce) intervals if requested.
|
||||
if (EnableJoining) {
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
|
||||
#include "llvm/CodeGen/RegisterCoalescer.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "RegisterClassInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
class SimpleRegisterCoalescing;
|
||||
@ -47,8 +47,7 @@ namespace llvm {
|
||||
LiveDebugVariables *ldv_;
|
||||
const MachineLoopInfo* loopInfo;
|
||||
AliasAnalysis *AA;
|
||||
|
||||
DenseMap<const TargetRegisterClass*, BitVector> allocatableRCRegs_;
|
||||
RegisterClassInfo RegClassInfo;
|
||||
|
||||
/// JoinedCopies - Keep track of copies eliminated due to coalescing.
|
||||
///
|
||||
|
Loading…
Reference in New Issue
Block a user