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::v4f32: 138 if (Subtarget->hasSIMD128()) 139 return VT; 140 break; 141 default: 142 break; 143 } 144 return MVT::INVALID_SIMPLE_VALUE_TYPE; 145 } 146 bool computeAddress(const Value *Obj, Address &Addr); 147 void materializeLoadStoreOperands(Address &Addr); 148 void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB, 149 MachineMemOperand *MMO); 150 unsigned maskI1Value(unsigned Reg, const Value *V); 151 unsigned getRegForI1Value(const Value *V, bool &Not); 152 unsigned zeroExtendToI32(unsigned Reg, const Value *V, 153 MVT::SimpleValueType From); 154 unsigned signExtendToI32(unsigned Reg, const Value *V, 155 MVT::SimpleValueType From); 156 unsigned zeroExtend(unsigned Reg, const Value *V, 157 MVT::SimpleValueType From, 158 MVT::SimpleValueType To); 159 unsigned signExtend(unsigned Reg, const Value *V, 160 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() ? 378 &WebAssembly::I64RegClass : 379 &WebAssembly::I32RegClass); 380 unsigned Opc = Subtarget->hasAddr64() ? 381 WebAssembly::CONST_I64 : 382 WebAssembly::CONST_I32; 383 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg) 384 .addImm(0); 385 Addr.setReg(Reg); 386 } 387 } 388 } 389 390 void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr, 391 const MachineInstrBuilder &MIB, 392 MachineMemOperand *MMO) { 393 // Set the alignment operand (this is rewritten in SetP2AlignOperands). 394 // TODO: Disable SetP2AlignOperands for FastISel and just do it here. 395 MIB.addImm(0); 396 397 if (const GlobalValue *GV = Addr.getGlobalValue()) 398 MIB.addGlobalAddress(GV, Addr.getOffset()); 399 else 400 MIB.addImm(Addr.getOffset()); 401 402 if (Addr.isRegBase()) 403 MIB.addReg(Addr.getReg()); 404 else 405 MIB.addFrameIndex(Addr.getFI()); 406 407 MIB.addMemOperand(MMO); 408 } 409 410 unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) { 411 return zeroExtendToI32(Reg, V, MVT::i1); 412 } 413 414 unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V, bool &Not) { 415 if (const ICmpInst *ICmp = dyn_cast<ICmpInst>(V)) 416 if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1))) 417 if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32)) { 418 Not = ICmp->isTrueWhenEqual(); 419 return getRegForValue(ICmp->getOperand(0)); 420 } 421 422 if (BinaryOperator::isNot(V) && V->getType()->isIntegerTy(32)) { 423 Not = true; 424 return getRegForValue(BinaryOperator::getNotArgument(V)); 425 } 426 427 Not = false; 428 unsigned Reg = getRegForValue(V); 429 if (Reg == 0) 430 return 0; 431 return maskI1Value(Reg, V); 432 } 433 434 unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V, 435 MVT::SimpleValueType From) { 436 if (Reg == 0) 437 return 0; 438 439 switch (From) { 440 case MVT::i1: 441 // If the value is naturally an i1, we don't need to mask it. 442 // TODO: Recursively examine selects, phis, and, or, xor, constants. 443 if (From == MVT::i1 && V != nullptr) { 444 if (isa<CmpInst>(V) || 445 (isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr())) 446 return copyValue(Reg); 447 } 448 case MVT::i8: 449 case MVT::i16: 450 break; 451 case MVT::i32: 452 return copyValue(Reg); 453 default: 454 return 0; 455 } 456 457 unsigned Imm = createResultReg(&WebAssembly::I32RegClass); 458 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 459 TII.get(WebAssembly::CONST_I32), Imm) 460 .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits())); 461 462 unsigned Result = createResultReg(&WebAssembly::I32RegClass); 463 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 464 TII.get(WebAssembly::AND_I32), Result) 465 .addReg(Reg) 466 .addReg(Imm); 467 468 return Result; 469 } 470 471 unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V, 472 MVT::SimpleValueType From) { 473 if (Reg == 0) 474 return 0; 475 476 switch (From) { 477 case MVT::i1: 478 case MVT::i8: 479 case MVT::i16: 480 break; 481 case MVT::i32: 482 return copyValue(Reg); 483 default: 484 return 0; 485 } 486 487 unsigned Imm = createResultReg(&WebAssembly::I32RegClass); 488 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 489 TII.get(WebAssembly::CONST_I32), Imm) 490 .addImm(32 - MVT(From).getSizeInBits()); 491 492 unsigned Left = createResultReg(&WebAssembly::I32RegClass); 493 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 494 TII.get(WebAssembly::SHL_I32), Left) 495 .addReg(Reg) 496 .addReg(Imm); 497 498 unsigned Right = createResultReg(&WebAssembly::I32RegClass); 499 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 500 TII.get(WebAssembly::SHR_S_I32), Right) 501 .addReg(Left) 502 .addReg(Imm); 503 504 return Right; 505 } 506 507 unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V, 508 MVT::SimpleValueType From, 509 MVT::SimpleValueType To) { 510 if (To == MVT::i64) { 511 if (From == MVT::i64) 512 return copyValue(Reg); 513 514 Reg = zeroExtendToI32(Reg, V, From); 515 516 unsigned Result = createResultReg(&WebAssembly::I64RegClass); 517 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 518 TII.get(WebAssembly::I64_EXTEND_U_I32), Result) 519 .addReg(Reg); 520 return Result; 521 } 522 523 return zeroExtendToI32(Reg, V, From); 524 } 525 526 unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V, 527 MVT::SimpleValueType From, 528 MVT::SimpleValueType To) { 529 if (To == MVT::i64) { 530 if (From == MVT::i64) 531 return copyValue(Reg); 532 533 Reg = signExtendToI32(Reg, V, From); 534 535 unsigned Result = createResultReg(&WebAssembly::I64RegClass); 536 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 537 TII.get(WebAssembly::I64_EXTEND_S_I32), Result) 538 .addReg(Reg); 539 return Result; 540 } 541 542 return signExtendToI32(Reg, V, From); 543 } 544 545 unsigned WebAssemblyFastISel::getRegForUnsignedValue(const Value *V) { 546 MVT::SimpleValueType From = getSimpleType(V->getType()); 547 MVT::SimpleValueType To = getLegalType(From); 548 unsigned VReg = getRegForValue(V); 549 if (VReg == 0) 550 return 0; 551 return zeroExtend(VReg, V, From, To); 552 } 553 554 unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) { 555 MVT::SimpleValueType From = getSimpleType(V->getType()); 556 MVT::SimpleValueType To = getLegalType(From); 557 unsigned VReg = getRegForValue(V); 558 if (VReg == 0) 559 return 0; 560 return signExtend(VReg, V, From, To); 561 } 562 563 unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V, 564 bool IsSigned) { 565 return IsSigned ? getRegForSignedValue(V) : 566 getRegForUnsignedValue(V); 567 } 568 569 unsigned WebAssemblyFastISel::notValue(unsigned Reg) { 570 assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass); 571 572 unsigned NotReg = createResultReg(&WebAssembly::I32RegClass); 573 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 574 TII.get(WebAssembly::EQZ_I32), NotReg) 575 .addReg(Reg); 576 return NotReg; 577 } 578 579 unsigned WebAssemblyFastISel::copyValue(unsigned Reg) { 580 unsigned ResultReg = createResultReg(MRI.getRegClass(Reg)); 581 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 582 TII.get(WebAssembly::COPY), ResultReg) 583 .addReg(Reg); 584 return ResultReg; 585 } 586 587 unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) { 588 DenseMap<const AllocaInst *, int>::iterator SI = 589 FuncInfo.StaticAllocaMap.find(AI); 590 591 if (SI != FuncInfo.StaticAllocaMap.end()) { 592 unsigned ResultReg = createResultReg(Subtarget->hasAddr64() ? 593 &WebAssembly::I64RegClass : 594 &WebAssembly::I32RegClass); 595 unsigned Opc = Subtarget->hasAddr64() ? 596 WebAssembly::COPY_I64 : 597 WebAssembly::COPY_I32; 598 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) 599 .addFrameIndex(SI->second); 600 return ResultReg; 601 } 602 603 return 0; 604 } 605 606 unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) { 607 if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) { 608 unsigned ResultReg = createResultReg(Subtarget->hasAddr64() ? 609 &WebAssembly::I64RegClass : 610 &WebAssembly::I32RegClass); 611 unsigned Opc = Subtarget->hasAddr64() ? 612 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::v4f32: 682 Opc = WebAssembly::ARGUMENT_v4f32; 683 RC = &WebAssembly::V128RegClass; 684 break; 685 case MVT::ExceptRef: 686 Opc = WebAssembly::ARGUMENT_EXCEPT_REF; 687 RC = &WebAssembly::EXCEPT_REFRegClass; 688 break; 689 default: 690 return false; 691 } 692 unsigned ResultReg = createResultReg(RC); 693 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) 694 .addImm(i); 695 updateValueMap(&Arg, ResultReg); 696 697 ++i; 698 } 699 700 MRI.addLiveIn(WebAssembly::ARGUMENTS); 701 702 auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>(); 703 for (auto const &Arg : F->args()) { 704 MVT::SimpleValueType ArgTy = getLegalType(getSimpleType(Arg.getType())); 705 if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE) { 706 MFI->clearParamsAndResults(); 707 return false; 708 } 709 MFI->addParam(ArgTy); 710 } 711 712 if (!F->getReturnType()->isVoidTy()) { 713 MVT::SimpleValueType RetTy = getLegalType(getSimpleType(F->getReturnType())); 714 if (RetTy == MVT::INVALID_SIMPLE_VALUE_TYPE) { 715 MFI->clearParamsAndResults(); 716 return false; 717 } 718 MFI->addResult(RetTy); 719 } 720 721 return true; 722 } 723 724 bool WebAssemblyFastISel::selectCall(const Instruction *I) { 725 const CallInst *Call = cast<CallInst>(I); 726 727 if (Call->isMustTailCall() || Call->isInlineAsm() || 728 Call->getFunctionType()->isVarArg()) 729 return false; 730 731 Function *Func = Call->getCalledFunction(); 732 if (Func && Func->isIntrinsic()) 733 return false; 734 735 bool IsDirect = Func != nullptr; 736 if (!IsDirect && isa<ConstantExpr>(Call->getCalledValue())) 737 return false; 738 739 FunctionType *FuncTy = Call->getFunctionType(); 740 unsigned Opc; 741 bool IsVoid = FuncTy->getReturnType()->isVoidTy(); 742 unsigned ResultReg; 743 if (IsVoid) { 744 Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::PCALL_INDIRECT_VOID; 745 } else { 746 if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy()) 747 return false; 748 749 MVT::SimpleValueType RetTy = getSimpleType(Call->getType()); 750 switch (RetTy) { 751 case MVT::i1: 752 case MVT::i8: 753 case MVT::i16: 754 case MVT::i32: 755 Opc = IsDirect ? WebAssembly::CALL_I32 : WebAssembly::PCALL_INDIRECT_I32; 756 ResultReg = createResultReg(&WebAssembly::I32RegClass); 757 break; 758 case MVT::i64: 759 Opc = IsDirect ? WebAssembly::CALL_I64 : WebAssembly::PCALL_INDIRECT_I64; 760 ResultReg = createResultReg(&WebAssembly::I64RegClass); 761 break; 762 case MVT::f32: 763 Opc = IsDirect ? WebAssembly::CALL_F32 : WebAssembly::PCALL_INDIRECT_F32; 764 ResultReg = createResultReg(&WebAssembly::F32RegClass); 765 break; 766 case MVT::f64: 767 Opc = IsDirect ? WebAssembly::CALL_F64 : WebAssembly::PCALL_INDIRECT_F64; 768 ResultReg = createResultReg(&WebAssembly::F64RegClass); 769 break; 770 case MVT::v16i8: 771 Opc = 772 IsDirect ? WebAssembly::CALL_v16i8 : WebAssembly::PCALL_INDIRECT_v16i8; 773 ResultReg = createResultReg(&WebAssembly::V128RegClass); 774 break; 775 case MVT::v8i16: 776 Opc = 777 IsDirect ? WebAssembly::CALL_v8i16 : WebAssembly::PCALL_INDIRECT_v8i16; 778 ResultReg = createResultReg(&WebAssembly::V128RegClass); 779 break; 780 case MVT::v4i32: 781 Opc = 782 IsDirect ? WebAssembly::CALL_v4i32 : WebAssembly::PCALL_INDIRECT_v4i32; 783 ResultReg = createResultReg(&WebAssembly::V128RegClass); 784 break; 785 case MVT::v4f32: 786 Opc = 787 IsDirect ? WebAssembly::CALL_v4f32 : WebAssembly::PCALL_INDIRECT_v4f32; 788 ResultReg = createResultReg(&WebAssembly::V128RegClass); 789 break; 790 case MVT::ExceptRef: 791 Opc = IsDirect ? WebAssembly::CALL_EXCEPT_REF 792 : WebAssembly::PCALL_INDIRECT_EXCEPT_REF; 793 ResultReg = createResultReg(&WebAssembly::EXCEPT_REFRegClass); 794 break; 795 default: 796 return false; 797 } 798 } 799 800 SmallVector<unsigned, 8> Args; 801 for (unsigned i = 0, e = Call->getNumArgOperands(); i < e; ++i) { 802 Value *V = Call->getArgOperand(i); 803 MVT::SimpleValueType ArgTy = getSimpleType(V->getType()); 804 if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE) 805 return false; 806 807 const AttributeList &Attrs = Call->getAttributes(); 808 if (Attrs.hasParamAttribute(i, Attribute::ByVal) || 809 Attrs.hasParamAttribute(i, Attribute::SwiftSelf) || 810 Attrs.hasParamAttribute(i, Attribute::SwiftError) || 811 Attrs.hasParamAttribute(i, Attribute::InAlloca) || 812 Attrs.hasParamAttribute(i, Attribute::Nest)) 813 return false; 814 815 unsigned Reg; 816 817 if (Attrs.hasParamAttribute(i, Attribute::SExt)) 818 Reg = getRegForSignedValue(V); 819 else if (Attrs.hasParamAttribute(i, Attribute::ZExt)) 820 Reg = getRegForUnsignedValue(V); 821 else 822 Reg = getRegForValue(V); 823 824 if (Reg == 0) 825 return false; 826 827 Args.push_back(Reg); 828 } 829 830 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)); 831 832 if (!IsVoid) 833 MIB.addReg(ResultReg, RegState::Define); 834 835 if (IsDirect) 836 MIB.addGlobalAddress(Func); 837 else { 838 unsigned Reg = getRegForValue(Call->getCalledValue()); 839 if (Reg == 0) 840 return false; 841 MIB.addReg(Reg); 842 } 843 844 for (unsigned ArgReg : Args) 845 MIB.addReg(ArgReg); 846 847 if (!IsVoid) 848 updateValueMap(Call, ResultReg); 849 return true; 850 } 851 852 bool WebAssemblyFastISel::selectSelect(const Instruction *I) { 853 const SelectInst *Select = cast<SelectInst>(I); 854 855 bool Not; 856 unsigned CondReg = getRegForI1Value(Select->getCondition(), Not); 857 if (CondReg == 0) 858 return false; 859 860 unsigned TrueReg = getRegForValue(Select->getTrueValue()); 861 if (TrueReg == 0) 862 return false; 863 864 unsigned FalseReg = getRegForValue(Select->getFalseValue()); 865 if (FalseReg == 0) 866 return false; 867 868 if (Not) 869 std::swap(TrueReg, FalseReg); 870 871 unsigned Opc; 872 const TargetRegisterClass *RC; 873 switch (getSimpleType(Select->getType())) { 874 case MVT::i1: 875 case MVT::i8: 876 case MVT::i16: 877 case MVT::i32: 878 Opc = WebAssembly::SELECT_I32; 879 RC = &WebAssembly::I32RegClass; 880 break; 881 case MVT::i64: 882 Opc = WebAssembly::SELECT_I64; 883 RC = &WebAssembly::I64RegClass; 884 break; 885 case MVT::f32: 886 Opc = WebAssembly::SELECT_F32; 887 RC = &WebAssembly::F32RegClass; 888 break; 889 case MVT::f64: 890 Opc = WebAssembly::SELECT_F64; 891 RC = &WebAssembly::F64RegClass; 892 break; 893 case MVT::ExceptRef: 894 Opc = WebAssembly::SELECT_EXCEPT_REF; 895 RC = &WebAssembly::EXCEPT_REFRegClass; 896 break; 897 default: 898 return false; 899 } 900 901 unsigned ResultReg = createResultReg(RC); 902 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) 903 .addReg(TrueReg) 904 .addReg(FalseReg) 905 .addReg(CondReg); 906 907 updateValueMap(Select, ResultReg); 908 return true; 909 } 910 911 bool WebAssemblyFastISel::selectTrunc(const Instruction *I) { 912 const TruncInst *Trunc = cast<TruncInst>(I); 913 914 unsigned Reg = getRegForValue(Trunc->getOperand(0)); 915 if (Reg == 0) 916 return false; 917 918 if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) { 919 unsigned Result = createResultReg(&WebAssembly::I32RegClass); 920 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 921 TII.get(WebAssembly::I32_WRAP_I64), Result) 922 .addReg(Reg); 923 Reg = Result; 924 } 925 926 updateValueMap(Trunc, Reg); 927 return true; 928 } 929 930 bool WebAssemblyFastISel::selectZExt(const Instruction *I) { 931 const ZExtInst *ZExt = cast<ZExtInst>(I); 932 933 const Value *Op = ZExt->getOperand(0); 934 MVT::SimpleValueType From = getSimpleType(Op->getType()); 935 MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType())); 936 unsigned In = getRegForValue(Op); 937 if (In == 0) 938 return false; 939 unsigned Reg = zeroExtend(In, Op, From, To); 940 if (Reg == 0) 941 return false; 942 943 updateValueMap(ZExt, Reg); 944 return true; 945 } 946 947 bool WebAssemblyFastISel::selectSExt(const Instruction *I) { 948 const SExtInst *SExt = cast<SExtInst>(I); 949 950 const Value *Op = SExt->getOperand(0); 951 MVT::SimpleValueType From = getSimpleType(Op->getType()); 952 MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType())); 953 unsigned In = getRegForValue(Op); 954 if (In == 0) 955 return false; 956 unsigned Reg = signExtend(In, Op, From, To); 957 if (Reg == 0) 958 return false; 959 960 updateValueMap(SExt, Reg); 961 return true; 962 } 963 964 bool WebAssemblyFastISel::selectICmp(const Instruction *I) { 965 const ICmpInst *ICmp = cast<ICmpInst>(I); 966 967 bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64; 968 unsigned Opc; 969 bool isSigned = false; 970 switch (ICmp->getPredicate()) { 971 case ICmpInst::ICMP_EQ: 972 Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64; 973 break; 974 case ICmpInst::ICMP_NE: 975 Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64; 976 break; 977 case ICmpInst::ICMP_UGT: 978 Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64; 979 break; 980 case ICmpInst::ICMP_UGE: 981 Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64; 982 break; 983 case ICmpInst::ICMP_ULT: 984 Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64; 985 break; 986 case ICmpInst::ICMP_ULE: 987 Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64; 988 break; 989 case ICmpInst::ICMP_SGT: 990 Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64; 991 isSigned = true; 992 break; 993 case ICmpInst::ICMP_SGE: 994 Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64; 995 isSigned = true; 996 break; 997 case ICmpInst::ICMP_SLT: 998 Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64; 999 isSigned = true; 1000 break; 1001 case ICmpInst::ICMP_SLE: 1002 Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64; 1003 isSigned = true; 1004 break; 1005 default: return false; 1006 } 1007 1008 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), isSigned); 1009 if (LHS == 0) 1010 return false; 1011 1012 unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), isSigned); 1013 if (RHS == 0) 1014 return false; 1015 1016 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass); 1017 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) 1018 .addReg(LHS) 1019 .addReg(RHS); 1020 updateValueMap(ICmp, ResultReg); 1021 return true; 1022 } 1023 1024 bool WebAssemblyFastISel::selectFCmp(const Instruction *I) { 1025 const FCmpInst *FCmp = cast<FCmpInst>(I); 1026 1027 unsigned LHS = getRegForValue(FCmp->getOperand(0)); 1028 if (LHS == 0) 1029 return false; 1030 1031 unsigned RHS = getRegForValue(FCmp->getOperand(1)); 1032 if (RHS == 0) 1033 return false; 1034 1035 bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64; 1036 unsigned Opc; 1037 bool Not = false; 1038 switch (FCmp->getPredicate()) { 1039 case FCmpInst::FCMP_OEQ: 1040 Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64; 1041 break; 1042 case FCmpInst::FCMP_UNE: 1043 Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64; 1044 break; 1045 case FCmpInst::FCMP_OGT: 1046 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64; 1047 break; 1048 case FCmpInst::FCMP_OGE: 1049 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64; 1050 break; 1051 case FCmpInst::FCMP_OLT: 1052 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64; 1053 break; 1054 case FCmpInst::FCMP_OLE: 1055 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64; 1056 break; 1057 case FCmpInst::FCMP_UGT: 1058 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64; 1059 Not = true; 1060 break; 1061 case FCmpInst::FCMP_UGE: 1062 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64; 1063 Not = true; 1064 break; 1065 case FCmpInst::FCMP_ULT: 1066 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64; 1067 Not = true; 1068 break; 1069 case FCmpInst::FCMP_ULE: 1070 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64; 1071 Not = true; 1072 break; 1073 default: 1074 return false; 1075 } 1076 1077 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass); 1078 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) 1079 .addReg(LHS) 1080 .addReg(RHS); 1081 1082 if (Not) 1083 ResultReg = notValue(ResultReg); 1084 1085 updateValueMap(FCmp, ResultReg); 1086 return true; 1087 } 1088 1089 bool WebAssemblyFastISel::selectBitCast(const Instruction *I) { 1090 // Target-independent code can handle this, except it doesn't set the dead 1091 // flag on the ARGUMENTS clobber, so we have to do that manually in order 1092 // to satisfy code that expects this of isBitcast() instructions. 1093 EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType()); 1094 EVT RetVT = TLI.getValueType(DL, I->getType()); 1095 if (!VT.isSimple() || !RetVT.isSimple()) 1096 return false; 1097 1098 unsigned In = getRegForValue(I->getOperand(0)); 1099 if (In == 0) 1100 return false; 1101 1102 if (VT == RetVT) { 1103 // No-op bitcast. 1104 updateValueMap(I, In); 1105 return true; 1106 } 1107 1108 unsigned Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(), 1109 In, I->getOperand(0)->hasOneUse()); 1110 if (!Reg) 1111 return false; 1112 MachineBasicBlock::iterator Iter = FuncInfo.InsertPt; 1113 --Iter; 1114 assert(Iter->isBitcast()); 1115 Iter->setPhysRegsDeadExcept(ArrayRef<unsigned>(), TRI); 1116 updateValueMap(I, Reg); 1117 return true; 1118 } 1119 1120 bool WebAssemblyFastISel::selectLoad(const Instruction *I) { 1121 const LoadInst *Load = cast<LoadInst>(I); 1122 if (Load->isAtomic()) 1123 return false; 1124 if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy()) 1125 return false; 1126 1127 Address Addr; 1128 if (!computeAddress(Load->getPointerOperand(), Addr)) 1129 return false; 1130 1131 // TODO: Fold a following sign-/zero-extend into the load instruction. 1132 1133 unsigned Opc; 1134 const TargetRegisterClass *RC; 1135 switch (getSimpleType(Load->getType())) { 1136 case MVT::i1: 1137 case MVT::i8: 1138 Opc = WebAssembly::LOAD8_U_I32; 1139 RC = &WebAssembly::I32RegClass; 1140 break; 1141 case MVT::i16: 1142 Opc = WebAssembly::LOAD16_U_I32; 1143 RC = &WebAssembly::I32RegClass; 1144 break; 1145 case MVT::i32: 1146 Opc = WebAssembly::LOAD_I32; 1147 RC = &WebAssembly::I32RegClass; 1148 break; 1149 case MVT::i64: 1150 Opc = WebAssembly::LOAD_I64; 1151 RC = &WebAssembly::I64RegClass; 1152 break; 1153 case MVT::f32: 1154 Opc = WebAssembly::LOAD_F32; 1155 RC = &WebAssembly::F32RegClass; 1156 break; 1157 case MVT::f64: 1158 Opc = WebAssembly::LOAD_F64; 1159 RC = &WebAssembly::F64RegClass; 1160 break; 1161 default: 1162 return false; 1163 } 1164 1165 materializeLoadStoreOperands(Addr); 1166 1167 unsigned ResultReg = createResultReg(RC); 1168 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), 1169 ResultReg); 1170 1171 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load)); 1172 1173 updateValueMap(Load, ResultReg); 1174 return true; 1175 } 1176 1177 bool WebAssemblyFastISel::selectStore(const Instruction *I) { 1178 const StoreInst *Store = cast<StoreInst>(I); 1179 if (Store->isAtomic()) 1180 return false; 1181 if (!Subtarget->hasSIMD128() && 1182 Store->getValueOperand()->getType()->isVectorTy()) 1183 return false; 1184 1185 Address Addr; 1186 if (!computeAddress(Store->getPointerOperand(), Addr)) 1187 return false; 1188 1189 unsigned Opc; 1190 bool VTIsi1 = false; 1191 switch (getSimpleType(Store->getValueOperand()->getType())) { 1192 case MVT::i1: 1193 VTIsi1 = true; 1194 LLVM_FALLTHROUGH; 1195 case MVT::i8: 1196 Opc = WebAssembly::STORE8_I32; 1197 break; 1198 case MVT::i16: 1199 Opc = WebAssembly::STORE16_I32; 1200 break; 1201 case MVT::i32: 1202 Opc = WebAssembly::STORE_I32; 1203 break; 1204 case MVT::i64: 1205 Opc = WebAssembly::STORE_I64; 1206 break; 1207 case MVT::f32: 1208 Opc = WebAssembly::STORE_F32; 1209 break; 1210 case MVT::f64: 1211 Opc = WebAssembly::STORE_F64; 1212 break; 1213 default: return false; 1214 } 1215 1216 materializeLoadStoreOperands(Addr); 1217 1218 unsigned ValueReg = getRegForValue(Store->getValueOperand()); 1219 if (ValueReg == 0) 1220 return false; 1221 if (VTIsi1) 1222 ValueReg = maskI1Value(ValueReg, Store->getValueOperand()); 1223 1224 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)); 1225 1226 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store)); 1227 1228 MIB.addReg(ValueReg); 1229 return true; 1230 } 1231 1232 bool WebAssemblyFastISel::selectBr(const Instruction *I) { 1233 const BranchInst *Br = cast<BranchInst>(I); 1234 if (Br->isUnconditional()) { 1235 MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)]; 1236 fastEmitBranch(MSucc, Br->getDebugLoc()); 1237 return true; 1238 } 1239 1240 MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)]; 1241 MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)]; 1242 1243 bool Not; 1244 unsigned CondReg = getRegForI1Value(Br->getCondition(), Not); 1245 if (CondReg == 0) 1246 return false; 1247 1248 unsigned Opc = WebAssembly::BR_IF; 1249 if (Not) 1250 Opc = WebAssembly::BR_UNLESS; 1251 1252 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)) 1253 .addMBB(TBB) 1254 .addReg(CondReg); 1255 1256 finishCondBranch(Br->getParent(), TBB, FBB); 1257 return true; 1258 } 1259 1260 bool WebAssemblyFastISel::selectRet(const Instruction *I) { 1261 if (!FuncInfo.CanLowerReturn) 1262 return false; 1263 1264 const ReturnInst *Ret = cast<ReturnInst>(I); 1265 1266 if (Ret->getNumOperands() == 0) { 1267 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 1268 TII.get(WebAssembly::RETURN_VOID)); 1269 return true; 1270 } 1271 1272 Value *RV = Ret->getOperand(0); 1273 if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy()) 1274 return false; 1275 1276 unsigned Opc; 1277 switch (getSimpleType(RV->getType())) { 1278 case MVT::i1: case MVT::i8: 1279 case MVT::i16: case MVT::i32: 1280 Opc = WebAssembly::RETURN_I32; 1281 break; 1282 case MVT::i64: 1283 Opc = WebAssembly::RETURN_I64; 1284 break; 1285 case MVT::f32: 1286 Opc = WebAssembly::RETURN_F32; 1287 break; 1288 case MVT::f64: 1289 Opc = WebAssembly::RETURN_F64; 1290 break; 1291 case MVT::v16i8: 1292 Opc = WebAssembly::RETURN_v16i8; 1293 break; 1294 case MVT::v8i16: 1295 Opc = WebAssembly::RETURN_v8i16; 1296 break; 1297 case MVT::v4i32: 1298 Opc = WebAssembly::RETURN_v4i32; 1299 break; 1300 case MVT::v4f32: 1301 Opc = WebAssembly::RETURN_v4f32; 1302 break; 1303 case MVT::ExceptRef: 1304 Opc = WebAssembly::RETURN_EXCEPT_REF; 1305 break; 1306 default: return false; 1307 } 1308 1309 unsigned Reg; 1310 if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::SExt)) 1311 Reg = getRegForSignedValue(RV); 1312 else if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::ZExt)) 1313 Reg = getRegForUnsignedValue(RV); 1314 else 1315 Reg = getRegForValue(RV); 1316 1317 if (Reg == 0) 1318 return false; 1319 1320 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)).addReg(Reg); 1321 return true; 1322 } 1323 1324 bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) { 1325 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 1326 TII.get(WebAssembly::UNREACHABLE)); 1327 return true; 1328 } 1329 1330 bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) { 1331 switch (I->getOpcode()) { 1332 case Instruction::Call: 1333 if (selectCall(I)) 1334 return true; 1335 break; 1336 case Instruction::Select: return selectSelect(I); 1337 case Instruction::Trunc: return selectTrunc(I); 1338 case Instruction::ZExt: return selectZExt(I); 1339 case Instruction::SExt: return selectSExt(I); 1340 case Instruction::ICmp: return selectICmp(I); 1341 case Instruction::FCmp: return selectFCmp(I); 1342 case Instruction::BitCast: return selectBitCast(I); 1343 case Instruction::Load: return selectLoad(I); 1344 case Instruction::Store: return selectStore(I); 1345 case Instruction::Br: return selectBr(I); 1346 case Instruction::Ret: return selectRet(I); 1347 case Instruction::Unreachable: return selectUnreachable(I); 1348 default: break; 1349 } 1350 1351 // Fall back to target-independent instruction selection. 1352 return selectOperator(I, I->getOpcode()); 1353 } 1354 1355 FastISel *WebAssembly::createFastISel(FunctionLoweringInfo &FuncInfo, 1356 const TargetLibraryInfo *LibInfo) { 1357 return new WebAssemblyFastISel(FuncInfo, LibInfo); 1358 } 1359