ARMLegalizerInfo.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. //===- ARMLegalizerInfo.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 Machinelegalizer class for ARM.
  10. /// \todo This should be generated by TableGen.
  11. //===----------------------------------------------------------------------===//
  12. #include "ARMLegalizerInfo.h"
  13. #include "ARMCallLowering.h"
  14. #include "ARMSubtarget.h"
  15. #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
  16. #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
  17. #include "llvm/CodeGen/LowLevelType.h"
  18. #include "llvm/CodeGen/MachineRegisterInfo.h"
  19. #include "llvm/CodeGen/TargetOpcodes.h"
  20. #include "llvm/CodeGen/ValueTypes.h"
  21. #include "llvm/IR/DerivedTypes.h"
  22. #include "llvm/IR/Type.h"
  23. using namespace llvm;
  24. using namespace LegalizeActions;
  25. /// FIXME: The following static functions are SizeChangeStrategy functions
  26. /// that are meant to temporarily mimic the behaviour of the old legalization
  27. /// based on doubling/halving non-legal types as closely as possible. This is
  28. /// not entirly possible as only legalizing the types that are exactly a power
  29. /// of 2 times the size of the legal types would require specifying all those
  30. /// sizes explicitly.
  31. /// In practice, not specifying those isn't a problem, and the below functions
  32. /// should disappear quickly as we add support for legalizing non-power-of-2
  33. /// sized types further.
  34. static void addAndInterleaveWithUnsupported(
  35. LegacyLegalizerInfo::SizeAndActionsVec &result,
  36. const LegacyLegalizerInfo::SizeAndActionsVec &v) {
  37. for (unsigned i = 0; i < v.size(); ++i) {
  38. result.push_back(v[i]);
  39. if (i + 1 < v[i].first && i + 1 < v.size() &&
  40. v[i + 1].first != v[i].first + 1)
  41. result.push_back({v[i].first + 1, LegacyLegalizeActions::Unsupported});
  42. }
  43. }
  44. static LegacyLegalizerInfo::SizeAndActionsVec
  45. widen_8_16(const LegacyLegalizerInfo::SizeAndActionsVec &v) {
  46. assert(v.size() >= 1);
  47. assert(v[0].first > 17);
  48. LegacyLegalizerInfo::SizeAndActionsVec result = {
  49. {1, LegacyLegalizeActions::Unsupported},
  50. {8, LegacyLegalizeActions::WidenScalar},
  51. {9, LegacyLegalizeActions::Unsupported},
  52. {16, LegacyLegalizeActions::WidenScalar},
  53. {17, LegacyLegalizeActions::Unsupported}};
  54. addAndInterleaveWithUnsupported(result, v);
  55. auto Largest = result.back().first;
  56. result.push_back({Largest + 1, LegacyLegalizeActions::Unsupported});
  57. return result;
  58. }
  59. static bool AEABI(const ARMSubtarget &ST) {
  60. return ST.isTargetAEABI() || ST.isTargetGNUAEABI() || ST.isTargetMuslAEABI();
  61. }
  62. ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
  63. using namespace TargetOpcode;
  64. const LLT p0 = LLT::pointer(0, 32);
  65. const LLT s1 = LLT::scalar(1);
  66. const LLT s8 = LLT::scalar(8);
  67. const LLT s16 = LLT::scalar(16);
  68. const LLT s32 = LLT::scalar(32);
  69. const LLT s64 = LLT::scalar(64);
  70. auto &LegacyInfo = getLegacyLegalizerInfo();
  71. if (ST.isThumb1Only()) {
  72. // Thumb1 is not supported yet.
  73. LegacyInfo.computeTables();
  74. verify(*ST.getInstrInfo());
  75. return;
  76. }
  77. getActionDefinitionsBuilder({G_SEXT, G_ZEXT, G_ANYEXT})
  78. .legalForCartesianProduct({s8, s16, s32}, {s1, s8, s16});
  79. getActionDefinitionsBuilder(G_SEXT_INREG).lower();
  80. getActionDefinitionsBuilder({G_MUL, G_AND, G_OR, G_XOR})
  81. .legalFor({s32})
  82. .clampScalar(0, s32, s32);
  83. if (ST.hasNEON())
  84. getActionDefinitionsBuilder({G_ADD, G_SUB})
  85. .legalFor({s32, s64})
  86. .minScalar(0, s32);
  87. else
  88. getActionDefinitionsBuilder({G_ADD, G_SUB})
  89. .legalFor({s32})
  90. .minScalar(0, s32);
  91. getActionDefinitionsBuilder({G_ASHR, G_LSHR, G_SHL})
  92. .legalFor({{s32, s32}})
  93. .minScalar(0, s32)
  94. .clampScalar(1, s32, s32);
  95. bool HasHWDivide = (!ST.isThumb() && ST.hasDivideInARMMode()) ||
  96. (ST.isThumb() && ST.hasDivideInThumbMode());
  97. if (HasHWDivide)
  98. getActionDefinitionsBuilder({G_SDIV, G_UDIV})
  99. .legalFor({s32})
  100. .clampScalar(0, s32, s32);
  101. else
  102. getActionDefinitionsBuilder({G_SDIV, G_UDIV})
  103. .libcallFor({s32})
  104. .clampScalar(0, s32, s32);
  105. for (unsigned Op : {G_SREM, G_UREM}) {
  106. LegacyInfo.setLegalizeScalarToDifferentSizeStrategy(Op, 0, widen_8_16);
  107. if (HasHWDivide)
  108. LegacyInfo.setAction({Op, s32}, LegacyLegalizeActions::Lower);
  109. else if (AEABI(ST))
  110. LegacyInfo.setAction({Op, s32}, LegacyLegalizeActions::Custom);
  111. else
  112. LegacyInfo.setAction({Op, s32}, LegacyLegalizeActions::Libcall);
  113. }
  114. getActionDefinitionsBuilder(G_INTTOPTR)
  115. .legalFor({{p0, s32}})
  116. .minScalar(1, s32);
  117. getActionDefinitionsBuilder(G_PTRTOINT)
  118. .legalFor({{s32, p0}})
  119. .minScalar(0, s32);
  120. getActionDefinitionsBuilder(G_CONSTANT)
  121. .legalFor({s32, p0})
  122. .clampScalar(0, s32, s32);
  123. getActionDefinitionsBuilder(G_ICMP)
  124. .legalForCartesianProduct({s1}, {s32, p0})
  125. .minScalar(1, s32);
  126. getActionDefinitionsBuilder(G_SELECT)
  127. .legalForCartesianProduct({s32, p0}, {s1})
  128. .minScalar(0, s32);
  129. // We're keeping these builders around because we'll want to add support for
  130. // floating point to them.
  131. auto &LoadStoreBuilder = getActionDefinitionsBuilder({G_LOAD, G_STORE})
  132. .legalForTypesWithMemDesc({{s8, p0, s8, 8},
  133. {s16, p0, s16, 8},
  134. {s32, p0, s32, 8},
  135. {p0, p0, p0, 8}})
  136. .unsupportedIfMemSizeNotPow2();
  137. getActionDefinitionsBuilder(G_FRAME_INDEX).legalFor({p0});
  138. getActionDefinitionsBuilder(G_GLOBAL_VALUE).legalFor({p0});
  139. auto &PhiBuilder =
  140. getActionDefinitionsBuilder(G_PHI)
  141. .legalFor({s32, p0})
  142. .minScalar(0, s32);
  143. getActionDefinitionsBuilder(G_PTR_ADD)
  144. .legalFor({{p0, s32}})
  145. .minScalar(1, s32);
  146. getActionDefinitionsBuilder(G_BRCOND).legalFor({s1});
  147. if (!ST.useSoftFloat() && ST.hasVFP2Base()) {
  148. getActionDefinitionsBuilder(
  149. {G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FCONSTANT, G_FNEG})
  150. .legalFor({s32, s64});
  151. LoadStoreBuilder
  152. .legalForTypesWithMemDesc({{s64, p0, s64, 32}})
  153. .maxScalar(0, s32);
  154. PhiBuilder.legalFor({s64});
  155. getActionDefinitionsBuilder(G_FCMP).legalForCartesianProduct({s1},
  156. {s32, s64});
  157. getActionDefinitionsBuilder(G_MERGE_VALUES).legalFor({{s64, s32}});
  158. getActionDefinitionsBuilder(G_UNMERGE_VALUES).legalFor({{s32, s64}});
  159. getActionDefinitionsBuilder(G_FPEXT).legalFor({{s64, s32}});
  160. getActionDefinitionsBuilder(G_FPTRUNC).legalFor({{s32, s64}});
  161. getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})
  162. .legalForCartesianProduct({s32}, {s32, s64});
  163. getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
  164. .legalForCartesianProduct({s32, s64}, {s32});
  165. } else {
  166. getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV})
  167. .libcallFor({s32, s64});
  168. LoadStoreBuilder.maxScalar(0, s32);
  169. for (auto Ty : {s32, s64})
  170. LegacyInfo.setAction({G_FNEG, Ty}, LegacyLegalizeActions::Lower);
  171. getActionDefinitionsBuilder(G_FCONSTANT).customFor({s32, s64});
  172. getActionDefinitionsBuilder(G_FCMP).customForCartesianProduct({s1},
  173. {s32, s64});
  174. if (AEABI(ST))
  175. setFCmpLibcallsAEABI();
  176. else
  177. setFCmpLibcallsGNU();
  178. getActionDefinitionsBuilder(G_FPEXT).libcallFor({{s64, s32}});
  179. getActionDefinitionsBuilder(G_FPTRUNC).libcallFor({{s32, s64}});
  180. getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})
  181. .libcallForCartesianProduct({s32}, {s32, s64});
  182. getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
  183. .libcallForCartesianProduct({s32, s64}, {s32});
  184. }
  185. // Just expand whatever loads and stores are left.
  186. LoadStoreBuilder.lower();
  187. if (!ST.useSoftFloat() && ST.hasVFP4Base())
  188. getActionDefinitionsBuilder(G_FMA).legalFor({s32, s64});
  189. else
  190. getActionDefinitionsBuilder(G_FMA).libcallFor({s32, s64});
  191. getActionDefinitionsBuilder({G_FREM, G_FPOW}).libcallFor({s32, s64});
  192. if (ST.hasV5TOps()) {
  193. getActionDefinitionsBuilder(G_CTLZ)
  194. .legalFor({s32, s32})
  195. .clampScalar(1, s32, s32)
  196. .clampScalar(0, s32, s32);
  197. getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF)
  198. .lowerFor({s32, s32})
  199. .clampScalar(1, s32, s32)
  200. .clampScalar(0, s32, s32);
  201. } else {
  202. getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF)
  203. .libcallFor({s32, s32})
  204. .clampScalar(1, s32, s32)
  205. .clampScalar(0, s32, s32);
  206. getActionDefinitionsBuilder(G_CTLZ)
  207. .lowerFor({s32, s32})
  208. .clampScalar(1, s32, s32)
  209. .clampScalar(0, s32, s32);
  210. }
  211. LegacyInfo.computeTables();
  212. verify(*ST.getInstrInfo());
  213. }
  214. void ARMLegalizerInfo::setFCmpLibcallsAEABI() {
  215. // FCMP_TRUE and FCMP_FALSE don't need libcalls, they should be
  216. // default-initialized.
  217. FCmp32Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
  218. FCmp32Libcalls[CmpInst::FCMP_OEQ] = {
  219. {RTLIB::OEQ_F32, CmpInst::BAD_ICMP_PREDICATE}};
  220. FCmp32Libcalls[CmpInst::FCMP_OGE] = {
  221. {RTLIB::OGE_F32, CmpInst::BAD_ICMP_PREDICATE}};
  222. FCmp32Libcalls[CmpInst::FCMP_OGT] = {
  223. {RTLIB::OGT_F32, CmpInst::BAD_ICMP_PREDICATE}};
  224. FCmp32Libcalls[CmpInst::FCMP_OLE] = {
  225. {RTLIB::OLE_F32, CmpInst::BAD_ICMP_PREDICATE}};
  226. FCmp32Libcalls[CmpInst::FCMP_OLT] = {
  227. {RTLIB::OLT_F32, CmpInst::BAD_ICMP_PREDICATE}};
  228. FCmp32Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::UO_F32, CmpInst::ICMP_EQ}};
  229. FCmp32Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F32, CmpInst::ICMP_EQ}};
  230. FCmp32Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F32, CmpInst::ICMP_EQ}};
  231. FCmp32Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F32, CmpInst::ICMP_EQ}};
  232. FCmp32Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F32, CmpInst::ICMP_EQ}};
  233. FCmp32Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F32, CmpInst::ICMP_EQ}};
  234. FCmp32Libcalls[CmpInst::FCMP_UNO] = {
  235. {RTLIB::UO_F32, CmpInst::BAD_ICMP_PREDICATE}};
  236. FCmp32Libcalls[CmpInst::FCMP_ONE] = {
  237. {RTLIB::OGT_F32, CmpInst::BAD_ICMP_PREDICATE},
  238. {RTLIB::OLT_F32, CmpInst::BAD_ICMP_PREDICATE}};
  239. FCmp32Libcalls[CmpInst::FCMP_UEQ] = {
  240. {RTLIB::OEQ_F32, CmpInst::BAD_ICMP_PREDICATE},
  241. {RTLIB::UO_F32, CmpInst::BAD_ICMP_PREDICATE}};
  242. FCmp64Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
  243. FCmp64Libcalls[CmpInst::FCMP_OEQ] = {
  244. {RTLIB::OEQ_F64, CmpInst::BAD_ICMP_PREDICATE}};
  245. FCmp64Libcalls[CmpInst::FCMP_OGE] = {
  246. {RTLIB::OGE_F64, CmpInst::BAD_ICMP_PREDICATE}};
  247. FCmp64Libcalls[CmpInst::FCMP_OGT] = {
  248. {RTLIB::OGT_F64, CmpInst::BAD_ICMP_PREDICATE}};
  249. FCmp64Libcalls[CmpInst::FCMP_OLE] = {
  250. {RTLIB::OLE_F64, CmpInst::BAD_ICMP_PREDICATE}};
  251. FCmp64Libcalls[CmpInst::FCMP_OLT] = {
  252. {RTLIB::OLT_F64, CmpInst::BAD_ICMP_PREDICATE}};
  253. FCmp64Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::UO_F64, CmpInst::ICMP_EQ}};
  254. FCmp64Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F64, CmpInst::ICMP_EQ}};
  255. FCmp64Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F64, CmpInst::ICMP_EQ}};
  256. FCmp64Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F64, CmpInst::ICMP_EQ}};
  257. FCmp64Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F64, CmpInst::ICMP_EQ}};
  258. FCmp64Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F64, CmpInst::ICMP_EQ}};
  259. FCmp64Libcalls[CmpInst::FCMP_UNO] = {
  260. {RTLIB::UO_F64, CmpInst::BAD_ICMP_PREDICATE}};
  261. FCmp64Libcalls[CmpInst::FCMP_ONE] = {
  262. {RTLIB::OGT_F64, CmpInst::BAD_ICMP_PREDICATE},
  263. {RTLIB::OLT_F64, CmpInst::BAD_ICMP_PREDICATE}};
  264. FCmp64Libcalls[CmpInst::FCMP_UEQ] = {
  265. {RTLIB::OEQ_F64, CmpInst::BAD_ICMP_PREDICATE},
  266. {RTLIB::UO_F64, CmpInst::BAD_ICMP_PREDICATE}};
  267. }
  268. void ARMLegalizerInfo::setFCmpLibcallsGNU() {
  269. // FCMP_TRUE and FCMP_FALSE don't need libcalls, they should be
  270. // default-initialized.
  271. FCmp32Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
  272. FCmp32Libcalls[CmpInst::FCMP_OEQ] = {{RTLIB::OEQ_F32, CmpInst::ICMP_EQ}};
  273. FCmp32Libcalls[CmpInst::FCMP_OGE] = {{RTLIB::OGE_F32, CmpInst::ICMP_SGE}};
  274. FCmp32Libcalls[CmpInst::FCMP_OGT] = {{RTLIB::OGT_F32, CmpInst::ICMP_SGT}};
  275. FCmp32Libcalls[CmpInst::FCMP_OLE] = {{RTLIB::OLE_F32, CmpInst::ICMP_SLE}};
  276. FCmp32Libcalls[CmpInst::FCMP_OLT] = {{RTLIB::OLT_F32, CmpInst::ICMP_SLT}};
  277. FCmp32Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::UO_F32, CmpInst::ICMP_EQ}};
  278. FCmp32Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F32, CmpInst::ICMP_SGE}};
  279. FCmp32Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F32, CmpInst::ICMP_SGT}};
  280. FCmp32Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F32, CmpInst::ICMP_SLE}};
  281. FCmp32Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F32, CmpInst::ICMP_SLT}};
  282. FCmp32Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F32, CmpInst::ICMP_NE}};
  283. FCmp32Libcalls[CmpInst::FCMP_UNO] = {{RTLIB::UO_F32, CmpInst::ICMP_NE}};
  284. FCmp32Libcalls[CmpInst::FCMP_ONE] = {{RTLIB::OGT_F32, CmpInst::ICMP_SGT},
  285. {RTLIB::OLT_F32, CmpInst::ICMP_SLT}};
  286. FCmp32Libcalls[CmpInst::FCMP_UEQ] = {{RTLIB::OEQ_F32, CmpInst::ICMP_EQ},
  287. {RTLIB::UO_F32, CmpInst::ICMP_NE}};
  288. FCmp64Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
  289. FCmp64Libcalls[CmpInst::FCMP_OEQ] = {{RTLIB::OEQ_F64, CmpInst::ICMP_EQ}};
  290. FCmp64Libcalls[CmpInst::FCMP_OGE] = {{RTLIB::OGE_F64, CmpInst::ICMP_SGE}};
  291. FCmp64Libcalls[CmpInst::FCMP_OGT] = {{RTLIB::OGT_F64, CmpInst::ICMP_SGT}};
  292. FCmp64Libcalls[CmpInst::FCMP_OLE] = {{RTLIB::OLE_F64, CmpInst::ICMP_SLE}};
  293. FCmp64Libcalls[CmpInst::FCMP_OLT] = {{RTLIB::OLT_F64, CmpInst::ICMP_SLT}};
  294. FCmp64Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::UO_F64, CmpInst::ICMP_EQ}};
  295. FCmp64Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F64, CmpInst::ICMP_SGE}};
  296. FCmp64Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F64, CmpInst::ICMP_SGT}};
  297. FCmp64Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F64, CmpInst::ICMP_SLE}};
  298. FCmp64Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F64, CmpInst::ICMP_SLT}};
  299. FCmp64Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F64, CmpInst::ICMP_NE}};
  300. FCmp64Libcalls[CmpInst::FCMP_UNO] = {{RTLIB::UO_F64, CmpInst::ICMP_NE}};
  301. FCmp64Libcalls[CmpInst::FCMP_ONE] = {{RTLIB::OGT_F64, CmpInst::ICMP_SGT},
  302. {RTLIB::OLT_F64, CmpInst::ICMP_SLT}};
  303. FCmp64Libcalls[CmpInst::FCMP_UEQ] = {{RTLIB::OEQ_F64, CmpInst::ICMP_EQ},
  304. {RTLIB::UO_F64, CmpInst::ICMP_NE}};
  305. }
  306. ARMLegalizerInfo::FCmpLibcallsList
  307. ARMLegalizerInfo::getFCmpLibcalls(CmpInst::Predicate Predicate,
  308. unsigned Size) const {
  309. assert(CmpInst::isFPPredicate(Predicate) && "Unsupported FCmp predicate");
  310. if (Size == 32)
  311. return FCmp32Libcalls[Predicate];
  312. if (Size == 64)
  313. return FCmp64Libcalls[Predicate];
  314. llvm_unreachable("Unsupported size for FCmp predicate");
  315. }
  316. bool ARMLegalizerInfo::legalizeCustom(LegalizerHelper &Helper,
  317. MachineInstr &MI) const {
  318. using namespace TargetOpcode;
  319. MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
  320. MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
  321. LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
  322. switch (MI.getOpcode()) {
  323. default:
  324. return false;
  325. case G_SREM:
  326. case G_UREM: {
  327. Register OriginalResult = MI.getOperand(0).getReg();
  328. auto Size = MRI.getType(OriginalResult).getSizeInBits();
  329. if (Size != 32)
  330. return false;
  331. auto Libcall =
  332. MI.getOpcode() == G_SREM ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
  333. // Our divmod libcalls return a struct containing the quotient and the
  334. // remainder. Create a new, unused register for the quotient and use the
  335. // destination of the original instruction for the remainder.
  336. Type *ArgTy = Type::getInt32Ty(Ctx);
  337. StructType *RetTy = StructType::get(Ctx, {ArgTy, ArgTy}, /* Packed */ true);
  338. Register RetRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)),
  339. OriginalResult};
  340. auto Status = createLibcall(MIRBuilder, Libcall, {RetRegs, RetTy, 0},
  341. {{MI.getOperand(1).getReg(), ArgTy, 0},
  342. {MI.getOperand(2).getReg(), ArgTy, 0}});
  343. if (Status != LegalizerHelper::Legalized)
  344. return false;
  345. break;
  346. }
  347. case G_FCMP: {
  348. assert(MRI.getType(MI.getOperand(2).getReg()) ==
  349. MRI.getType(MI.getOperand(3).getReg()) &&
  350. "Mismatched operands for G_FCMP");
  351. auto OpSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
  352. auto OriginalResult = MI.getOperand(0).getReg();
  353. auto Predicate =
  354. static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
  355. auto Libcalls = getFCmpLibcalls(Predicate, OpSize);
  356. if (Libcalls.empty()) {
  357. assert((Predicate == CmpInst::FCMP_TRUE ||
  358. Predicate == CmpInst::FCMP_FALSE) &&
  359. "Predicate needs libcalls, but none specified");
  360. MIRBuilder.buildConstant(OriginalResult,
  361. Predicate == CmpInst::FCMP_TRUE ? 1 : 0);
  362. MI.eraseFromParent();
  363. return true;
  364. }
  365. assert((OpSize == 32 || OpSize == 64) && "Unsupported operand size");
  366. auto *ArgTy = OpSize == 32 ? Type::getFloatTy(Ctx) : Type::getDoubleTy(Ctx);
  367. auto *RetTy = Type::getInt32Ty(Ctx);
  368. SmallVector<Register, 2> Results;
  369. for (auto Libcall : Libcalls) {
  370. auto LibcallResult = MRI.createGenericVirtualRegister(LLT::scalar(32));
  371. auto Status = createLibcall(MIRBuilder, Libcall.LibcallID,
  372. {LibcallResult, RetTy, 0},
  373. {{MI.getOperand(2).getReg(), ArgTy, 0},
  374. {MI.getOperand(3).getReg(), ArgTy, 0}});
  375. if (Status != LegalizerHelper::Legalized)
  376. return false;
  377. auto ProcessedResult =
  378. Libcalls.size() == 1
  379. ? OriginalResult
  380. : MRI.createGenericVirtualRegister(MRI.getType(OriginalResult));
  381. // We have a result, but we need to transform it into a proper 1-bit 0 or
  382. // 1, taking into account the different peculiarities of the values
  383. // returned by the comparison functions.
  384. CmpInst::Predicate ResultPred = Libcall.Predicate;
  385. if (ResultPred == CmpInst::BAD_ICMP_PREDICATE) {
  386. // We have a nice 0 or 1, and we just need to truncate it back to 1 bit
  387. // to keep the types consistent.
  388. MIRBuilder.buildTrunc(ProcessedResult, LibcallResult);
  389. } else {
  390. // We need to compare against 0.
  391. assert(CmpInst::isIntPredicate(ResultPred) && "Unsupported predicate");
  392. auto Zero = MIRBuilder.buildConstant(LLT::scalar(32), 0);
  393. MIRBuilder.buildICmp(ResultPred, ProcessedResult, LibcallResult, Zero);
  394. }
  395. Results.push_back(ProcessedResult);
  396. }
  397. if (Results.size() != 1) {
  398. assert(Results.size() == 2 && "Unexpected number of results");
  399. MIRBuilder.buildOr(OriginalResult, Results[0], Results[1]);
  400. }
  401. break;
  402. }
  403. case G_FCONSTANT: {
  404. // Convert to integer constants, while preserving the binary representation.
  405. auto AsInteger =
  406. MI.getOperand(1).getFPImm()->getValueAPF().bitcastToAPInt();
  407. MIRBuilder.buildConstant(MI.getOperand(0),
  408. *ConstantInt::get(Ctx, AsInteger));
  409. break;
  410. }
  411. }
  412. MI.eraseFromParent();
  413. return true;
  414. }