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