ARMLegalizerInfo.cpp 19 KB

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