WebAssemblyFastISel.cpp 41 KB

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