WebAssemblyFastISel.cpp 39 KB

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