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