X86RegisterBankInfo.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. //===- X86RegisterBankInfo.cpp -----------------------------------*- C++ -*-==//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. /// \file
  9. /// This file implements the targeting of the RegisterBankInfo class for X86.
  10. /// \todo This should be generated by TableGen.
  11. //===----------------------------------------------------------------------===//
  12. #include "X86RegisterBankInfo.h"
  13. #include "X86InstrInfo.h"
  14. #include "llvm/CodeGen/MachineRegisterInfo.h"
  15. #include "llvm/CodeGen/RegisterBank.h"
  16. #include "llvm/CodeGen/RegisterBankInfo.h"
  17. #include "llvm/CodeGen/TargetRegisterInfo.h"
  18. #define GET_TARGET_REGBANK_IMPL
  19. #include "X86GenRegisterBank.inc"
  20. using namespace llvm;
  21. // This file will be TableGen'ed at some point.
  22. #define GET_TARGET_REGBANK_INFO_IMPL
  23. #include "X86GenRegisterBankInfo.def"
  24. X86RegisterBankInfo::X86RegisterBankInfo(const TargetRegisterInfo &TRI) {
  25. // validate RegBank initialization.
  26. const RegisterBank &RBGPR = getRegBank(X86::GPRRegBankID);
  27. (void)RBGPR;
  28. assert(&X86::GPRRegBank == &RBGPR && "Incorrect RegBanks inizalization.");
  29. // The GPR register bank is fully defined by all the registers in
  30. // GR64 + its subclasses.
  31. assert(RBGPR.covers(*TRI.getRegClass(X86::GR64RegClassID)) &&
  32. "Subclass not added?");
  33. assert(RBGPR.getSize() == 64 && "GPRs should hold up to 64-bit");
  34. }
  35. const RegisterBank &
  36. X86RegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
  37. LLT) const {
  38. if (X86::GR8RegClass.hasSubClassEq(&RC) ||
  39. X86::GR16RegClass.hasSubClassEq(&RC) ||
  40. X86::GR32RegClass.hasSubClassEq(&RC) ||
  41. X86::GR64RegClass.hasSubClassEq(&RC) ||
  42. X86::LOW32_ADDR_ACCESSRegClass.hasSubClassEq(&RC) ||
  43. X86::LOW32_ADDR_ACCESS_RBPRegClass.hasSubClassEq(&RC))
  44. return getRegBank(X86::GPRRegBankID);
  45. if (X86::FR32XRegClass.hasSubClassEq(&RC) ||
  46. X86::FR64XRegClass.hasSubClassEq(&RC) ||
  47. X86::VR128XRegClass.hasSubClassEq(&RC) ||
  48. X86::VR256XRegClass.hasSubClassEq(&RC) ||
  49. X86::VR512RegClass.hasSubClassEq(&RC))
  50. return getRegBank(X86::VECRRegBankID);
  51. llvm_unreachable("Unsupported register kind yet.");
  52. }
  53. X86GenRegisterBankInfo::PartialMappingIdx
  54. X86GenRegisterBankInfo::getPartialMappingIdx(const LLT &Ty, bool isFP) {
  55. if ((Ty.isScalar() && !isFP) || Ty.isPointer()) {
  56. switch (Ty.getSizeInBits()) {
  57. case 1:
  58. case 8:
  59. return PMI_GPR8;
  60. case 16:
  61. return PMI_GPR16;
  62. case 32:
  63. return PMI_GPR32;
  64. case 64:
  65. return PMI_GPR64;
  66. case 128:
  67. return PMI_VEC128;
  68. break;
  69. default:
  70. llvm_unreachable("Unsupported register size.");
  71. }
  72. } else if (Ty.isScalar()) {
  73. switch (Ty.getSizeInBits()) {
  74. case 32:
  75. return PMI_FP32;
  76. case 64:
  77. return PMI_FP64;
  78. case 128:
  79. return PMI_VEC128;
  80. default:
  81. llvm_unreachable("Unsupported register size.");
  82. }
  83. } else {
  84. switch (Ty.getSizeInBits()) {
  85. case 128:
  86. return PMI_VEC128;
  87. case 256:
  88. return PMI_VEC256;
  89. case 512:
  90. return PMI_VEC512;
  91. default:
  92. llvm_unreachable("Unsupported register size.");
  93. }
  94. }
  95. return PMI_None;
  96. }
  97. void X86RegisterBankInfo::getInstrPartialMappingIdxs(
  98. const MachineInstr &MI, const MachineRegisterInfo &MRI, const bool isFP,
  99. SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx) {
  100. unsigned NumOperands = MI.getNumOperands();
  101. for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
  102. auto &MO = MI.getOperand(Idx);
  103. if (!MO.isReg() || !MO.getReg())
  104. OpRegBankIdx[Idx] = PMI_None;
  105. else
  106. OpRegBankIdx[Idx] = getPartialMappingIdx(MRI.getType(MO.getReg()), isFP);
  107. }
  108. }
  109. bool X86RegisterBankInfo::getInstrValueMapping(
  110. const MachineInstr &MI,
  111. const SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx,
  112. SmallVectorImpl<const ValueMapping *> &OpdsMapping) {
  113. unsigned NumOperands = MI.getNumOperands();
  114. for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
  115. if (!MI.getOperand(Idx).isReg())
  116. continue;
  117. if (!MI.getOperand(Idx).getReg())
  118. continue;
  119. auto Mapping = getValueMapping(OpRegBankIdx[Idx], 1);
  120. if (!Mapping->isValid())
  121. return false;
  122. OpdsMapping[Idx] = Mapping;
  123. }
  124. return true;
  125. }
  126. const RegisterBankInfo::InstructionMapping &
  127. X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr &MI,
  128. bool isFP) const {
  129. const MachineFunction &MF = *MI.getParent()->getParent();
  130. const MachineRegisterInfo &MRI = MF.getRegInfo();
  131. unsigned NumOperands = MI.getNumOperands();
  132. LLT Ty = MRI.getType(MI.getOperand(0).getReg());
  133. if (NumOperands != 3 || (Ty != MRI.getType(MI.getOperand(1).getReg())) ||
  134. (Ty != MRI.getType(MI.getOperand(2).getReg())))
  135. llvm_unreachable("Unsupported operand mapping yet.");
  136. auto Mapping = getValueMapping(getPartialMappingIdx(Ty, isFP), 3);
  137. return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
  138. }
  139. const RegisterBankInfo::InstructionMapping &
  140. X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
  141. const MachineFunction &MF = *MI.getParent()->getParent();
  142. const MachineRegisterInfo &MRI = MF.getRegInfo();
  143. unsigned Opc = MI.getOpcode();
  144. // Try the default logic for non-generic instructions that are either copies
  145. // or already have some operands assigned to banks.
  146. if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
  147. const InstructionMapping &Mapping = getInstrMappingImpl(MI);
  148. if (Mapping.isValid())
  149. return Mapping;
  150. }
  151. switch (Opc) {
  152. case TargetOpcode::G_ADD:
  153. case TargetOpcode::G_SUB:
  154. case TargetOpcode::G_MUL:
  155. return getSameOperandsMapping(MI, false);
  156. case TargetOpcode::G_FADD:
  157. case TargetOpcode::G_FSUB:
  158. case TargetOpcode::G_FMUL:
  159. case TargetOpcode::G_FDIV:
  160. return getSameOperandsMapping(MI, true);
  161. case TargetOpcode::G_SHL:
  162. case TargetOpcode::G_LSHR:
  163. case TargetOpcode::G_ASHR: {
  164. unsigned NumOperands = MI.getNumOperands();
  165. LLT Ty = MRI.getType(MI.getOperand(0).getReg());
  166. auto Mapping = getValueMapping(getPartialMappingIdx(Ty, false), 3);
  167. return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
  168. }
  169. default:
  170. break;
  171. }
  172. unsigned NumOperands = MI.getNumOperands();
  173. SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
  174. switch (Opc) {
  175. case TargetOpcode::G_FPEXT:
  176. case TargetOpcode::G_FPTRUNC:
  177. case TargetOpcode::G_FCONSTANT:
  178. // Instruction having only floating-point operands (all scalars in VECRReg)
  179. getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
  180. break;
  181. case TargetOpcode::G_SITOFP:
  182. case TargetOpcode::G_FPTOSI: {
  183. // Some of the floating-point instructions have mixed GPR and FP operands:
  184. // fine-tune the computed mapping.
  185. auto &Op0 = MI.getOperand(0);
  186. auto &Op1 = MI.getOperand(1);
  187. const LLT Ty0 = MRI.getType(Op0.getReg());
  188. const LLT Ty1 = MRI.getType(Op1.getReg());
  189. bool FirstArgIsFP = Opc == TargetOpcode::G_SITOFP;
  190. bool SecondArgIsFP = Opc == TargetOpcode::G_FPTOSI;
  191. OpRegBankIdx[0] = getPartialMappingIdx(Ty0, /* isFP */ FirstArgIsFP);
  192. OpRegBankIdx[1] = getPartialMappingIdx(Ty1, /* isFP */ SecondArgIsFP);
  193. break;
  194. }
  195. case TargetOpcode::G_FCMP: {
  196. LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
  197. LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
  198. (void)Ty2;
  199. assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
  200. "Mismatched operand sizes for G_FCMP");
  201. unsigned Size = Ty1.getSizeInBits();
  202. (void)Size;
  203. assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
  204. auto FpRegBank = getPartialMappingIdx(Ty1, /* isFP */ true);
  205. OpRegBankIdx = {PMI_GPR8,
  206. /* Predicate */ PMI_None, FpRegBank, FpRegBank};
  207. break;
  208. }
  209. case TargetOpcode::G_TRUNC:
  210. case TargetOpcode::G_ANYEXT: {
  211. auto &Op0 = MI.getOperand(0);
  212. auto &Op1 = MI.getOperand(1);
  213. const LLT Ty0 = MRI.getType(Op0.getReg());
  214. const LLT Ty1 = MRI.getType(Op1.getReg());
  215. bool isFPTrunc = (Ty0.getSizeInBits() == 32 || Ty0.getSizeInBits() == 64) &&
  216. Ty1.getSizeInBits() == 128 && Opc == TargetOpcode::G_TRUNC;
  217. bool isFPAnyExt =
  218. Ty0.getSizeInBits() == 128 &&
  219. (Ty1.getSizeInBits() == 32 || Ty1.getSizeInBits() == 64) &&
  220. Opc == TargetOpcode::G_ANYEXT;
  221. getInstrPartialMappingIdxs(MI, MRI, /* isFP */ isFPTrunc || isFPAnyExt,
  222. OpRegBankIdx);
  223. } break;
  224. default:
  225. // Track the bank of each register, use NotFP mapping (all scalars in GPRs)
  226. getInstrPartialMappingIdxs(MI, MRI, /* isFP */ false, OpRegBankIdx);
  227. break;
  228. }
  229. // Finally construct the computed mapping.
  230. SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
  231. if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
  232. return getInvalidInstructionMapping();
  233. return getInstructionMapping(DefaultMappingID, /* Cost */ 1,
  234. getOperandsMapping(OpdsMapping), NumOperands);
  235. }
  236. void X86RegisterBankInfo::applyMappingImpl(
  237. const OperandsMapper &OpdMapper) const {
  238. return applyDefaultMapping(OpdMapper);
  239. }
  240. RegisterBankInfo::InstructionMappings
  241. X86RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const {
  242. const MachineFunction &MF = *MI.getParent()->getParent();
  243. const TargetSubtargetInfo &STI = MF.getSubtarget();
  244. const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
  245. const MachineRegisterInfo &MRI = MF.getRegInfo();
  246. switch (MI.getOpcode()) {
  247. case TargetOpcode::G_LOAD:
  248. case TargetOpcode::G_STORE:
  249. case TargetOpcode::G_IMPLICIT_DEF: {
  250. // we going to try to map 32/64 bit to PMI_FP32/PMI_FP64
  251. unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
  252. if (Size != 32 && Size != 64)
  253. break;
  254. unsigned NumOperands = MI.getNumOperands();
  255. // Track the bank of each register, use FP mapping (all scalars in VEC)
  256. SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
  257. getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
  258. // Finally construct the computed mapping.
  259. SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
  260. if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
  261. break;
  262. const RegisterBankInfo::InstructionMapping &Mapping = getInstructionMapping(
  263. /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping), NumOperands);
  264. InstructionMappings AltMappings;
  265. AltMappings.push_back(&Mapping);
  266. return AltMappings;
  267. }
  268. default:
  269. break;
  270. }
  271. return RegisterBankInfo::getInstrAlternativeMappings(MI);
  272. }