mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 11:42:57 +01:00
Re-commit: [globalisel] Tablegen-erate current Register Bank Information
Summary: Adds a RegisterBank tablegen class that can be used to declare the register banks and an associated tablegen pass to generate the necessary code. Changes since first commit attempt: * Added missing guards * Added more missing guards * Found and fixed a use-after-free bug involving Twine locals Reviewers: t.p.northover, ab, rovka, qcolombet Reviewed By: qcolombet Subscribers: aditya_nandakumar, rengolin, kristof.beyls, vkalintiris, mgorny, dberris, llvm-commits, rovka Differential Revision: https://reviews.llvm.org/D27338 llvm-svn: 292478
This commit is contained in:
parent
dcc513e780
commit
39b5a7c2bb
@ -42,7 +42,7 @@ private:
|
||||
|
||||
public:
|
||||
RegisterBank(unsigned ID, const char *Name, unsigned Size,
|
||||
const uint32_t *ContainedRegClasses);
|
||||
const uint32_t *ContainedRegClasses, unsigned NumRegClasses);
|
||||
|
||||
/// Get the identifier of this register bank.
|
||||
unsigned getID() const { return ID; }
|
||||
|
16
include/llvm/Target/GlobalISel/RegisterBank.td
Normal file
16
include/llvm/Target/GlobalISel/RegisterBank.td
Normal file
@ -0,0 +1,16 @@
|
||||
//===- RegisterBank.td - Register bank definitions ---------*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class RegisterBank<string name, list<RegisterClass> classes> {
|
||||
string Name = name;
|
||||
list<RegisterClass> RegisterClasses = classes;
|
||||
}
|
@ -1344,4 +1344,5 @@ include "llvm/Target/TargetSelectionDAG.td"
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Pull in the common support for Global ISel generation.
|
||||
//
|
||||
include "llvm/Target/GlobalISel/RegisterBank.td"
|
||||
include "llvm/Target/TargetGlobalISel.td"
|
||||
|
@ -19,10 +19,11 @@ using namespace llvm;
|
||||
|
||||
const unsigned RegisterBank::InvalidID = UINT_MAX;
|
||||
|
||||
RegisterBank::RegisterBank(unsigned ID, const char *Name, unsigned Size,
|
||||
const uint32_t *CoveredClasses)
|
||||
RegisterBank::RegisterBank(
|
||||
unsigned ID, const char *Name, unsigned Size,
|
||||
const uint32_t *CoveredClasses, unsigned NumRegClasses)
|
||||
: ID(ID), Name(Name), Size(Size) {
|
||||
ContainedRegClasses.resize(200);
|
||||
ContainedRegClasses.resize(NumRegClasses);
|
||||
ContainedRegClasses.setBitsInMask(CoveredClasses);
|
||||
}
|
||||
|
||||
|
@ -127,6 +127,7 @@ def HasV8_2aOps : SubtargetFeature<"v8.2a", "HasV8_2aOps", "true",
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "AArch64RegisterInfo.td"
|
||||
include "AArch64RegisterBanks.td"
|
||||
include "AArch64CallingConvention.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -16,204 +16,81 @@
|
||||
#endif
|
||||
|
||||
namespace llvm {
|
||||
namespace AArch64 {
|
||||
|
||||
const uint32_t GPRCoverageData[] = {
|
||||
// Classes 0-31
|
||||
(1u << AArch64::GPR32allRegClassID) | (1u << AArch64::GPR32RegClassID) |
|
||||
(1u << AArch64::GPR32spRegClassID) |
|
||||
(1u << AArch64::GPR32commonRegClassID) |
|
||||
(1u << AArch64::GPR32sponlyRegClassID) |
|
||||
(1u << AArch64::GPR64allRegClassID) | (1u << AArch64::GPR64RegClassID) |
|
||||
(1u << AArch64::GPR64spRegClassID) |
|
||||
(1u << AArch64::GPR64commonRegClassID) |
|
||||
(1u << AArch64::tcGPR64RegClassID) |
|
||||
(1u << AArch64::GPR64sponlyRegClassID),
|
||||
// Classes 32-63
|
||||
0,
|
||||
// FIXME: The entries below this point can be safely removed once this is
|
||||
// tablegenerated. It's only needed because of the hardcoded register class
|
||||
// limit.
|
||||
// Classes 64-96
|
||||
0,
|
||||
// Classes 97-128
|
||||
0,
|
||||
// Classes 129-160
|
||||
0,
|
||||
// Classes 161-192
|
||||
0,
|
||||
// Classes 193-224
|
||||
0,
|
||||
};
|
||||
|
||||
const uint32_t FPRCoverageData[] = {
|
||||
// Classes 0-31
|
||||
(1u << AArch64::FPR8RegClassID) | (1u << AArch64::FPR16RegClassID) |
|
||||
(1u << AArch64::FPR32RegClassID) | (1u << AArch64::FPR64RegClassID) |
|
||||
(1u << AArch64::DDRegClassID) | (1u << AArch64::FPR128RegClassID) |
|
||||
(1u << AArch64::FPR128_loRegClassID) | (1u << AArch64::DDDRegClassID) |
|
||||
(1u << AArch64::DDDDRegClassID),
|
||||
// Classes 32-63
|
||||
(1u << (AArch64::QQRegClassID - 32)) |
|
||||
(1u << (AArch64::QQ_with_qsub0_in_FPR128_loRegClassID - 32)) |
|
||||
(1u << (AArch64::QQ_with_qsub1_in_FPR128_loRegClassID - 32)) |
|
||||
(1u
|
||||
<< (AArch64::
|
||||
QQQ_with_qsub1_in_FPR128_lo_and_QQQ_with_qsub2_in_FPR128_loRegClassID -
|
||||
32)) |
|
||||
(1u
|
||||
<< (AArch64::
|
||||
QQQ_with_qsub0_in_FPR128_lo_and_QQQ_with_qsub2_in_FPR128_loRegClassID -
|
||||
32)) |
|
||||
(1u << (AArch64::QQQQRegClassID - 32)) |
|
||||
(1u << (AArch64::QQQQ_with_qsub0_in_FPR128_loRegClassID - 32)) |
|
||||
(1u << (AArch64::QQQQ_with_qsub1_in_FPR128_loRegClassID - 32)) |
|
||||
(1u << (AArch64::QQQQ_with_qsub2_in_FPR128_loRegClassID - 32)) |
|
||||
(1u << (AArch64::QQQQ_with_qsub3_in_FPR128_loRegClassID - 32)) |
|
||||
(1u
|
||||
<< (AArch64::
|
||||
QQQQ_with_qsub0_in_FPR128_lo_and_QQQQ_with_qsub1_in_FPR128_loRegClassID -
|
||||
32)) |
|
||||
(1u
|
||||
<< (AArch64::
|
||||
QQQQ_with_qsub1_in_FPR128_lo_and_QQQQ_with_qsub2_in_FPR128_loRegClassID -
|
||||
32)) |
|
||||
(1u
|
||||
<< (AArch64::
|
||||
QQQQ_with_qsub2_in_FPR128_lo_and_QQQQ_with_qsub3_in_FPR128_loRegClassID -
|
||||
32)) |
|
||||
(1u
|
||||
<< (AArch64::
|
||||
QQQQ_with_qsub0_in_FPR128_lo_and_QQQQ_with_qsub2_in_FPR128_loRegClassID -
|
||||
32)) |
|
||||
(1u
|
||||
<< (AArch64::
|
||||
QQQQ_with_qsub1_in_FPR128_lo_and_QQQQ_with_qsub3_in_FPR128_loRegClassID -
|
||||
32)) |
|
||||
(1u
|
||||
<< (AArch64::
|
||||
QQQQ_with_qsub0_in_FPR128_lo_and_QQQQ_with_qsub3_in_FPR128_loRegClassID -
|
||||
32)) |
|
||||
(1u
|
||||
<< (AArch64::
|
||||
QQ_with_qsub0_in_FPR128_lo_and_QQ_with_qsub1_in_FPR128_loRegClassID -
|
||||
32)) |
|
||||
(1u << (AArch64::QQQRegClassID - 32)) |
|
||||
(1u << (AArch64::QQQ_with_qsub0_in_FPR128_loRegClassID - 32)) |
|
||||
(1u << (AArch64::QQQ_with_qsub1_in_FPR128_loRegClassID - 32)) |
|
||||
(1u << (AArch64::QQQ_with_qsub2_in_FPR128_loRegClassID - 32)) |
|
||||
(1u
|
||||
<< (AArch64::
|
||||
QQQ_with_qsub0_in_FPR128_lo_and_QQQ_with_qsub1_in_FPR128_loRegClassID -
|
||||
32)),
|
||||
// FIXME: The entries below this point can be safely removed once this
|
||||
// is tablegenerated. It's only needed because of the hardcoded register
|
||||
// class limit.
|
||||
// Classes 64-96
|
||||
0,
|
||||
// Classes 97-128
|
||||
0,
|
||||
// Classes 129-160
|
||||
0,
|
||||
// Classes 161-192
|
||||
0,
|
||||
// Classes 193-224
|
||||
0,
|
||||
};
|
||||
|
||||
const uint32_t CCRCoverageData[] = {
|
||||
// Classes 0-31
|
||||
1u << AArch64::CCRRegClassID,
|
||||
// Classes 32-63
|
||||
0,
|
||||
// FIXME: The entries below this point can be safely removed once this
|
||||
// is tablegenerated. It's only needed because of the hardcoded register
|
||||
// class limit.
|
||||
// Classes 64-96
|
||||
0,
|
||||
// Classes 97-128
|
||||
0,
|
||||
// Classes 129-160
|
||||
0,
|
||||
// Classes 161-192
|
||||
0,
|
||||
// Classes 193-224
|
||||
0,
|
||||
};
|
||||
|
||||
RegisterBank GPRRegBank(AArch64::GPRRegBankID, "GPR", 64, GPRCoverageData);
|
||||
RegisterBank FPRRegBank(AArch64::FPRRegBankID, "FPR", 512, FPRCoverageData);
|
||||
RegisterBank CCRRegBank(AArch64::CCRRegBankID, "CCR", 32, CCRCoverageData);
|
||||
} // end namespace AArch64
|
||||
|
||||
RegisterBank *AArch64GenRegisterBankInfo::RegBanks[] = {
|
||||
&AArch64::GPRRegBank, &AArch64::FPRRegBank, &AArch64::CCRRegBank};
|
||||
|
||||
RegisterBankInfo::PartialMapping AArch64GenRegisterBankInfo::PartMappings[]{
|
||||
/* StartIdx, Length, RegBank */
|
||||
// 0: GPR 32-bit value.
|
||||
{0, 32, AArch64::GPRRegBank},
|
||||
// 1: GPR 64-bit value.
|
||||
{0, 64, AArch64::GPRRegBank},
|
||||
// 2: FPR 32-bit value.
|
||||
// 0: FPR 32-bit value.
|
||||
{0, 32, AArch64::FPRRegBank},
|
||||
// 3: FPR 64-bit value.
|
||||
// 1: FPR 64-bit value.
|
||||
{0, 64, AArch64::FPRRegBank},
|
||||
// 4: FPR 128-bit value.
|
||||
// 2: FPR 128-bit value.
|
||||
{0, 128, AArch64::FPRRegBank},
|
||||
// 5: FPR 256-bit value.
|
||||
// 3: FPR 256-bit value.
|
||||
{0, 256, AArch64::FPRRegBank},
|
||||
// 6: FPR 512-bit value.
|
||||
{0, 512, AArch64::FPRRegBank}};
|
||||
// 4: FPR 512-bit value.
|
||||
{0, 512, AArch64::FPRRegBank},
|
||||
// 5: GPR 32-bit value.
|
||||
{0, 32, AArch64::GPRRegBank},
|
||||
// 6: GPR 64-bit value.
|
||||
{0, 64, AArch64::GPRRegBank},
|
||||
};
|
||||
|
||||
// ValueMappings.
|
||||
RegisterBankInfo::ValueMapping AArch64GenRegisterBankInfo::ValMappings[]{
|
||||
/* BreakDown, NumBreakDowns */
|
||||
// 3-operands instructions (all binary operations should end up with one of
|
||||
// those mapping).
|
||||
// 0: GPR 32-bit value. <-- This must match First3OpsIdx.
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1},
|
||||
// 3: GPR 64-bit value.
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1},
|
||||
// 6: FPR 32-bit value.
|
||||
// 0: FPR 32-bit value. <-- This must match First3OpsIdx.
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1},
|
||||
// 9: FPR 64-bit value.
|
||||
// 3: FPR 64-bit value.
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1},
|
||||
// 12: FPR 128-bit value.
|
||||
// 6: FPR 128-bit value.
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR128 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR128 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR128 - PMI_Min], 1},
|
||||
// 15: FPR 256-bit value.
|
||||
// 9: FPR 256-bit value.
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR256 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR256 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR256 - PMI_Min], 1},
|
||||
// 18: FPR 512-bit value. <-- This must match Last3OpsIdx.
|
||||
// 12: FPR 512-bit value.
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR512 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR512 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR512 - PMI_Min], 1},
|
||||
// 15: GPR 32-bit value.
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1},
|
||||
// 18: GPR 64-bit value. <-- This must match Last3OpsIdx.
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1},
|
||||
// Cross register bank copies.
|
||||
// 21: GPR 32-bit value to FPR 32-bit value. <-- This must match
|
||||
// 21: FPR 32-bit value to GPR 32-bit value. <-- This must match
|
||||
// FirstCrossRegCpyIdx.
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1},
|
||||
// 23: FPR 64-bit value to GPR 64-bit value.
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1},
|
||||
// 25: FPR 128-bit value to GPR 128-bit value (invalid)
|
||||
{nullptr, 1},
|
||||
{nullptr, 1},
|
||||
// 27: FPR 256-bit value to GPR 256-bit value (invalid)
|
||||
{nullptr, 1},
|
||||
{nullptr, 1},
|
||||
// 29: FPR 512-bit value to GPR 512-bit value (invalid)
|
||||
{nullptr, 1},
|
||||
{nullptr, 1},
|
||||
// 31: GPR 32-bit value to FPR 32-bit value.
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1},
|
||||
// 23: GPR 64-bit value to FPR 64-bit value.
|
||||
// 33: GPR 64-bit value to FPR 64-bit value. <-- This must match
|
||||
// LastCrossRegCpyIdx.
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1},
|
||||
// 25: FPR 32-bit value to GPR 32-bit value.
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1},
|
||||
// 27: FPR 64-bit value to GPR 64-bit value. <-- This must match
|
||||
// LastCrossRegCpyIdx.
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1},
|
||||
{&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}
|
||||
};
|
||||
|
||||
bool AArch64GenRegisterBankInfo::checkPartialMap(unsigned Idx,
|
||||
@ -301,9 +178,9 @@ AArch64GenRegisterBankInfo::getValueMapping(PartialMappingIdx RBIdx,
|
||||
|
||||
AArch64GenRegisterBankInfo::PartialMappingIdx
|
||||
AArch64GenRegisterBankInfo::BankIDToCopyMapIdx[]{
|
||||
PMI_FirstGPR, // GPR
|
||||
PMI_FirstFPR, // FPR
|
||||
PMI_None, // CCR
|
||||
PMI_FirstFPR, // FPR
|
||||
PMI_FirstGPR, // GPR
|
||||
};
|
||||
|
||||
const RegisterBankInfo::ValueMapping *
|
||||
|
@ -21,6 +21,9 @@
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#include "llvm/Target/TargetSubtargetInfo.h"
|
||||
|
||||
#define GET_TARGET_REGBANK_IMPL
|
||||
#include "AArch64GenRegisterBank.inc"
|
||||
|
||||
// This file will be TableGen'ed at some point.
|
||||
#include "AArch64GenRegisterBankInfo.def"
|
||||
|
||||
@ -30,9 +33,6 @@ using namespace llvm;
|
||||
#error "You shouldn't build this"
|
||||
#endif
|
||||
|
||||
AArch64GenRegisterBankInfo::AArch64GenRegisterBankInfo()
|
||||
: RegisterBankInfo(RegBanks, AArch64::NumRegisterBanks) {}
|
||||
|
||||
AArch64RegisterBankInfo::AArch64RegisterBankInfo(const TargetRegisterInfo &TRI)
|
||||
: AArch64GenRegisterBankInfo() {
|
||||
static bool AlreadyInit = false;
|
||||
|
@ -16,40 +16,30 @@
|
||||
|
||||
#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
|
||||
|
||||
#define GET_REGBANK_DECLARATIONS
|
||||
#include "AArch64GenRegisterBank.inc"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class TargetRegisterInfo;
|
||||
|
||||
namespace AArch64 {
|
||||
enum {
|
||||
GPRRegBankID = 0, /// General Purpose Registers: W, X.
|
||||
FPRRegBankID = 1, /// Floating Point/Vector Registers: B, H, S, D, Q.
|
||||
CCRRegBankID = 2, /// Conditional register: NZCV.
|
||||
NumRegisterBanks
|
||||
};
|
||||
} // End AArch64 namespace.
|
||||
|
||||
class AArch64GenRegisterBankInfo : public RegisterBankInfo {
|
||||
private:
|
||||
static RegisterBank *RegBanks[];
|
||||
|
||||
protected:
|
||||
AArch64GenRegisterBankInfo();
|
||||
|
||||
enum PartialMappingIdx {
|
||||
PMI_None = -1,
|
||||
PMI_GPR32 = 1,
|
||||
PMI_GPR64,
|
||||
PMI_FPR32,
|
||||
PMI_FPR32 = 1,
|
||||
PMI_FPR64,
|
||||
PMI_FPR128,
|
||||
PMI_FPR256,
|
||||
PMI_FPR512,
|
||||
PMI_GPR32,
|
||||
PMI_GPR64,
|
||||
PMI_FirstGPR = PMI_GPR32,
|
||||
PMI_LastGPR = PMI_GPR64,
|
||||
PMI_FirstFPR = PMI_FPR32,
|
||||
PMI_LastFPR = PMI_FPR512,
|
||||
PMI_Min = PMI_FirstGPR,
|
||||
PMI_Min = PMI_FirstFPR,
|
||||
};
|
||||
|
||||
static RegisterBankInfo::PartialMapping PartMappings[];
|
||||
@ -61,7 +51,7 @@ protected:
|
||||
Last3OpsIdx = 18,
|
||||
DistanceBetweenRegBanks = 3,
|
||||
FirstCrossRegCpyIdx = 21,
|
||||
LastCrossRegCpyIdx = 27,
|
||||
LastCrossRegCpyIdx = 33,
|
||||
DistanceBetweenCrossRegCpy = 2
|
||||
};
|
||||
|
||||
@ -90,6 +80,9 @@ protected:
|
||||
/// register bank with a size of \p Size.
|
||||
static const RegisterBankInfo::ValueMapping *
|
||||
getCopyMapping(unsigned DstBankID, unsigned SrcBankID, unsigned Size);
|
||||
|
||||
#define GET_TARGET_REGBANK_CLASS
|
||||
#include "AArch64GenRegisterBank.inc"
|
||||
};
|
||||
|
||||
/// This class provides the information for the target register banks.
|
||||
|
20
lib/Target/AArch64/AArch64RegisterBanks.td
Normal file
20
lib/Target/AArch64/AArch64RegisterBanks.td
Normal file
@ -0,0 +1,20 @@
|
||||
//=- AArch64RegisterBank.td - Describe the AArch64 Banks -----*- tablegen -*-=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// General Purpose Registers: W, X.
|
||||
def GPRRegBank : RegisterBank<"GPR", [GPR64all]>;
|
||||
|
||||
/// Floating Point/Vector Registers: B, H, S, D, Q.
|
||||
def FPRRegBank : RegisterBank<"FPR", [QQQQ]>;
|
||||
|
||||
/// Conditional register: NZCV.
|
||||
def CCRRegBank : RegisterBank<"CCR", [CCR]>;
|
@ -14,7 +14,9 @@
|
||||
#include "AArch64CallLowering.h"
|
||||
#include "AArch64InstructionSelector.h"
|
||||
#include "AArch64LegalizerInfo.h"
|
||||
#ifdef LLVM_BUILD_GLOBAL_ISEL
|
||||
#include "AArch64RegisterBankInfo.h"
|
||||
#endif
|
||||
#include "AArch64Subtarget.h"
|
||||
#include "AArch64TargetMachine.h"
|
||||
#include "AArch64TargetObjectFile.h"
|
||||
|
@ -14,6 +14,7 @@ tablegen(LLVM AArch64GenSubtargetInfo.inc -gen-subtarget)
|
||||
tablegen(LLVM AArch64GenDisassemblerTables.inc -gen-disassembler)
|
||||
tablegen(LLVM AArch64GenSystemOperands.inc -gen-searchable-tables)
|
||||
if(LLVM_BUILD_GLOBAL_ISEL)
|
||||
tablegen(LLVM AArch64GenRegisterBank.inc -gen-register-bank)
|
||||
tablegen(LLVM AArch64GenGlobalISel.inc -gen-global-isel)
|
||||
endif()
|
||||
|
||||
|
@ -55,7 +55,9 @@ const uint32_t GPRCoverageData[] = {
|
||||
0,
|
||||
};
|
||||
|
||||
RegisterBank GPRRegBank(ARM::GPRRegBankID, "GPRB", 32, ARM::GPRCoverageData);
|
||||
// FIXME: The 200 will be replaced by the number of register classes when this is
|
||||
// tablegenerated.
|
||||
RegisterBank GPRRegBank(ARM::GPRRegBankID, "GPRB", 32, ARM::GPRCoverageData, 200);
|
||||
RegisterBank *RegBanks[] = {&GPRRegBank};
|
||||
|
||||
RegisterBankInfo::PartialMapping GPRPartialMapping{0, 32, GPRRegBank};
|
||||
|
16
llvm/Target/GlobalISel/RegisterBank.td
Normal file
16
llvm/Target/GlobalISel/RegisterBank.td
Normal file
@ -0,0 +1,16 @@
|
||||
//===- RegisterBank.td - Register bank definitions ---------*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class RegisterBank<string name, list<RegisterClass> classes> {
|
||||
string Name = name;
|
||||
list<RegisterClass> RegisterClasses = classes;
|
||||
}
|
@ -27,6 +27,7 @@ add_tablegen(llvm-tblgen LLVM
|
||||
IntrinsicEmitter.cpp
|
||||
OptParserEmitter.cpp
|
||||
PseudoLoweringEmitter.cpp
|
||||
RegisterBankEmitter.cpp
|
||||
RegisterInfoEmitter.cpp
|
||||
SearchableTableEmitter.cpp
|
||||
SubtargetEmitter.cpp
|
||||
|
312
utils/TableGen/RegisterBankEmitter.cpp
Normal file
312
utils/TableGen/RegisterBankEmitter.cpp
Normal file
@ -0,0 +1,312 @@
|
||||
//===- RegisterBankEmitter.cpp - Generate a Register Bank Desc. -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This tablegen backend is responsible for emitting a description of a target
|
||||
// register bank for a code generator.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/TableGen/Error.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
|
||||
#include "CodeGenRegisters.h"
|
||||
|
||||
#define DEBUG_TYPE "register-bank-emitter"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class RegisterBank {
|
||||
|
||||
/// A vector of register classes that are included in the register bank.
|
||||
typedef std::vector<const CodeGenRegisterClass *> RegisterClassesTy;
|
||||
|
||||
private:
|
||||
const Record &TheDef;
|
||||
|
||||
/// The register classes that are covered by the register bank.
|
||||
RegisterClassesTy RCs;
|
||||
|
||||
/// The register class with the largest register size.
|
||||
const CodeGenRegisterClass *RCWithLargestRegsSize;
|
||||
|
||||
public:
|
||||
RegisterBank(const Record &TheDef)
|
||||
: TheDef(TheDef), RCs(), RCWithLargestRegsSize(nullptr) {}
|
||||
|
||||
/// Get the human-readable name for the bank.
|
||||
std::string getName() const { return TheDef.getValueAsString("Name"); }
|
||||
/// Get the name of the enumerator in the ID enumeration.
|
||||
std::string getEnumeratorName() const { return (TheDef.getName() + "ID").str(); }
|
||||
|
||||
/// Get the name of the array holding the register class coverage data;
|
||||
std::string getCoverageArrayName() const {
|
||||
return (TheDef.getName() + "CoverageData").str();
|
||||
}
|
||||
|
||||
/// Get the name of the global instance variable.
|
||||
StringRef getInstanceVarName() const { return TheDef.getName(); }
|
||||
|
||||
const Record &getDef() const { return TheDef; }
|
||||
|
||||
/// Get the register classes listed in the RegisterBank.RegisterClasses field.
|
||||
std::vector<const CodeGenRegisterClass *>
|
||||
getExplictlySpecifiedRegisterClasses(
|
||||
CodeGenRegBank &RegisterClassHierarchy) const {
|
||||
std::vector<const CodeGenRegisterClass *> RCs;
|
||||
for (const auto &RCDef : getDef().getValueAsListOfDefs("RegisterClasses"))
|
||||
RCs.push_back(RegisterClassHierarchy.getRegClass(RCDef));
|
||||
return RCs;
|
||||
}
|
||||
|
||||
/// Add a register class to the bank without duplicates.
|
||||
void addRegisterClass(const CodeGenRegisterClass *RC) {
|
||||
if (std::find_if(RCs.begin(), RCs.end(),
|
||||
[&RC](const CodeGenRegisterClass *X) {
|
||||
return X == RC;
|
||||
}) != RCs.end())
|
||||
return;
|
||||
|
||||
// FIXME? We really want the register size rather than the spill size
|
||||
// since the spill size may be bigger on some targets with
|
||||
// limited load/store instructions. However, we don't store the
|
||||
// register size anywhere (we could sum the sizes of the subregisters
|
||||
// but there may be additional bits too) and we can't derive it from
|
||||
// the VT's reliably due to Untyped.
|
||||
if (RCWithLargestRegsSize == nullptr)
|
||||
RCWithLargestRegsSize = RC;
|
||||
else if (RCWithLargestRegsSize->SpillSize < RC->SpillSize)
|
||||
RCWithLargestRegsSize = RC;
|
||||
assert(RCWithLargestRegsSize && "RC was nullptr?");
|
||||
|
||||
RCs.emplace_back(RC);
|
||||
}
|
||||
|
||||
const CodeGenRegisterClass *getRCWithLargestRegsSize() const {
|
||||
return RCWithLargestRegsSize;
|
||||
}
|
||||
|
||||
iterator_range<typename RegisterClassesTy::const_iterator>
|
||||
register_classes() const {
|
||||
return llvm::make_range(RCs.begin(), RCs.end());
|
||||
}
|
||||
};
|
||||
|
||||
class RegisterBankEmitter {
|
||||
private:
|
||||
RecordKeeper &Records;
|
||||
CodeGenRegBank RegisterClassHierarchy;
|
||||
|
||||
void emitHeader(raw_ostream &OS, const StringRef TargetName,
|
||||
const std::vector<RegisterBank> &Banks);
|
||||
void emitBaseClassDefinition(raw_ostream &OS, const StringRef TargetName,
|
||||
const std::vector<RegisterBank> &Banks);
|
||||
void emitBaseClassImplementation(raw_ostream &OS, const StringRef TargetName,
|
||||
std::vector<RegisterBank> &Banks);
|
||||
|
||||
public:
|
||||
RegisterBankEmitter(RecordKeeper &R)
|
||||
: Records(R), RegisterClassHierarchy(Records) {}
|
||||
|
||||
void run(raw_ostream &OS);
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
/// Emit code to declare the ID enumeration and external global instance
|
||||
/// variables.
|
||||
void RegisterBankEmitter::emitHeader(raw_ostream &OS,
|
||||
const StringRef TargetName,
|
||||
const std::vector<RegisterBank> &Banks) {
|
||||
// <Target>RegisterBankInfo.h
|
||||
OS << "namespace llvm {\n"
|
||||
<< "namespace " << TargetName << " {\n"
|
||||
<< "enum {\n";
|
||||
for (const auto &Bank : Banks)
|
||||
OS << " " << Bank.getEnumeratorName() << ",\n";
|
||||
OS << " NumRegisterBanks,\n"
|
||||
<< "};\n"
|
||||
<< "} // end namespace " << TargetName << "\n"
|
||||
<< "} // end namespace llvm\n";
|
||||
}
|
||||
|
||||
/// Emit declarations of the <Target>GenRegisterBankInfo class.
|
||||
void RegisterBankEmitter::emitBaseClassDefinition(
|
||||
raw_ostream &OS, const StringRef TargetName,
|
||||
const std::vector<RegisterBank> &Banks) {
|
||||
OS << "private:\n"
|
||||
<< " static RegisterBank *RegBanks[];\n\n"
|
||||
<< "protected:\n"
|
||||
<< " " << TargetName << "GenRegisterBankInfo();\n"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
/// Visit each register class belonging to the given register bank.
|
||||
///
|
||||
/// A class belongs to the bank iff any of these apply:
|
||||
/// * It is explicitly specified
|
||||
/// * It is a subclass of a class that is a member.
|
||||
/// * It is a class containing subregisters of the registers of a class that
|
||||
/// is a member. This is known as a subreg-class.
|
||||
///
|
||||
/// This function must be called for each explicitly specified register class.
|
||||
///
|
||||
/// \param RC The register class to search.
|
||||
/// \param Kind A debug string containing the path the visitor took to reach RC.
|
||||
/// \param VisitFn The action to take for each class visited. It may be called
|
||||
/// multiple times for a given class if there are multiple paths
|
||||
/// to the class.
|
||||
static void visitRegisterBankClasses(
|
||||
CodeGenRegBank &RegisterClassHierarchy, const CodeGenRegisterClass *RC,
|
||||
const Twine Kind,
|
||||
std::function<void(const CodeGenRegisterClass *, StringRef)> VisitFn) {
|
||||
// Visit each explicitly named class.
|
||||
VisitFn(RC, Kind.str());
|
||||
|
||||
for (const auto &PossibleSubclass : RegisterClassHierarchy.getRegClasses()) {
|
||||
std::string TmpKind =
|
||||
(Twine(Kind) + " (" + PossibleSubclass.getName() + ")").str();
|
||||
|
||||
// Visit each subclass of an explicitly named class.
|
||||
if (RC != &PossibleSubclass && RC->hasSubClass(&PossibleSubclass))
|
||||
visitRegisterBankClasses(RegisterClassHierarchy, &PossibleSubclass,
|
||||
TmpKind + " " + RC->getName() + " subclass",
|
||||
VisitFn);
|
||||
|
||||
// Visit each class that contains only subregisters of RC with a common
|
||||
// subregister-index.
|
||||
//
|
||||
// More precisely, PossibleSubclass is a subreg-class iff Reg:SubIdx is in
|
||||
// PossibleSubclass for all registers Reg from RC using any
|
||||
// subregister-index SubReg
|
||||
for (const auto &SubIdx : RegisterClassHierarchy.getSubRegIndices()) {
|
||||
BitVector BV(RegisterClassHierarchy.getRegClasses().size());
|
||||
PossibleSubclass.getSuperRegClasses(&SubIdx, BV);
|
||||
if (BV.test(RC->EnumValue)) {
|
||||
std::string TmpKind2 = (Twine(TmpKind) + " " + RC->getName() +
|
||||
" class-with-subregs: " + RC->getName())
|
||||
.str();
|
||||
VisitFn(&PossibleSubclass, TmpKind2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterBankEmitter::emitBaseClassImplementation(
|
||||
raw_ostream &OS, StringRef TargetName,
|
||||
std::vector<RegisterBank> &Banks) {
|
||||
|
||||
OS << "namespace llvm {\n"
|
||||
<< "namespace " << TargetName << " {\n";
|
||||
for (const auto &Bank : Banks) {
|
||||
std::vector<std::vector<const CodeGenRegisterClass *>> RCsGroupedByWord(
|
||||
(RegisterClassHierarchy.getRegClasses().size() + 31) / 32);
|
||||
|
||||
for (const auto &RC : Bank.register_classes())
|
||||
RCsGroupedByWord[RC->EnumValue / 32].push_back(RC);
|
||||
|
||||
OS << "const uint32_t " << Bank.getCoverageArrayName() << "[] = {\n";
|
||||
unsigned LowestIdxInWord = 0;
|
||||
for (const auto &RCs : RCsGroupedByWord) {
|
||||
OS << " // " << LowestIdxInWord << "-" << (LowestIdxInWord + 31) << "\n";
|
||||
for (const auto &RC : RCs) {
|
||||
std::string QualifiedRegClassID =
|
||||
(Twine(TargetName) + "::" + RC->getName() + "RegClassID").str();
|
||||
OS << " (1u << (" << QualifiedRegClassID << " - "
|
||||
<< LowestIdxInWord << ")) |\n";
|
||||
}
|
||||
OS << " 0,\n";
|
||||
LowestIdxInWord += 32;
|
||||
}
|
||||
OS << "};\n";
|
||||
}
|
||||
OS << "\n";
|
||||
|
||||
for (const auto &Bank : Banks) {
|
||||
std::string QualifiedBankID =
|
||||
(TargetName + "::" + Bank.getEnumeratorName()).str();
|
||||
unsigned Size = Bank.getRCWithLargestRegsSize()->SpillSize;
|
||||
OS << "RegisterBank " << Bank.getInstanceVarName() << "(/* ID */ "
|
||||
<< QualifiedBankID << ", /* Name */ \"" << Bank.getName()
|
||||
<< "\", /* Size */ " << Size << ", "
|
||||
<< "/* CoveredRegClasses */ " << Bank.getCoverageArrayName()
|
||||
<< ", /* NumRegClasses */ "
|
||||
<< RegisterClassHierarchy.getRegClasses().size() << ");\n";
|
||||
}
|
||||
OS << "} // end namespace " << TargetName << "\n"
|
||||
<< "\n";
|
||||
|
||||
OS << "RegisterBank *" << TargetName
|
||||
<< "GenRegisterBankInfo::RegBanks[] = {\n";
|
||||
for (const auto &Bank : Banks)
|
||||
OS << " &" << TargetName << "::" << Bank.getInstanceVarName() << ",\n";
|
||||
OS << "};\n\n";
|
||||
|
||||
OS << TargetName << "GenRegisterBankInfo::" << TargetName
|
||||
<< "GenRegisterBankInfo()\n"
|
||||
<< " : RegisterBankInfo(RegBanks, " << TargetName
|
||||
<< "::NumRegisterBanks) {\n"
|
||||
<< " // Assert that RegBank indices match their ID's\n"
|
||||
<< " unsigned Index = 0;\n"
|
||||
<< "#ifndef NDEBUG\n"
|
||||
<< " for (const auto &RB : RegBanks)\n"
|
||||
<< " assert(Index++ == RB->getID() && \"Index != ID\");\n"
|
||||
<< "#endif // NDEBUG\n"
|
||||
<< "}\n"
|
||||
<< "} // end namespace llvm\n";
|
||||
}
|
||||
|
||||
void RegisterBankEmitter::run(raw_ostream &OS) {
|
||||
std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
|
||||
if (Targets.size() != 1)
|
||||
PrintFatalError("ERROR: Too many or too few subclasses of Target defined!");
|
||||
StringRef TargetName = Targets[0]->getName();
|
||||
|
||||
std::vector<RegisterBank> Banks;
|
||||
for (const auto &V : Records.getAllDerivedDefinitions("RegisterBank")) {
|
||||
RegisterBank Bank(*V);
|
||||
|
||||
for (const CodeGenRegisterClass *RC :
|
||||
Bank.getExplictlySpecifiedRegisterClasses(RegisterClassHierarchy)) {
|
||||
visitRegisterBankClasses(
|
||||
RegisterClassHierarchy, RC, "explicit",
|
||||
[&Bank](const CodeGenRegisterClass *RC, StringRef Kind) {
|
||||
DEBUG(dbgs() << "Added " << RC->getName() << "(" << Kind << ")\n");
|
||||
Bank.addRegisterClass(RC);
|
||||
});
|
||||
}
|
||||
|
||||
Banks.push_back(Bank);
|
||||
}
|
||||
|
||||
emitSourceFileHeader("Register Bank Source Fragments", OS);
|
||||
OS << "#ifdef GET_REGBANK_DECLARATIONS\n"
|
||||
<< "#undef GET_REGBANK_DECLARATIONS\n";
|
||||
emitHeader(OS, TargetName, Banks);
|
||||
OS << "#endif // GET_REGBANK_DECLARATIONS\n\n"
|
||||
<< "#ifdef GET_TARGET_REGBANK_CLASS\n"
|
||||
<< "#undef GET_TARGET_REGBANK_CLASS\n";
|
||||
emitBaseClassDefinition(OS, TargetName, Banks);
|
||||
OS << "#endif // GET_TARGET_REGBANK_CLASS\n\n"
|
||||
<< "#ifdef GET_TARGET_REGBANK_IMPL\n"
|
||||
<< "#undef GET_TARGET_REGBANK_IMPL\n";
|
||||
emitBaseClassImplementation(OS, TargetName, Banks);
|
||||
OS << "#endif // GET_TARGET_REGBANK_IMPL\n";
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void EmitRegisterBank(RecordKeeper &RK, raw_ostream &OS) {
|
||||
RegisterBankEmitter(RK).run(OS);
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
@ -46,6 +46,7 @@ enum ActionType {
|
||||
GenAttributes,
|
||||
GenSearchableTables,
|
||||
GenGlobalISel,
|
||||
GenRegisterBank,
|
||||
};
|
||||
|
||||
namespace {
|
||||
@ -94,7 +95,9 @@ namespace {
|
||||
clEnumValN(GenSearchableTables, "gen-searchable-tables",
|
||||
"Generate generic binary-searchable table"),
|
||||
clEnumValN(GenGlobalISel, "gen-global-isel",
|
||||
"Generate GlobalISel selector")));
|
||||
"Generate GlobalISel selector"),
|
||||
clEnumValN(GenRegisterBank, "gen-register-bank",
|
||||
"Generate registers bank descriptions")));
|
||||
|
||||
cl::opt<std::string>
|
||||
Class("class", cl::desc("Print Enum list for this class"),
|
||||
@ -182,6 +185,8 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
|
||||
break;
|
||||
case GenGlobalISel:
|
||||
EmitGlobalISel(Records, OS);
|
||||
case GenRegisterBank:
|
||||
EmitRegisterBank(Records, OS);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -81,6 +81,7 @@ void EmitCTags(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitAttributes(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitSearchableTables(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitGlobalISel(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitRegisterBank(RecordKeeper &RK, raw_ostream &OS);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user