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