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