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