summaryrefslogtreecommitdiff
path: root/lib/Target/ARM/ARMRegisterBankInfo.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-04-16 16:01:22 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-04-16 16:01:22 +0000
commit71d5a2540a98c81f5bcaeb48805e0e2881f530ef (patch)
tree5343938942df402b49ec7300a1c25a2d4ccd5821 /lib/Target/ARM/ARMRegisterBankInfo.cpp
parent31bbf64f3a4974a2d6c8b3b27ad2f519caf74057 (diff)
Notes
Diffstat (limited to 'lib/Target/ARM/ARMRegisterBankInfo.cpp')
-rw-r--r--lib/Target/ARM/ARMRegisterBankInfo.cpp208
1 files changed, 175 insertions, 33 deletions
diff --git a/lib/Target/ARM/ARMRegisterBankInfo.cpp b/lib/Target/ARM/ARMRegisterBankInfo.cpp
index 324087d670b5..08f3da738868 100644
--- a/lib/Target/ARM/ARMRegisterBankInfo.cpp
+++ b/lib/Target/ARM/ARMRegisterBankInfo.cpp
@@ -13,11 +13,15 @@
#include "ARMRegisterBankInfo.h"
#include "ARMInstrInfo.h" // For the register classes
+#include "ARMSubtarget.h"
#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
+#define GET_TARGET_REGBANK_IMPL
+#include "ARMGenRegisterBank.inc"
+
using namespace llvm;
#ifndef LLVM_BUILD_GLOBAL_ISEL
@@ -29,44 +33,109 @@ using namespace llvm;
// into an ARMGenRegisterBankInfo.def (similar to AArch64).
namespace llvm {
namespace ARM {
-const uint32_t GPRCoverageData[] = {
- // Classes 0-31
- (1u << ARM::GPRRegClassID) | (1u << ARM::GPRwithAPSRRegClassID) |
- (1u << ARM::GPRnopcRegClassID) | (1u << ARM::rGPRRegClassID) |
- (1u << ARM::hGPRRegClassID) | (1u << ARM::tGPRRegClassID) |
- (1u << ARM::GPRnopc_and_hGPRRegClassID) |
- (1u << ARM::hGPR_and_rGPRRegClassID) | (1u << ARM::tcGPRRegClassID) |
- (1u << ARM::tGPR_and_tcGPRRegClassID) | (1u << ARM::GPRspRegClassID) |
- (1u << ARM::hGPR_and_tcGPRRegClassID),
- // Classes 32-63
- 0,
- // Classes 64-96
- 0,
- // FIXME: Some of 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 97-128
- 0,
- // Classes 129-160
- 0,
- // Classes 161-192
- 0,
- // Classes 193-224
- 0,
+enum PartialMappingIdx {
+ PMI_GPR,
+ PMI_SPR,
+ PMI_DPR,
+ PMI_Min = PMI_GPR,
+};
+
+RegisterBankInfo::PartialMapping PartMappings[]{
+ // GPR Partial Mapping
+ {0, 32, GPRRegBank},
+ // SPR Partial Mapping
+ {0, 32, FPRRegBank},
+ // DPR Partial Mapping
+ {0, 64, FPRRegBank},
};
-RegisterBank GPRRegBank(ARM::GPRRegBankID, "GPRB", 32, ARM::GPRCoverageData);
-RegisterBank *RegBanks[] = {&GPRRegBank};
+#ifndef NDEBUG
+static bool checkPartMapping(const RegisterBankInfo::PartialMapping &PM,
+ unsigned Start, unsigned Length,
+ unsigned RegBankID) {
+ return PM.StartIdx == Start && PM.Length == Length &&
+ PM.RegBank->getID() == RegBankID;
+}
+
+static void checkPartialMappings() {
+ assert(
+ checkPartMapping(PartMappings[PMI_GPR - PMI_Min], 0, 32, GPRRegBankID) &&
+ "Wrong mapping for GPR");
+ assert(
+ checkPartMapping(PartMappings[PMI_SPR - PMI_Min], 0, 32, FPRRegBankID) &&
+ "Wrong mapping for SPR");
+ assert(
+ checkPartMapping(PartMappings[PMI_DPR - PMI_Min], 0, 64, FPRRegBankID) &&
+ "Wrong mapping for DPR");
+}
+#endif
-RegisterBankInfo::PartialMapping GPRPartialMapping{0, 32, GPRRegBank};
+enum ValueMappingIdx {
+ InvalidIdx = 0,
+ GPR3OpsIdx = 1,
+ SPR3OpsIdx = 4,
+ DPR3OpsIdx = 7,
+};
RegisterBankInfo::ValueMapping ValueMappings[] = {
- {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}};
+ // invalid
+ {nullptr, 0},
+ // 3 ops in GPRs
+ {&PartMappings[PMI_GPR - PMI_Min], 1},
+ {&PartMappings[PMI_GPR - PMI_Min], 1},
+ {&PartMappings[PMI_GPR - PMI_Min], 1},
+ // 3 ops in SPRs
+ {&PartMappings[PMI_SPR - PMI_Min], 1},
+ {&PartMappings[PMI_SPR - PMI_Min], 1},
+ {&PartMappings[PMI_SPR - PMI_Min], 1},
+ // 3 ops in DPRs
+ {&PartMappings[PMI_DPR - PMI_Min], 1},
+ {&PartMappings[PMI_DPR - PMI_Min], 1},
+ {&PartMappings[PMI_DPR - PMI_Min], 1}};
+
+#ifndef NDEBUG
+static bool checkValueMapping(const RegisterBankInfo::ValueMapping &VM,
+ RegisterBankInfo::PartialMapping *BreakDown) {
+ return VM.NumBreakDowns == 1 && VM.BreakDown == BreakDown;
+}
+
+static void checkValueMappings() {
+ assert(checkValueMapping(ValueMappings[GPR3OpsIdx],
+ &PartMappings[PMI_GPR - PMI_Min]) &&
+ "Wrong value mapping for 3 GPR ops instruction");
+ assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 1],
+ &PartMappings[PMI_GPR - PMI_Min]) &&
+ "Wrong value mapping for 3 GPR ops instruction");
+ assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 2],
+ &PartMappings[PMI_GPR - PMI_Min]) &&
+ "Wrong value mapping for 3 GPR ops instruction");
+
+ assert(checkValueMapping(ValueMappings[SPR3OpsIdx],
+ &PartMappings[PMI_SPR - PMI_Min]) &&
+ "Wrong value mapping for 3 SPR ops instruction");
+ assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 1],
+ &PartMappings[PMI_SPR - PMI_Min]) &&
+ "Wrong value mapping for 3 SPR ops instruction");
+ assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 2],
+ &PartMappings[PMI_SPR - PMI_Min]) &&
+ "Wrong value mapping for 3 SPR ops instruction");
+
+ assert(checkValueMapping(ValueMappings[DPR3OpsIdx],
+ &PartMappings[PMI_DPR - PMI_Min]) &&
+ "Wrong value mapping for 3 DPR ops instruction");
+ assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 1],
+ &PartMappings[PMI_DPR - PMI_Min]) &&
+ "Wrong value mapping for 3 DPR ops instruction");
+ assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 2],
+ &PartMappings[PMI_DPR - PMI_Min]) &&
+ "Wrong value mapping for 3 DPR ops instruction");
+}
+#endif
} // end namespace arm
} // end namespace llvm
ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI)
- : RegisterBankInfo(ARM::RegBanks, ARM::NumRegisterBanks) {
+ : ARMGenRegisterBankInfo() {
static bool AlreadyInit = false;
// We have only one set of register banks, whatever the subtarget
// is. Therefore, the initialization of the RegBanks table should be
@@ -97,6 +166,11 @@ ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI)
assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPR_and_tcGPRRegClassID)) &&
"Subclass not added?");
assert(RBGPR.getSize() == 32 && "GPRs should hold up to 32-bit");
+
+#ifndef NDEBUG
+ ARM::checkPartialMappings();
+ ARM::checkValueMappings();
+#endif
}
const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass(
@@ -105,8 +179,16 @@ const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass(
switch (RC.getID()) {
case GPRRegClassID:
+ case GPRnopcRegClassID:
+ case GPRspRegClassID:
case tGPR_and_tcGPRRegClassID:
+ case tGPRRegClassID:
return getRegBank(ARM::GPRRegBankID);
+ case SPR_8RegClassID:
+ case SPRRegClassID:
+ case DPR_8RegClassID:
+ case DPRRegClassID:
+ return getRegBank(ARM::FPRRegBankID);
default:
llvm_unreachable("Unsupported register kind");
}
@@ -128,23 +210,83 @@ ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
using namespace TargetOpcode;
+ const MachineFunction &MF = *MI.getParent()->getParent();
+ const MachineRegisterInfo &MRI = MF.getRegInfo();
+ LLT Ty = MRI.getType(MI.getOperand(0).getReg());
+
unsigned NumOperands = MI.getNumOperands();
- const ValueMapping *OperandsMapping = &ARM::ValueMappings[0];
+ const ValueMapping *OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
switch (Opc) {
case G_ADD:
- case G_LOAD:
+ case G_SEXT:
+ case G_ZEXT:
+ case G_GEP:
// FIXME: We're abusing the fact that everything lives in a GPR for now; in
// the real world we would use different mappings.
- OperandsMapping = &ARM::ValueMappings[0];
+ OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
+ break;
+ case G_LOAD:
+ case G_STORE:
+ OperandsMapping =
+ Ty.getSizeInBits() == 64
+ ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
+ &ARM::ValueMappings[ARM::GPR3OpsIdx]})
+ : &ARM::ValueMappings[ARM::GPR3OpsIdx];
+ break;
+ case G_FADD:
+ assert((Ty.getSizeInBits() == 32 || Ty.getSizeInBits() == 64) &&
+ "Unsupported size for G_FADD");
+ OperandsMapping = Ty.getSizeInBits() == 64
+ ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
+ : &ARM::ValueMappings[ARM::SPR3OpsIdx];
break;
+ case G_CONSTANT:
case G_FRAME_INDEX:
- OperandsMapping = getOperandsMapping({&ARM::ValueMappings[0], nullptr});
+ OperandsMapping =
+ getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
break;
+ case G_SEQUENCE: {
+ // We only support G_SEQUENCE for creating a double precision floating point
+ // value out of two GPRs.
+ LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
+ LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
+ if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 ||
+ Ty2.getSizeInBits() != 32)
+ return InstructionMapping{};
+ OperandsMapping =
+ getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
+ &ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr,
+ &ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
+ break;
+ }
+ case G_EXTRACT: {
+ // We only support G_EXTRACT for splitting a double precision floating point
+ // value into two GPRs.
+ LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
+ if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 64 ||
+ MI.getOperand(2).getImm() % 32 != 0)
+ return InstructionMapping{};
+ OperandsMapping = getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
+ &ARM::ValueMappings[ARM::DPR3OpsIdx],
+ nullptr, nullptr});
+ break;
+ }
default:
return InstructionMapping{};
}
+#ifndef NDEBUG
+ for (unsigned i = 0; i < NumOperands; i++) {
+ for (const auto &Mapping : OperandsMapping[i]) {
+ assert(
+ (Mapping.RegBank->getID() != ARM::FPRRegBankID ||
+ MF.getSubtarget<ARMSubtarget>().hasVFP2()) &&
+ "Trying to use floating point register bank on target without vfp");
+ }
+ }
+#endif
+
return InstructionMapping{DefaultMappingID, /*Cost=*/1, OperandsMapping,
NumOperands};
}