1 //===- ARMRegisterBankInfo.cpp -----------------------------------*- C++ -*-==//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 /// This file implements the targeting of the RegisterBankInfo class for ARM.
11 /// \todo This should be generated by TableGen.
12 //===----------------------------------------------------------------------===//
13 
14 #include "ARMRegisterBankInfo.h"
15 #include "ARMInstrInfo.h" // For the register classes
16 #include "llvm/CodeGen/GlobalISel/RegisterBank.h"
17 #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
18 #include "llvm/CodeGen/MachineRegisterInfo.h"
19 #include "llvm/Target/TargetRegisterInfo.h"
20 
21 #define GET_TARGET_REGBANK_IMPL
22 #include "ARMGenRegisterBank.inc"
23 
24 using namespace llvm;
25 
26 #ifndef LLVM_BUILD_GLOBAL_ISEL
27 #error "You shouldn't build this"
28 #endif
29 
30 // FIXME: TableGen this.
31 // If it grows too much and TableGen still isn't ready to do the job, extract it
32 // into an ARMGenRegisterBankInfo.def (similar to AArch64).
33 namespace llvm {
34 namespace ARM {
35 RegisterBankInfo::PartialMapping GPRPartialMapping{0, 32, GPRRegBank};
36 
37 RegisterBankInfo::ValueMapping ValueMappings[] = {
38     {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}};
39 } // end namespace arm
40 } // end namespace llvm
41 
42 ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI)
43     : ARMGenRegisterBankInfo() {
44   static bool AlreadyInit = false;
45   // We have only one set of register banks, whatever the subtarget
46   // is. Therefore, the initialization of the RegBanks table should be
47   // done only once. Indeed the table of all register banks
48   // (ARM::RegBanks) is unique in the compiler. At some point, it
49   // will get tablegen'ed and the whole constructor becomes empty.
50   if (AlreadyInit)
51     return;
52   AlreadyInit = true;
53 
54   const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID);
55   (void)RBGPR;
56   assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up");
57 
58   // Initialize the GPR bank.
59   assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) &&
60          "Subclass not added?");
61   assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) &&
62          "Subclass not added?");
63   assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) &&
64          "Subclass not added?");
65   assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) &&
66          "Subclass not added?");
67   assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) &&
68          "Subclass not added?");
69   assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) &&
70          "Subclass not added?");
71   assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPR_and_tcGPRRegClassID)) &&
72          "Subclass not added?");
73   assert(RBGPR.getSize() == 32 && "GPRs should hold up to 32-bit");
74 }
75 
76 const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass(
77     const TargetRegisterClass &RC) const {
78   using namespace ARM;
79 
80   switch (RC.getID()) {
81   case GPRRegClassID:
82   case GPRnopcRegClassID:
83   case tGPR_and_tcGPRRegClassID:
84     return getRegBank(ARM::GPRRegBankID);
85   default:
86     llvm_unreachable("Unsupported register kind");
87   }
88 
89   llvm_unreachable("Switch should handle all register classes");
90 }
91 
92 RegisterBankInfo::InstructionMapping
93 ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
94   auto Opc = MI.getOpcode();
95 
96   // Try the default logic for non-generic instructions that are either copies
97   // or already have some operands assigned to banks.
98   if (!isPreISelGenericOpcode(Opc)) {
99     InstructionMapping Mapping = getInstrMappingImpl(MI);
100     if (Mapping.isValid())
101       return Mapping;
102   }
103 
104   using namespace TargetOpcode;
105 
106   unsigned NumOperands = MI.getNumOperands();
107   const ValueMapping *OperandsMapping = &ARM::ValueMappings[0];
108 
109   switch (Opc) {
110   case G_ADD:
111   case G_LOAD:
112   case G_SEXT:
113   case G_ZEXT:
114     // FIXME: We're abusing the fact that everything lives in a GPR for now; in
115     // the real world we would use different mappings.
116     OperandsMapping = &ARM::ValueMappings[0];
117     break;
118   case G_FRAME_INDEX:
119     OperandsMapping = getOperandsMapping({&ARM::ValueMappings[0], nullptr});
120     break;
121   default:
122     return InstructionMapping{};
123   }
124 
125   return InstructionMapping{DefaultMappingID, /*Cost=*/1, OperandsMapping,
126                             NumOperands};
127 }
128