WebAssemblyFastISel.cpp 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435
  1. //===-- WebAssemblyFastISel.cpp - WebAssembly FastISel implementation -----===//
  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. ///
  9. /// \file
  10. /// This file defines the WebAssembly-specific support for the FastISel
  11. /// class. Some of the target-specific code is generated by tablegen in the file
  12. /// WebAssemblyGenFastISel.inc, which is #included here.
  13. ///
  14. /// TODO: kill flags
  15. ///
  16. //===----------------------------------------------------------------------===//
  17. #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
  18. #include "Utils/WebAssemblyTypeUtilities.h"
  19. #include "Utils/WebAssemblyUtilities.h"
  20. #include "WebAssembly.h"
  21. #include "WebAssemblyMachineFunctionInfo.h"
  22. #include "WebAssemblySubtarget.h"
  23. #include "WebAssemblyTargetMachine.h"
  24. #include "llvm/Analysis/BranchProbabilityInfo.h"
  25. #include "llvm/CodeGen/FastISel.h"
  26. #include "llvm/CodeGen/FunctionLoweringInfo.h"
  27. #include "llvm/CodeGen/MachineConstantPool.h"
  28. #include "llvm/CodeGen/MachineFrameInfo.h"
  29. #include "llvm/CodeGen/MachineInstrBuilder.h"
  30. #include "llvm/CodeGen/MachineModuleInfo.h"
  31. #include "llvm/CodeGen/MachineRegisterInfo.h"
  32. #include "llvm/IR/DataLayout.h"
  33. #include "llvm/IR/DerivedTypes.h"
  34. #include "llvm/IR/Function.h"
  35. #include "llvm/IR/GetElementPtrTypeIterator.h"
  36. #include "llvm/IR/GlobalAlias.h"
  37. #include "llvm/IR/GlobalVariable.h"
  38. #include "llvm/IR/Instructions.h"
  39. #include "llvm/IR/IntrinsicInst.h"
  40. #include "llvm/IR/Operator.h"
  41. #include "llvm/IR/PatternMatch.h"
  42. using namespace llvm;
  43. using namespace PatternMatch;
  44. #define DEBUG_TYPE "wasm-fastisel"
  45. namespace {
  46. class WebAssemblyFastISel final : public FastISel {
  47. // All possible address modes.
  48. class Address {
  49. public:
  50. using BaseKind = enum { RegBase, FrameIndexBase };
  51. private:
  52. BaseKind Kind = RegBase;
  53. union {
  54. unsigned Reg;
  55. int FI;
  56. } Base;
  57. // Whether the base has been determined yet
  58. bool IsBaseSet = false;
  59. int64_t Offset = 0;
  60. const GlobalValue *GV = nullptr;
  61. public:
  62. // Innocuous defaults for our address.
  63. Address() { Base.Reg = 0; }
  64. void setKind(BaseKind K) {
  65. assert(!isSet() && "Can't change kind with non-zero base");
  66. Kind = K;
  67. }
  68. BaseKind getKind() const { return Kind; }
  69. bool isRegBase() const { return Kind == RegBase; }
  70. bool isFIBase() const { return Kind == FrameIndexBase; }
  71. void setReg(unsigned Reg) {
  72. assert(isRegBase() && "Invalid base register access!");
  73. assert(!IsBaseSet && "Base cannot be reset");
  74. Base.Reg = Reg;
  75. IsBaseSet = true;
  76. }
  77. unsigned getReg() const {
  78. assert(isRegBase() && "Invalid base register access!");
  79. return Base.Reg;
  80. }
  81. void setFI(unsigned FI) {
  82. assert(isFIBase() && "Invalid base frame index access!");
  83. assert(!IsBaseSet && "Base cannot be reset");
  84. Base.FI = FI;
  85. IsBaseSet = true;
  86. }
  87. unsigned getFI() const {
  88. assert(isFIBase() && "Invalid base frame index access!");
  89. return Base.FI;
  90. }
  91. void setOffset(int64_t NewOffset) {
  92. assert(NewOffset >= 0 && "Offsets must be non-negative");
  93. Offset = NewOffset;
  94. }
  95. int64_t getOffset() const { return Offset; }
  96. void setGlobalValue(const GlobalValue *G) { GV = G; }
  97. const GlobalValue *getGlobalValue() const { return GV; }
  98. bool isSet() const { return IsBaseSet; }
  99. };
  100. /// Keep a pointer to the WebAssemblySubtarget around so that we can make the
  101. /// right decision when generating code for different targets.
  102. const WebAssemblySubtarget *Subtarget;
  103. LLVMContext *Context;
  104. private:
  105. // Utility helper routines
  106. MVT::SimpleValueType getSimpleType(Type *Ty) {
  107. EVT VT = TLI.getValueType(DL, Ty, /*AllowUnknown=*/true);
  108. return VT.isSimple() ? VT.getSimpleVT().SimpleTy
  109. : MVT::INVALID_SIMPLE_VALUE_TYPE;
  110. }
  111. MVT::SimpleValueType getLegalType(MVT::SimpleValueType VT) {
  112. switch (VT) {
  113. case MVT::i1:
  114. case MVT::i8:
  115. case MVT::i16:
  116. return MVT::i32;
  117. case MVT::i32:
  118. case MVT::i64:
  119. case MVT::f32:
  120. case MVT::f64:
  121. return VT;
  122. case MVT::funcref:
  123. case MVT::externref:
  124. if (Subtarget->hasReferenceTypes())
  125. return VT;
  126. break;
  127. case MVT::f16:
  128. return MVT::f32;
  129. case MVT::v16i8:
  130. case MVT::v8i16:
  131. case MVT::v4i32:
  132. case MVT::v4f32:
  133. case MVT::v2i64:
  134. case MVT::v2f64:
  135. if (Subtarget->hasSIMD128())
  136. return VT;
  137. break;
  138. default:
  139. break;
  140. }
  141. return MVT::INVALID_SIMPLE_VALUE_TYPE;
  142. }
  143. bool computeAddress(const Value *Obj, Address &Addr);
  144. void materializeLoadStoreOperands(Address &Addr);
  145. void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB,
  146. MachineMemOperand *MMO);
  147. unsigned maskI1Value(unsigned Reg, const Value *V);
  148. unsigned getRegForI1Value(const Value *V, const BasicBlock *BB, bool &Not);
  149. unsigned zeroExtendToI32(unsigned Reg, const Value *V,
  150. MVT::SimpleValueType From);
  151. unsigned signExtendToI32(unsigned Reg, const Value *V,
  152. MVT::SimpleValueType From);
  153. unsigned zeroExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
  154. MVT::SimpleValueType To);
  155. unsigned signExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
  156. MVT::SimpleValueType To);
  157. unsigned getRegForUnsignedValue(const Value *V);
  158. unsigned getRegForSignedValue(const Value *V);
  159. unsigned getRegForPromotedValue(const Value *V, bool IsSigned);
  160. unsigned notValue(unsigned Reg);
  161. unsigned copyValue(unsigned Reg);
  162. // Backend specific FastISel code.
  163. unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
  164. unsigned fastMaterializeConstant(const Constant *C) override;
  165. bool fastLowerArguments() override;
  166. // Selection routines.
  167. bool selectCall(const Instruction *I);
  168. bool selectSelect(const Instruction *I);
  169. bool selectTrunc(const Instruction *I);
  170. bool selectZExt(const Instruction *I);
  171. bool selectSExt(const Instruction *I);
  172. bool selectICmp(const Instruction *I);
  173. bool selectFCmp(const Instruction *I);
  174. bool selectBitCast(const Instruction *I);
  175. bool selectLoad(const Instruction *I);
  176. bool selectStore(const Instruction *I);
  177. bool selectBr(const Instruction *I);
  178. bool selectRet(const Instruction *I);
  179. bool selectUnreachable(const Instruction *I);
  180. public:
  181. // Backend specific FastISel code.
  182. WebAssemblyFastISel(FunctionLoweringInfo &FuncInfo,
  183. const TargetLibraryInfo *LibInfo)
  184. : FastISel(FuncInfo, LibInfo, /*SkipTargetIndependentISel=*/true) {
  185. Subtarget = &FuncInfo.MF->getSubtarget<WebAssemblySubtarget>();
  186. Context = &FuncInfo.Fn->getContext();
  187. }
  188. bool fastSelectInstruction(const Instruction *I) override;
  189. #include "WebAssemblyGenFastISel.inc"
  190. };
  191. } // end anonymous namespace
  192. bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) {
  193. const User *U = nullptr;
  194. unsigned Opcode = Instruction::UserOp1;
  195. if (const auto *I = dyn_cast<Instruction>(Obj)) {
  196. // Don't walk into other basic blocks unless the object is an alloca from
  197. // another block, otherwise it may not have a virtual register assigned.
  198. if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
  199. FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
  200. Opcode = I->getOpcode();
  201. U = I;
  202. }
  203. } else if (const auto *C = dyn_cast<ConstantExpr>(Obj)) {
  204. Opcode = C->getOpcode();
  205. U = C;
  206. }
  207. if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))
  208. if (Ty->getAddressSpace() > 255)
  209. // Fast instruction selection doesn't support the special
  210. // address spaces.
  211. return false;
  212. if (const auto *GV = dyn_cast<GlobalValue>(Obj)) {
  213. if (TLI.isPositionIndependent())
  214. return false;
  215. if (Addr.getGlobalValue())
  216. return false;
  217. if (GV->isThreadLocal())
  218. return false;
  219. Addr.setGlobalValue(GV);
  220. return true;
  221. }
  222. switch (Opcode) {
  223. default:
  224. break;
  225. case Instruction::BitCast: {
  226. // Look through bitcasts.
  227. return computeAddress(U->getOperand(0), Addr);
  228. }
  229. case Instruction::IntToPtr: {
  230. // Look past no-op inttoptrs.
  231. if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
  232. TLI.getPointerTy(DL))
  233. return computeAddress(U->getOperand(0), Addr);
  234. break;
  235. }
  236. case Instruction::PtrToInt: {
  237. // Look past no-op ptrtoints.
  238. if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
  239. return computeAddress(U->getOperand(0), Addr);
  240. break;
  241. }
  242. case Instruction::GetElementPtr: {
  243. Address SavedAddr = Addr;
  244. uint64_t TmpOffset = Addr.getOffset();
  245. // Non-inbounds geps can wrap; wasm's offsets can't.
  246. if (!cast<GEPOperator>(U)->isInBounds())
  247. goto unsupported_gep;
  248. // Iterate through the GEP folding the constants into offsets where
  249. // we can.
  250. for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);
  251. GTI != E; ++GTI) {
  252. const Value *Op = GTI.getOperand();
  253. if (StructType *STy = GTI.getStructTypeOrNull()) {
  254. const StructLayout *SL = DL.getStructLayout(STy);
  255. unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
  256. TmpOffset += SL->getElementOffset(Idx);
  257. } else {
  258. uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
  259. for (;;) {
  260. if (const auto *CI = dyn_cast<ConstantInt>(Op)) {
  261. // Constant-offset addressing.
  262. TmpOffset += CI->getSExtValue() * S;
  263. break;
  264. }
  265. if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
  266. // An unscaled add of a register. Set it as the new base.
  267. Register Reg = getRegForValue(Op);
  268. if (Reg == 0)
  269. return false;
  270. Addr.setReg(Reg);
  271. break;
  272. }
  273. if (canFoldAddIntoGEP(U, Op)) {
  274. // A compatible add with a constant operand. Fold the constant.
  275. auto *CI = cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
  276. TmpOffset += CI->getSExtValue() * S;
  277. // Iterate on the other operand.
  278. Op = cast<AddOperator>(Op)->getOperand(0);
  279. continue;
  280. }
  281. // Unsupported
  282. goto unsupported_gep;
  283. }
  284. }
  285. }
  286. // Don't fold in negative offsets.
  287. if (int64_t(TmpOffset) >= 0) {
  288. // Try to grab the base operand now.
  289. Addr.setOffset(TmpOffset);
  290. if (computeAddress(U->getOperand(0), Addr))
  291. return true;
  292. }
  293. // We failed, restore everything and try the other options.
  294. Addr = SavedAddr;
  295. unsupported_gep:
  296. break;
  297. }
  298. case Instruction::Alloca: {
  299. const auto *AI = cast<AllocaInst>(Obj);
  300. DenseMap<const AllocaInst *, int>::iterator SI =
  301. FuncInfo.StaticAllocaMap.find(AI);
  302. if (SI != FuncInfo.StaticAllocaMap.end()) {
  303. if (Addr.isSet()) {
  304. return false;
  305. }
  306. Addr.setKind(Address::FrameIndexBase);
  307. Addr.setFI(SI->second);
  308. return true;
  309. }
  310. break;
  311. }
  312. case Instruction::Add: {
  313. // Adds of constants are common and easy enough.
  314. const Value *LHS = U->getOperand(0);
  315. const Value *RHS = U->getOperand(1);
  316. if (isa<ConstantInt>(LHS))
  317. std::swap(LHS, RHS);
  318. if (const auto *CI = dyn_cast<ConstantInt>(RHS)) {
  319. uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
  320. if (int64_t(TmpOffset) >= 0) {
  321. Addr.setOffset(TmpOffset);
  322. return computeAddress(LHS, Addr);
  323. }
  324. }
  325. Address Backup = Addr;
  326. if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr))
  327. return true;
  328. Addr = Backup;
  329. break;
  330. }
  331. case Instruction::Sub: {
  332. // Subs of constants are common and easy enough.
  333. const Value *LHS = U->getOperand(0);
  334. const Value *RHS = U->getOperand(1);
  335. if (const auto *CI = dyn_cast<ConstantInt>(RHS)) {
  336. int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
  337. if (TmpOffset >= 0) {
  338. Addr.setOffset(TmpOffset);
  339. return computeAddress(LHS, Addr);
  340. }
  341. }
  342. break;
  343. }
  344. }
  345. if (Addr.isSet()) {
  346. return false;
  347. }
  348. Register Reg = getRegForValue(Obj);
  349. if (Reg == 0)
  350. return false;
  351. Addr.setReg(Reg);
  352. return Addr.getReg() != 0;
  353. }
  354. void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {
  355. if (Addr.isRegBase()) {
  356. unsigned Reg = Addr.getReg();
  357. if (Reg == 0) {
  358. Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
  359. : &WebAssembly::I32RegClass);
  360. unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
  361. : WebAssembly::CONST_I32;
  362. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), Reg)
  363. .addImm(0);
  364. Addr.setReg(Reg);
  365. }
  366. }
  367. }
  368. void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr,
  369. const MachineInstrBuilder &MIB,
  370. MachineMemOperand *MMO) {
  371. // Set the alignment operand (this is rewritten in SetP2AlignOperands).
  372. // TODO: Disable SetP2AlignOperands for FastISel and just do it here.
  373. MIB.addImm(0);
  374. if (const GlobalValue *GV = Addr.getGlobalValue())
  375. MIB.addGlobalAddress(GV, Addr.getOffset());
  376. else
  377. MIB.addImm(Addr.getOffset());
  378. if (Addr.isRegBase())
  379. MIB.addReg(Addr.getReg());
  380. else
  381. MIB.addFrameIndex(Addr.getFI());
  382. MIB.addMemOperand(MMO);
  383. }
  384. unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) {
  385. return zeroExtendToI32(Reg, V, MVT::i1);
  386. }
  387. unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V,
  388. const BasicBlock *BB,
  389. bool &Not) {
  390. if (const auto *ICmp = dyn_cast<ICmpInst>(V))
  391. if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
  392. if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32) &&
  393. ICmp->getParent() == BB) {
  394. Not = ICmp->isTrueWhenEqual();
  395. return getRegForValue(ICmp->getOperand(0));
  396. }
  397. Not = false;
  398. Register Reg = getRegForValue(V);
  399. if (Reg == 0)
  400. return 0;
  401. return maskI1Value(Reg, V);
  402. }
  403. unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
  404. MVT::SimpleValueType From) {
  405. if (Reg == 0)
  406. return 0;
  407. switch (From) {
  408. case MVT::i1:
  409. // If the value is naturally an i1, we don't need to mask it. We only know
  410. // if a value is naturally an i1 if it is definitely lowered by FastISel,
  411. // not a DAG ISel fallback.
  412. if (V != nullptr && isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr())
  413. return copyValue(Reg);
  414. break;
  415. case MVT::i8:
  416. case MVT::i16:
  417. break;
  418. case MVT::i32:
  419. return copyValue(Reg);
  420. default:
  421. return 0;
  422. }
  423. Register Imm = createResultReg(&WebAssembly::I32RegClass);
  424. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
  425. TII.get(WebAssembly::CONST_I32), Imm)
  426. .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
  427. Register Result = createResultReg(&WebAssembly::I32RegClass);
  428. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
  429. TII.get(WebAssembly::AND_I32), Result)
  430. .addReg(Reg)
  431. .addReg(Imm);
  432. return Result;
  433. }
  434. unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,
  435. MVT::SimpleValueType From) {
  436. if (Reg == 0)
  437. return 0;
  438. switch (From) {
  439. case MVT::i1:
  440. case MVT::i8:
  441. case MVT::i16:
  442. break;
  443. case MVT::i32:
  444. return copyValue(Reg);
  445. default:
  446. return 0;
  447. }
  448. Register Imm = createResultReg(&WebAssembly::I32RegClass);
  449. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
  450. TII.get(WebAssembly::CONST_I32), Imm)
  451. .addImm(32 - MVT(From).getSizeInBits());
  452. Register Left = createResultReg(&WebAssembly::I32RegClass);
  453. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
  454. TII.get(WebAssembly::SHL_I32), Left)
  455. .addReg(Reg)
  456. .addReg(Imm);
  457. Register Right = createResultReg(&WebAssembly::I32RegClass);
  458. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
  459. TII.get(WebAssembly::SHR_S_I32), Right)
  460. .addReg(Left)
  461. .addReg(Imm);
  462. return Right;
  463. }
  464. unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V,
  465. MVT::SimpleValueType From,
  466. MVT::SimpleValueType To) {
  467. if (To == MVT::i64) {
  468. if (From == MVT::i64)
  469. return copyValue(Reg);
  470. Reg = zeroExtendToI32(Reg, V, From);
  471. Register Result = createResultReg(&WebAssembly::I64RegClass);
  472. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
  473. TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
  474. .addReg(Reg);
  475. return Result;
  476. }
  477. if (To == MVT::i32)
  478. return zeroExtendToI32(Reg, V, From);
  479. return 0;
  480. }
  481. unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,
  482. MVT::SimpleValueType From,
  483. MVT::SimpleValueType To) {
  484. if (To == MVT::i64) {
  485. if (From == MVT::i64)
  486. return copyValue(Reg);
  487. Reg = signExtendToI32(Reg, V, From);
  488. Register Result = createResultReg(&WebAssembly::I64RegClass);
  489. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
  490. TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
  491. .addReg(Reg);
  492. return Result;
  493. }
  494. if (To == MVT::i32)
  495. return signExtendToI32(Reg, V, From);
  496. return 0;
  497. }
  498. unsigned WebAssemblyFastISel::getRegForUnsignedValue(const Value *V) {
  499. MVT::SimpleValueType From = getSimpleType(V->getType());
  500. MVT::SimpleValueType To = getLegalType(From);
  501. Register VReg = getRegForValue(V);
  502. if (VReg == 0)
  503. return 0;
  504. return zeroExtend(VReg, V, From, To);
  505. }
  506. unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) {
  507. MVT::SimpleValueType From = getSimpleType(V->getType());
  508. MVT::SimpleValueType To = getLegalType(From);
  509. Register VReg = getRegForValue(V);
  510. if (VReg == 0)
  511. return 0;
  512. return signExtend(VReg, V, From, To);
  513. }
  514. unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V,
  515. bool IsSigned) {
  516. return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(V);
  517. }
  518. unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
  519. assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
  520. Register NotReg = createResultReg(&WebAssembly::I32RegClass);
  521. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
  522. TII.get(WebAssembly::EQZ_I32), NotReg)
  523. .addReg(Reg);
  524. return NotReg;
  525. }
  526. unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
  527. Register ResultReg = createResultReg(MRI.getRegClass(Reg));
  528. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(WebAssembly::COPY),
  529. ResultReg)
  530. .addReg(Reg);
  531. return ResultReg;
  532. }
  533. unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
  534. DenseMap<const AllocaInst *, int>::iterator SI =
  535. FuncInfo.StaticAllocaMap.find(AI);
  536. if (SI != FuncInfo.StaticAllocaMap.end()) {
  537. Register ResultReg =
  538. createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
  539. : &WebAssembly::I32RegClass);
  540. unsigned Opc =
  541. Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
  542. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)
  543. .addFrameIndex(SI->second);
  544. return ResultReg;
  545. }
  546. return 0;
  547. }
  548. unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
  549. if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
  550. if (TLI.isPositionIndependent())
  551. return 0;
  552. if (GV->isThreadLocal())
  553. return 0;
  554. Register ResultReg =
  555. createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
  556. : &WebAssembly::I32RegClass);
  557. unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
  558. : WebAssembly::CONST_I32;
  559. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)
  560. .addGlobalAddress(GV);
  561. return ResultReg;
  562. }
  563. // Let target-independent code handle it.
  564. return 0;
  565. }
  566. bool WebAssemblyFastISel::fastLowerArguments() {
  567. if (!FuncInfo.CanLowerReturn)
  568. return false;
  569. const Function *F = FuncInfo.Fn;
  570. if (F->isVarArg())
  571. return false;
  572. if (FuncInfo.Fn->getCallingConv() == CallingConv::Swift)
  573. return false;
  574. unsigned I = 0;
  575. for (auto const &Arg : F->args()) {
  576. const AttributeList &Attrs = F->getAttributes();
  577. if (Attrs.hasParamAttr(I, Attribute::ByVal) ||
  578. Attrs.hasParamAttr(I, Attribute::SwiftSelf) ||
  579. Attrs.hasParamAttr(I, Attribute::SwiftError) ||
  580. Attrs.hasParamAttr(I, Attribute::InAlloca) ||
  581. Attrs.hasParamAttr(I, Attribute::Nest))
  582. return false;
  583. Type *ArgTy = Arg.getType();
  584. if (ArgTy->isStructTy() || ArgTy->isArrayTy())
  585. return false;
  586. if (!Subtarget->hasSIMD128() && ArgTy->isVectorTy())
  587. return false;
  588. unsigned Opc;
  589. const TargetRegisterClass *RC;
  590. switch (getSimpleType(ArgTy)) {
  591. case MVT::i1:
  592. case MVT::i8:
  593. case MVT::i16:
  594. case MVT::i32:
  595. Opc = WebAssembly::ARGUMENT_i32;
  596. RC = &WebAssembly::I32RegClass;
  597. break;
  598. case MVT::i64:
  599. Opc = WebAssembly::ARGUMENT_i64;
  600. RC = &WebAssembly::I64RegClass;
  601. break;
  602. case MVT::f32:
  603. Opc = WebAssembly::ARGUMENT_f32;
  604. RC = &WebAssembly::F32RegClass;
  605. break;
  606. case MVT::f64:
  607. Opc = WebAssembly::ARGUMENT_f64;
  608. RC = &WebAssembly::F64RegClass;
  609. break;
  610. case MVT::v16i8:
  611. Opc = WebAssembly::ARGUMENT_v16i8;
  612. RC = &WebAssembly::V128RegClass;
  613. break;
  614. case MVT::v8i16:
  615. Opc = WebAssembly::ARGUMENT_v8i16;
  616. RC = &WebAssembly::V128RegClass;
  617. break;
  618. case MVT::v4i32:
  619. Opc = WebAssembly::ARGUMENT_v4i32;
  620. RC = &WebAssembly::V128RegClass;
  621. break;
  622. case MVT::v2i64:
  623. Opc = WebAssembly::ARGUMENT_v2i64;
  624. RC = &WebAssembly::V128RegClass;
  625. break;
  626. case MVT::v4f32:
  627. Opc = WebAssembly::ARGUMENT_v4f32;
  628. RC = &WebAssembly::V128RegClass;
  629. break;
  630. case MVT::v2f64:
  631. Opc = WebAssembly::ARGUMENT_v2f64;
  632. RC = &WebAssembly::V128RegClass;
  633. break;
  634. case MVT::funcref:
  635. Opc = WebAssembly::ARGUMENT_funcref;
  636. RC = &WebAssembly::FUNCREFRegClass;
  637. break;
  638. case MVT::externref:
  639. Opc = WebAssembly::ARGUMENT_externref;
  640. RC = &WebAssembly::EXTERNREFRegClass;
  641. break;
  642. default:
  643. return false;
  644. }
  645. Register ResultReg = createResultReg(RC);
  646. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)
  647. .addImm(I);
  648. updateValueMap(&Arg, ResultReg);
  649. ++I;
  650. }
  651. MRI.addLiveIn(WebAssembly::ARGUMENTS);
  652. auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
  653. for (auto const &Arg : F->args()) {
  654. MVT::SimpleValueType ArgTy = getLegalType(getSimpleType(Arg.getType()));
  655. if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
  656. MFI->clearParamsAndResults();
  657. return false;
  658. }
  659. MFI->addParam(ArgTy);
  660. }
  661. if (!F->getReturnType()->isVoidTy()) {
  662. MVT::SimpleValueType RetTy =
  663. getLegalType(getSimpleType(F->getReturnType()));
  664. if (RetTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
  665. MFI->clearParamsAndResults();
  666. return false;
  667. }
  668. MFI->addResult(RetTy);
  669. }
  670. return true;
  671. }
  672. bool WebAssemblyFastISel::selectCall(const Instruction *I) {
  673. const auto *Call = cast<CallInst>(I);
  674. // TODO: Support tail calls in FastISel
  675. if (Call->isMustTailCall() || Call->isInlineAsm() ||
  676. Call->getFunctionType()->isVarArg())
  677. return false;
  678. Function *Func = Call->getCalledFunction();
  679. if (Func && Func->isIntrinsic())
  680. return false;
  681. if (Call->getCallingConv() == CallingConv::Swift)
  682. return false;
  683. bool IsDirect = Func != nullptr;
  684. if (!IsDirect && isa<ConstantExpr>(Call->getCalledOperand()))
  685. return false;
  686. FunctionType *FuncTy = Call->getFunctionType();
  687. unsigned Opc = IsDirect ? WebAssembly::CALL : WebAssembly::CALL_INDIRECT;
  688. bool IsVoid = FuncTy->getReturnType()->isVoidTy();
  689. unsigned ResultReg;
  690. if (!IsVoid) {
  691. if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy())
  692. return false;
  693. MVT::SimpleValueType RetTy = getSimpleType(Call->getType());
  694. switch (RetTy) {
  695. case MVT::i1:
  696. case MVT::i8:
  697. case MVT::i16:
  698. case MVT::i32:
  699. ResultReg = createResultReg(&WebAssembly::I32RegClass);
  700. break;
  701. case MVT::i64:
  702. ResultReg = createResultReg(&WebAssembly::I64RegClass);
  703. break;
  704. case MVT::f32:
  705. ResultReg = createResultReg(&WebAssembly::F32RegClass);
  706. break;
  707. case MVT::f64:
  708. ResultReg = createResultReg(&WebAssembly::F64RegClass);
  709. break;
  710. case MVT::v16i8:
  711. ResultReg = createResultReg(&WebAssembly::V128RegClass);
  712. break;
  713. case MVT::v8i16:
  714. ResultReg = createResultReg(&WebAssembly::V128RegClass);
  715. break;
  716. case MVT::v4i32:
  717. ResultReg = createResultReg(&WebAssembly::V128RegClass);
  718. break;
  719. case MVT::v2i64:
  720. ResultReg = createResultReg(&WebAssembly::V128RegClass);
  721. break;
  722. case MVT::v4f32:
  723. ResultReg = createResultReg(&WebAssembly::V128RegClass);
  724. break;
  725. case MVT::v2f64:
  726. ResultReg = createResultReg(&WebAssembly::V128RegClass);
  727. break;
  728. case MVT::funcref:
  729. ResultReg = createResultReg(&WebAssembly::FUNCREFRegClass);
  730. break;
  731. case MVT::externref:
  732. ResultReg = createResultReg(&WebAssembly::EXTERNREFRegClass);
  733. break;
  734. default:
  735. return false;
  736. }
  737. }
  738. SmallVector<unsigned, 8> Args;
  739. for (unsigned I = 0, E = Call->arg_size(); I < E; ++I) {
  740. Value *V = Call->getArgOperand(I);
  741. MVT::SimpleValueType ArgTy = getSimpleType(V->getType());
  742. if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE)
  743. return false;
  744. const AttributeList &Attrs = Call->getAttributes();
  745. if (Attrs.hasParamAttr(I, Attribute::ByVal) ||
  746. Attrs.hasParamAttr(I, Attribute::SwiftSelf) ||
  747. Attrs.hasParamAttr(I, Attribute::SwiftError) ||
  748. Attrs.hasParamAttr(I, Attribute::InAlloca) ||
  749. Attrs.hasParamAttr(I, Attribute::Nest))
  750. return false;
  751. unsigned Reg;
  752. if (Attrs.hasParamAttr(I, Attribute::SExt))
  753. Reg = getRegForSignedValue(V);
  754. else if (Attrs.hasParamAttr(I, Attribute::ZExt))
  755. Reg = getRegForUnsignedValue(V);
  756. else
  757. Reg = getRegForValue(V);
  758. if (Reg == 0)
  759. return false;
  760. Args.push_back(Reg);
  761. }
  762. unsigned CalleeReg = 0;
  763. if (!IsDirect) {
  764. CalleeReg = getRegForValue(Call->getCalledOperand());
  765. if (!CalleeReg)
  766. return false;
  767. }
  768. auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc));
  769. if (!IsVoid)
  770. MIB.addReg(ResultReg, RegState::Define);
  771. if (IsDirect) {
  772. MIB.addGlobalAddress(Func);
  773. } else {
  774. // Placeholder for the type index.
  775. MIB.addImm(0);
  776. // The table into which this call_indirect indexes.
  777. MCSymbolWasm *Table = WebAssembly::getOrCreateFunctionTableSymbol(
  778. MF->getMMI().getContext(), Subtarget);
  779. if (Subtarget->hasReferenceTypes()) {
  780. MIB.addSym(Table);
  781. } else {
  782. // Otherwise for the MVP there is at most one table whose number is 0, but
  783. // we can't write a table symbol or issue relocations. Instead we just
  784. // ensure the table is live.
  785. Table->setNoStrip();
  786. MIB.addImm(0);
  787. }
  788. // See if we must truncate the function pointer.
  789. // CALL_INDIRECT takes an i32, but in wasm64 we represent function pointers
  790. // as 64-bit for uniformity with other pointer types.
  791. // See also: WebAssemblyISelLowering.cpp: LowerCallResults
  792. if (Subtarget->hasAddr64()) {
  793. auto Wrap = BuildMI(*FuncInfo.MBB, std::prev(FuncInfo.InsertPt), MIMD,
  794. TII.get(WebAssembly::I32_WRAP_I64));
  795. Register Reg32 = createResultReg(&WebAssembly::I32RegClass);
  796. Wrap.addReg(Reg32, RegState::Define);
  797. Wrap.addReg(CalleeReg);
  798. CalleeReg = Reg32;
  799. }
  800. }
  801. for (unsigned ArgReg : Args)
  802. MIB.addReg(ArgReg);
  803. if (!IsDirect)
  804. MIB.addReg(CalleeReg);
  805. if (!IsVoid)
  806. updateValueMap(Call, ResultReg);
  807. return true;
  808. }
  809. bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
  810. const auto *Select = cast<SelectInst>(I);
  811. bool Not;
  812. unsigned CondReg =
  813. getRegForI1Value(Select->getCondition(), I->getParent(), Not);
  814. if (CondReg == 0)
  815. return false;
  816. Register TrueReg = getRegForValue(Select->getTrueValue());
  817. if (TrueReg == 0)
  818. return false;
  819. Register FalseReg = getRegForValue(Select->getFalseValue());
  820. if (FalseReg == 0)
  821. return false;
  822. if (Not)
  823. std::swap(TrueReg, FalseReg);
  824. unsigned Opc;
  825. const TargetRegisterClass *RC;
  826. switch (getSimpleType(Select->getType())) {
  827. case MVT::i1:
  828. case MVT::i8:
  829. case MVT::i16:
  830. case MVT::i32:
  831. Opc = WebAssembly::SELECT_I32;
  832. RC = &WebAssembly::I32RegClass;
  833. break;
  834. case MVT::i64:
  835. Opc = WebAssembly::SELECT_I64;
  836. RC = &WebAssembly::I64RegClass;
  837. break;
  838. case MVT::f32:
  839. Opc = WebAssembly::SELECT_F32;
  840. RC = &WebAssembly::F32RegClass;
  841. break;
  842. case MVT::f64:
  843. Opc = WebAssembly::SELECT_F64;
  844. RC = &WebAssembly::F64RegClass;
  845. break;
  846. case MVT::funcref:
  847. Opc = WebAssembly::SELECT_FUNCREF;
  848. RC = &WebAssembly::FUNCREFRegClass;
  849. break;
  850. case MVT::externref:
  851. Opc = WebAssembly::SELECT_EXTERNREF;
  852. RC = &WebAssembly::EXTERNREFRegClass;
  853. break;
  854. default:
  855. return false;
  856. }
  857. Register ResultReg = createResultReg(RC);
  858. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)
  859. .addReg(TrueReg)
  860. .addReg(FalseReg)
  861. .addReg(CondReg);
  862. updateValueMap(Select, ResultReg);
  863. return true;
  864. }
  865. bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {
  866. const auto *Trunc = cast<TruncInst>(I);
  867. Register Reg = getRegForValue(Trunc->getOperand(0));
  868. if (Reg == 0)
  869. return false;
  870. if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
  871. Register Result = createResultReg(&WebAssembly::I32RegClass);
  872. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
  873. TII.get(WebAssembly::I32_WRAP_I64), Result)
  874. .addReg(Reg);
  875. Reg = Result;
  876. }
  877. updateValueMap(Trunc, Reg);
  878. return true;
  879. }
  880. bool WebAssemblyFastISel::selectZExt(const Instruction *I) {
  881. const auto *ZExt = cast<ZExtInst>(I);
  882. const Value *Op = ZExt->getOperand(0);
  883. MVT::SimpleValueType From = getSimpleType(Op->getType());
  884. MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType()));
  885. Register In = getRegForValue(Op);
  886. if (In == 0)
  887. return false;
  888. unsigned Reg = zeroExtend(In, Op, From, To);
  889. if (Reg == 0)
  890. return false;
  891. updateValueMap(ZExt, Reg);
  892. return true;
  893. }
  894. bool WebAssemblyFastISel::selectSExt(const Instruction *I) {
  895. const auto *SExt = cast<SExtInst>(I);
  896. const Value *Op = SExt->getOperand(0);
  897. MVT::SimpleValueType From = getSimpleType(Op->getType());
  898. MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType()));
  899. Register In = getRegForValue(Op);
  900. if (In == 0)
  901. return false;
  902. unsigned Reg = signExtend(In, Op, From, To);
  903. if (Reg == 0)
  904. return false;
  905. updateValueMap(SExt, Reg);
  906. return true;
  907. }
  908. bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
  909. const auto *ICmp = cast<ICmpInst>(I);
  910. bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
  911. unsigned Opc;
  912. bool IsSigned = false;
  913. switch (ICmp->getPredicate()) {
  914. case ICmpInst::ICMP_EQ:
  915. Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
  916. break;
  917. case ICmpInst::ICMP_NE:
  918. Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
  919. break;
  920. case ICmpInst::ICMP_UGT:
  921. Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
  922. break;
  923. case ICmpInst::ICMP_UGE:
  924. Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
  925. break;
  926. case ICmpInst::ICMP_ULT:
  927. Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
  928. break;
  929. case ICmpInst::ICMP_ULE:
  930. Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
  931. break;
  932. case ICmpInst::ICMP_SGT:
  933. Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
  934. IsSigned = true;
  935. break;
  936. case ICmpInst::ICMP_SGE:
  937. Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
  938. IsSigned = true;
  939. break;
  940. case ICmpInst::ICMP_SLT:
  941. Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
  942. IsSigned = true;
  943. break;
  944. case ICmpInst::ICMP_SLE:
  945. Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
  946. IsSigned = true;
  947. break;
  948. default:
  949. return false;
  950. }
  951. unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned);
  952. if (LHS == 0)
  953. return false;
  954. unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned);
  955. if (RHS == 0)
  956. return false;
  957. Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
  958. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)
  959. .addReg(LHS)
  960. .addReg(RHS);
  961. updateValueMap(ICmp, ResultReg);
  962. return true;
  963. }
  964. bool WebAssemblyFastISel::selectFCmp(const Instruction *I) {
  965. const auto *FCmp = cast<FCmpInst>(I);
  966. Register LHS = getRegForValue(FCmp->getOperand(0));
  967. if (LHS == 0)
  968. return false;
  969. Register RHS = getRegForValue(FCmp->getOperand(1));
  970. if (RHS == 0)
  971. return false;
  972. bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
  973. unsigned Opc;
  974. bool Not = false;
  975. switch (FCmp->getPredicate()) {
  976. case FCmpInst::FCMP_OEQ:
  977. Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
  978. break;
  979. case FCmpInst::FCMP_UNE:
  980. Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
  981. break;
  982. case FCmpInst::FCMP_OGT:
  983. Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
  984. break;
  985. case FCmpInst::FCMP_OGE:
  986. Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
  987. break;
  988. case FCmpInst::FCMP_OLT:
  989. Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
  990. break;
  991. case FCmpInst::FCMP_OLE:
  992. Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
  993. break;
  994. case FCmpInst::FCMP_UGT:
  995. Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
  996. Not = true;
  997. break;
  998. case FCmpInst::FCMP_UGE:
  999. Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
  1000. Not = true;
  1001. break;
  1002. case FCmpInst::FCMP_ULT:
  1003. Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
  1004. Not = true;
  1005. break;
  1006. case FCmpInst::FCMP_ULE:
  1007. Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
  1008. Not = true;
  1009. break;
  1010. default:
  1011. return false;
  1012. }
  1013. Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
  1014. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)
  1015. .addReg(LHS)
  1016. .addReg(RHS);
  1017. if (Not)
  1018. ResultReg = notValue(ResultReg);
  1019. updateValueMap(FCmp, ResultReg);
  1020. return true;
  1021. }
  1022. bool WebAssemblyFastISel::selectBitCast(const Instruction *I) {
  1023. // Target-independent code can handle this, except it doesn't set the dead
  1024. // flag on the ARGUMENTS clobber, so we have to do that manually in order
  1025. // to satisfy code that expects this of isBitcast() instructions.
  1026. EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType());
  1027. EVT RetVT = TLI.getValueType(DL, I->getType());
  1028. if (!VT.isSimple() || !RetVT.isSimple())
  1029. return false;
  1030. Register In = getRegForValue(I->getOperand(0));
  1031. if (In == 0)
  1032. return false;
  1033. if (VT == RetVT) {
  1034. // No-op bitcast.
  1035. updateValueMap(I, In);
  1036. return true;
  1037. }
  1038. Register Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(),
  1039. In);
  1040. if (!Reg)
  1041. return false;
  1042. MachineBasicBlock::iterator Iter = FuncInfo.InsertPt;
  1043. --Iter;
  1044. assert(Iter->isBitcast());
  1045. Iter->setPhysRegsDeadExcept(ArrayRef<Register>(), TRI);
  1046. updateValueMap(I, Reg);
  1047. return true;
  1048. }
  1049. bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
  1050. const auto *Load = cast<LoadInst>(I);
  1051. if (Load->isAtomic())
  1052. return false;
  1053. if (!WebAssembly::isDefaultAddressSpace(Load->getPointerAddressSpace()))
  1054. return false;
  1055. if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy())
  1056. return false;
  1057. Address Addr;
  1058. if (!computeAddress(Load->getPointerOperand(), Addr))
  1059. return false;
  1060. // TODO: Fold a following sign-/zero-extend into the load instruction.
  1061. unsigned Opc;
  1062. const TargetRegisterClass *RC;
  1063. bool A64 = Subtarget->hasAddr64();
  1064. switch (getSimpleType(Load->getType())) {
  1065. case MVT::i1:
  1066. case MVT::i8:
  1067. Opc = A64 ? WebAssembly::LOAD8_U_I32_A64 : WebAssembly::LOAD8_U_I32_A32;
  1068. RC = &WebAssembly::I32RegClass;
  1069. break;
  1070. case MVT::i16:
  1071. Opc = A64 ? WebAssembly::LOAD16_U_I32_A64 : WebAssembly::LOAD16_U_I32_A32;
  1072. RC = &WebAssembly::I32RegClass;
  1073. break;
  1074. case MVT::i32:
  1075. Opc = A64 ? WebAssembly::LOAD_I32_A64 : WebAssembly::LOAD_I32_A32;
  1076. RC = &WebAssembly::I32RegClass;
  1077. break;
  1078. case MVT::i64:
  1079. Opc = A64 ? WebAssembly::LOAD_I64_A64 : WebAssembly::LOAD_I64_A32;
  1080. RC = &WebAssembly::I64RegClass;
  1081. break;
  1082. case MVT::f32:
  1083. Opc = A64 ? WebAssembly::LOAD_F32_A64 : WebAssembly::LOAD_F32_A32;
  1084. RC = &WebAssembly::F32RegClass;
  1085. break;
  1086. case MVT::f64:
  1087. Opc = A64 ? WebAssembly::LOAD_F64_A64 : WebAssembly::LOAD_F64_A32;
  1088. RC = &WebAssembly::F64RegClass;
  1089. break;
  1090. default:
  1091. return false;
  1092. }
  1093. materializeLoadStoreOperands(Addr);
  1094. Register ResultReg = createResultReg(RC);
  1095. auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc),
  1096. ResultReg);
  1097. addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
  1098. updateValueMap(Load, ResultReg);
  1099. return true;
  1100. }
  1101. bool WebAssemblyFastISel::selectStore(const Instruction *I) {
  1102. const auto *Store = cast<StoreInst>(I);
  1103. if (Store->isAtomic())
  1104. return false;
  1105. if (!WebAssembly::isDefaultAddressSpace(Store->getPointerAddressSpace()))
  1106. return false;
  1107. if (!Subtarget->hasSIMD128() &&
  1108. Store->getValueOperand()->getType()->isVectorTy())
  1109. return false;
  1110. Address Addr;
  1111. if (!computeAddress(Store->getPointerOperand(), Addr))
  1112. return false;
  1113. unsigned Opc;
  1114. bool VTIsi1 = false;
  1115. bool A64 = Subtarget->hasAddr64();
  1116. switch (getSimpleType(Store->getValueOperand()->getType())) {
  1117. case MVT::i1:
  1118. VTIsi1 = true;
  1119. [[fallthrough]];
  1120. case MVT::i8:
  1121. Opc = A64 ? WebAssembly::STORE8_I32_A64 : WebAssembly::STORE8_I32_A32;
  1122. break;
  1123. case MVT::i16:
  1124. Opc = A64 ? WebAssembly::STORE16_I32_A64 : WebAssembly::STORE16_I32_A32;
  1125. break;
  1126. case MVT::i32:
  1127. Opc = A64 ? WebAssembly::STORE_I32_A64 : WebAssembly::STORE_I32_A32;
  1128. break;
  1129. case MVT::i64:
  1130. Opc = A64 ? WebAssembly::STORE_I64_A64 : WebAssembly::STORE_I64_A32;
  1131. break;
  1132. case MVT::f32:
  1133. Opc = A64 ? WebAssembly::STORE_F32_A64 : WebAssembly::STORE_F32_A32;
  1134. break;
  1135. case MVT::f64:
  1136. Opc = A64 ? WebAssembly::STORE_F64_A64 : WebAssembly::STORE_F64_A32;
  1137. break;
  1138. default:
  1139. return false;
  1140. }
  1141. materializeLoadStoreOperands(Addr);
  1142. Register ValueReg = getRegForValue(Store->getValueOperand());
  1143. if (ValueReg == 0)
  1144. return false;
  1145. if (VTIsi1)
  1146. ValueReg = maskI1Value(ValueReg, Store->getValueOperand());
  1147. auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc));
  1148. addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
  1149. MIB.addReg(ValueReg);
  1150. return true;
  1151. }
  1152. bool WebAssemblyFastISel::selectBr(const Instruction *I) {
  1153. const auto *Br = cast<BranchInst>(I);
  1154. if (Br->isUnconditional()) {
  1155. MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)];
  1156. fastEmitBranch(MSucc, Br->getDebugLoc());
  1157. return true;
  1158. }
  1159. MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)];
  1160. MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)];
  1161. bool Not;
  1162. unsigned CondReg = getRegForI1Value(Br->getCondition(), Br->getParent(), Not);
  1163. if (CondReg == 0)
  1164. return false;
  1165. unsigned Opc = WebAssembly::BR_IF;
  1166. if (Not)
  1167. Opc = WebAssembly::BR_UNLESS;
  1168. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc))
  1169. .addMBB(TBB)
  1170. .addReg(CondReg);
  1171. finishCondBranch(Br->getParent(), TBB, FBB);
  1172. return true;
  1173. }
  1174. bool WebAssemblyFastISel::selectRet(const Instruction *I) {
  1175. if (!FuncInfo.CanLowerReturn)
  1176. return false;
  1177. const auto *Ret = cast<ReturnInst>(I);
  1178. if (Ret->getNumOperands() == 0) {
  1179. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
  1180. TII.get(WebAssembly::RETURN));
  1181. return true;
  1182. }
  1183. // TODO: support multiple return in FastISel
  1184. if (Ret->getNumOperands() > 1)
  1185. return false;
  1186. Value *RV = Ret->getOperand(0);
  1187. if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy())
  1188. return false;
  1189. switch (getSimpleType(RV->getType())) {
  1190. case MVT::i1:
  1191. case MVT::i8:
  1192. case MVT::i16:
  1193. case MVT::i32:
  1194. case MVT::i64:
  1195. case MVT::f32:
  1196. case MVT::f64:
  1197. case MVT::v16i8:
  1198. case MVT::v8i16:
  1199. case MVT::v4i32:
  1200. case MVT::v2i64:
  1201. case MVT::v4f32:
  1202. case MVT::v2f64:
  1203. case MVT::funcref:
  1204. case MVT::externref:
  1205. break;
  1206. default:
  1207. return false;
  1208. }
  1209. unsigned Reg;
  1210. if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::SExt))
  1211. Reg = getRegForSignedValue(RV);
  1212. else if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::ZExt))
  1213. Reg = getRegForUnsignedValue(RV);
  1214. else
  1215. Reg = getRegForValue(RV);
  1216. if (Reg == 0)
  1217. return false;
  1218. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
  1219. TII.get(WebAssembly::RETURN))
  1220. .addReg(Reg);
  1221. return true;
  1222. }
  1223. bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) {
  1224. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
  1225. TII.get(WebAssembly::UNREACHABLE));
  1226. return true;
  1227. }
  1228. bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {
  1229. switch (I->getOpcode()) {
  1230. case Instruction::Call:
  1231. if (selectCall(I))
  1232. return true;
  1233. break;
  1234. case Instruction::Select:
  1235. return selectSelect(I);
  1236. case Instruction::Trunc:
  1237. return selectTrunc(I);
  1238. case Instruction::ZExt:
  1239. return selectZExt(I);
  1240. case Instruction::SExt:
  1241. return selectSExt(I);
  1242. case Instruction::ICmp:
  1243. return selectICmp(I);
  1244. case Instruction::FCmp:
  1245. return selectFCmp(I);
  1246. case Instruction::BitCast:
  1247. return selectBitCast(I);
  1248. case Instruction::Load:
  1249. return selectLoad(I);
  1250. case Instruction::Store:
  1251. return selectStore(I);
  1252. case Instruction::Br:
  1253. return selectBr(I);
  1254. case Instruction::Ret:
  1255. return selectRet(I);
  1256. case Instruction::Unreachable:
  1257. return selectUnreachable(I);
  1258. default:
  1259. break;
  1260. }
  1261. // Fall back to target-independent instruction selection.
  1262. return selectOperator(I, I->getOpcode());
  1263. }
  1264. FastISel *WebAssembly::createFastISel(FunctionLoweringInfo &FuncInfo,
  1265. const TargetLibraryInfo *LibInfo) {
  1266. return new WebAssemblyFastISel(FuncInfo, LibInfo);
  1267. }