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