ARMLegalizerInfo.cpp 19 KB

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