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