Lines Matching +full:reg +full:- +full:addr
1 //===-- WebAssemblyFastISel.cpp - WebAssembly FastISel implementation -----===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
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
16 //===----------------------------------------------------------------------===//
47 #define DEBUG_TYPE "wasm-fastisel"
60 unsigned Reg; member
73 Address() { Base.Reg = 0; } in Address()
75 assert(!isSet() && "Can't change kind with non-zero base"); in setKind()
81 void setReg(unsigned Reg) { in setReg() argument
84 Base.Reg = Reg; in setReg()
89 return Base.Reg; in getReg()
103 assert(NewOffset >= 0 && "Offsets must be non-negative"); in setOffset()
137 if (Subtarget->hasReferenceTypes()) in getLegalType()
141 if (Subtarget->hasReferenceTypes() && Subtarget->hasExceptionHandling()) in getLegalType()
152 if (Subtarget->hasSIMD128()) in getLegalType()
160 bool computeAddress(const Value *Obj, Address &Addr);
161 void materializeLoadStoreOperands(Address &Addr);
162 void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB,
164 unsigned maskI1Value(unsigned Reg, const Value *V);
166 unsigned zeroExtendToI32(unsigned Reg, const Value *V,
168 unsigned signExtendToI32(unsigned Reg, const Value *V,
170 unsigned zeroExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
172 unsigned signExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
177 unsigned notValue(unsigned Reg);
178 unsigned copyValue(unsigned Reg);
205 Subtarget = &FuncInfo.MF->getSubtarget<WebAssemblySubtarget>(); in WebAssemblyFastISel()
206 Context = &FuncInfo.Fn->getContext(); in WebAssemblyFastISel()
216 bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) { in computeAddress() argument
223 FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) { in computeAddress()
224 Opcode = I->getOpcode(); in computeAddress()
228 Opcode = C->getOpcode(); in computeAddress()
232 if (auto *Ty = dyn_cast<PointerType>(Obj->getType())) in computeAddress()
233 if (Ty->getAddressSpace() > 255) in computeAddress()
241 if (Addr.getGlobalValue()) in computeAddress()
243 if (GV->isThreadLocal()) in computeAddress()
245 Addr.setGlobalValue(GV); in computeAddress()
254 return computeAddress(U->getOperand(0), Addr); in computeAddress()
257 // Look past no-op inttoptrs. in computeAddress()
258 if (TLI.getValueType(DL, U->getOperand(0)->getType()) == in computeAddress()
260 return computeAddress(U->getOperand(0), Addr); in computeAddress()
264 // Look past no-op ptrtoints. in computeAddress()
265 if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL)) in computeAddress()
266 return computeAddress(U->getOperand(0), Addr); in computeAddress()
270 Address SavedAddr = Addr; in computeAddress()
271 uint64_t TmpOffset = Addr.getOffset(); in computeAddress()
272 // Non-inbounds geps can wrap; wasm's offsets can't. in computeAddress()
273 if (!cast<GEPOperator>(U)->isInBounds()) in computeAddress()
282 unsigned Idx = cast<ConstantInt>(Op)->getZExtValue(); in computeAddress()
283 TmpOffset += SL->getElementOffset(Idx); in computeAddress()
288 // Constant-offset addressing. in computeAddress()
289 TmpOffset += CI->getSExtValue() * S; in computeAddress()
292 if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) { in computeAddress()
294 Register Reg = getRegForValue(Op); in computeAddress() local
295 if (Reg == 0) in computeAddress()
297 Addr.setReg(Reg); in computeAddress()
302 auto *CI = cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1)); in computeAddress()
303 TmpOffset += CI->getSExtValue() * S; in computeAddress()
305 Op = cast<AddOperator>(Op)->getOperand(0); in computeAddress()
316 Addr.setOffset(TmpOffset); in computeAddress()
317 if (computeAddress(U->getOperand(0), Addr)) in computeAddress()
321 Addr = SavedAddr; in computeAddress()
330 if (Addr.isSet()) { in computeAddress()
333 Addr.setKind(Address::FrameIndexBase); in computeAddress()
334 Addr.setFI(SI->second); in computeAddress()
341 const Value *LHS = U->getOperand(0); in computeAddress()
342 const Value *RHS = U->getOperand(1); in computeAddress()
348 uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue(); in computeAddress()
350 Addr.setOffset(TmpOffset); in computeAddress()
351 return computeAddress(LHS, Addr); in computeAddress()
355 Address Backup = Addr; in computeAddress()
356 if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr)) in computeAddress()
358 Addr = Backup; in computeAddress()
364 const Value *LHS = U->getOperand(0); in computeAddress()
365 const Value *RHS = U->getOperand(1); in computeAddress()
368 int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue(); in computeAddress()
370 Addr.setOffset(TmpOffset); in computeAddress()
371 return computeAddress(LHS, Addr); in computeAddress()
377 if (Addr.isSet()) { in computeAddress()
380 Register Reg = getRegForValue(Obj); in computeAddress() local
381 if (Reg == 0) in computeAddress()
383 Addr.setReg(Reg); in computeAddress()
384 return Addr.getReg() != 0; in computeAddress()
387 void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) { in materializeLoadStoreOperands() argument
388 if (Addr.isRegBase()) { in materializeLoadStoreOperands()
389 unsigned Reg = Addr.getReg(); in materializeLoadStoreOperands() local
390 if (Reg == 0) { in materializeLoadStoreOperands()
391 Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass in materializeLoadStoreOperands()
393 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64 in materializeLoadStoreOperands()
395 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), Reg) in materializeLoadStoreOperands()
397 Addr.setReg(Reg); in materializeLoadStoreOperands()
402 void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr, in addLoadStoreOperands() argument
409 if (const GlobalValue *GV = Addr.getGlobalValue()) in addLoadStoreOperands()
410 MIB.addGlobalAddress(GV, Addr.getOffset()); in addLoadStoreOperands()
412 MIB.addImm(Addr.getOffset()); in addLoadStoreOperands()
414 if (Addr.isRegBase()) in addLoadStoreOperands()
415 MIB.addReg(Addr.getReg()); in addLoadStoreOperands()
417 MIB.addFrameIndex(Addr.getFI()); in addLoadStoreOperands()
422 unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) { in maskI1Value() argument
423 return zeroExtendToI32(Reg, V, MVT::i1); in maskI1Value()
430 if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1))) in getRegForI1Value()
431 if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32) && in getRegForI1Value()
432 ICmp->getParent() == BB) { in getRegForI1Value()
433 Not = ICmp->isTrueWhenEqual(); in getRegForI1Value()
434 return getRegForValue(ICmp->getOperand(0)); in getRegForI1Value()
438 Register Reg = getRegForValue(V); in getRegForI1Value() local
439 if (Reg == 0) in getRegForI1Value()
441 return maskI1Value(Reg, V); in getRegForI1Value()
444 unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V, in zeroExtendToI32() argument
446 if (Reg == 0) in zeroExtendToI32()
454 if (V != nullptr && isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr()) in zeroExtendToI32()
455 return copyValue(Reg); in zeroExtendToI32()
461 return copyValue(Reg); in zeroExtendToI32()
474 .addReg(Reg) in zeroExtendToI32()
480 unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V, in signExtendToI32() argument
482 if (Reg == 0) in signExtendToI32()
491 return copyValue(Reg); in signExtendToI32()
499 .addImm(32 - MVT(From).getSizeInBits()); in signExtendToI32()
504 .addReg(Reg) in signExtendToI32()
516 unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V, in zeroExtend() argument
521 return copyValue(Reg); in zeroExtend()
523 Reg = zeroExtendToI32(Reg, V, From); in zeroExtend()
528 .addReg(Reg); in zeroExtend()
533 return zeroExtendToI32(Reg, V, From); in zeroExtend()
538 unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V, in signExtend() argument
543 return copyValue(Reg); in signExtend()
545 Reg = signExtendToI32(Reg, V, From); in signExtend()
550 .addReg(Reg); in signExtend()
555 return signExtendToI32(Reg, V, From); in signExtend()
561 MVT::SimpleValueType From = getSimpleType(V->getType()); in getRegForUnsignedValue()
572 MVT::SimpleValueType From = getSimpleType(V->getType()); in getRegForSignedValue()
587 unsigned WebAssemblyFastISel::notValue(unsigned Reg) { in notValue() argument
588 assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass); in notValue()
593 .addReg(Reg); in notValue()
597 unsigned WebAssemblyFastISel::copyValue(unsigned Reg) { in copyValue() argument
598 Register ResultReg = createResultReg(MRI.getRegClass(Reg)); in copyValue()
601 .addReg(Reg); in copyValue()
611 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass in fastMaterializeAlloca()
614 Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32; in fastMaterializeAlloca()
616 .addFrameIndex(SI->second); in fastMaterializeAlloca()
627 if (GV->isThreadLocal()) in fastMaterializeConstant()
630 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass in fastMaterializeConstant()
632 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64 in fastMaterializeConstant()
639 // Let target-independent code handle it. in fastMaterializeConstant()
648 if (F->isVarArg()) in fastLowerArguments()
651 if (FuncInfo.Fn->getCallingConv() == CallingConv::Swift) in fastLowerArguments()
655 for (auto const &Arg : F->args()) { in fastLowerArguments()
656 const AttributeList &Attrs = F->getAttributes(); in fastLowerArguments()
665 if (ArgTy->isStructTy() || ArgTy->isArrayTy()) in fastLowerArguments()
667 if (!Subtarget->hasSIMD128() && ArgTy->isVectorTy()) in fastLowerArguments()
741 auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>(); in fastLowerArguments()
742 for (auto const &Arg : F->args()) { in fastLowerArguments()
745 MFI->clearParamsAndResults(); in fastLowerArguments()
748 MFI->addParam(ArgTy); in fastLowerArguments()
751 if (!F->getReturnType()->isVoidTy()) { in fastLowerArguments()
753 getLegalType(getSimpleType(F->getReturnType())); in fastLowerArguments()
755 MFI->clearParamsAndResults(); in fastLowerArguments()
758 MFI->addResult(RetTy); in fastLowerArguments()
768 if (Call->isMustTailCall() || Call->isInlineAsm() || in selectCall()
769 Call->getFunctionType()->isVarArg()) in selectCall()
772 Function *Func = Call->getCalledFunction(); in selectCall()
773 if (Func && Func->isIntrinsic()) in selectCall()
776 if (Call->getCallingConv() == CallingConv::Swift) in selectCall()
780 if (!IsDirect && isa<ConstantExpr>(Call->getCalledOperand())) in selectCall()
783 FunctionType *FuncTy = Call->getFunctionType(); in selectCall()
785 bool IsVoid = FuncTy->getReturnType()->isVoidTy(); in selectCall()
788 if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy()) in selectCall()
791 MVT::SimpleValueType RetTy = getSimpleType(Call->getType()); in selectCall()
841 for (unsigned I = 0, E = Call->arg_size(); I < E; ++I) { in selectCall()
842 Value *V = Call->getArgOperand(I); in selectCall()
843 MVT::SimpleValueType ArgTy = getSimpleType(V->getType()); in selectCall()
847 const AttributeList &Attrs = Call->getAttributes(); in selectCall()
855 unsigned Reg; in selectCall() local
857 if (Call->paramHasAttr(I, Attribute::SExt)) in selectCall()
858 Reg = getRegForSignedValue(V); in selectCall()
859 else if (Call->paramHasAttr(I, Attribute::ZExt)) in selectCall()
860 Reg = getRegForUnsignedValue(V); in selectCall()
862 Reg = getRegForValue(V); in selectCall()
864 if (Reg == 0) in selectCall()
867 Args.push_back(Reg); in selectCall()
872 CalleeReg = getRegForValue(Call->getCalledOperand()); in selectCall()
889 MF->getContext(), Subtarget); in selectCall()
890 if (Subtarget->hasReferenceTypes()) { in selectCall()
896 Table->setNoStrip(); in selectCall()
917 getRegForI1Value(Select->getCondition(), I->getParent(), Not); in selectSelect()
921 Register TrueReg = getRegForValue(Select->getTrueValue()); in selectSelect()
925 Register FalseReg = getRegForValue(Select->getFalseValue()); in selectSelect()
934 switch (getSimpleType(Select->getType())) { in selectSelect()
983 Register Reg = getRegForValue(Trunc->getOperand(0)); in selectTrunc() local
984 if (Reg == 0) in selectTrunc()
987 if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) { in selectTrunc()
991 .addReg(Reg); in selectTrunc()
992 Reg = Result; in selectTrunc()
995 updateValueMap(Trunc, Reg); in selectTrunc()
1002 const Value *Op = ZExt->getOperand(0); in selectZExt()
1003 MVT::SimpleValueType From = getSimpleType(Op->getType()); in selectZExt()
1004 MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType())); in selectZExt()
1008 unsigned Reg = zeroExtend(In, Op, From, To); in selectZExt() local
1009 if (Reg == 0) in selectZExt()
1012 updateValueMap(ZExt, Reg); in selectZExt()
1019 const Value *Op = SExt->getOperand(0); in selectSExt()
1020 MVT::SimpleValueType From = getSimpleType(Op->getType()); in selectSExt()
1021 MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType())); in selectSExt()
1025 unsigned Reg = signExtend(In, Op, From, To); in selectSExt() local
1026 if (Reg == 0) in selectSExt()
1029 updateValueMap(SExt, Reg); in selectSExt()
1036 bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64; in selectICmp()
1039 switch (ICmp->getPredicate()) { in selectICmp()
1078 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned); in selectICmp()
1082 unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned); in selectICmp()
1097 Register LHS = getRegForValue(FCmp->getOperand(0)); in selectFCmp()
1101 Register RHS = getRegForValue(FCmp->getOperand(1)); in selectFCmp()
1105 bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64; in selectFCmp()
1108 switch (FCmp->getPredicate()) { in selectFCmp()
1160 // Target-independent code can handle this, except it doesn't set the dead in selectBitCast()
1163 EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType()); in selectBitCast()
1164 EVT RetVT = TLI.getValueType(DL, I->getType()); in selectBitCast()
1168 Register In = getRegForValue(I->getOperand(0)); in selectBitCast()
1173 // No-op bitcast. in selectBitCast()
1178 Register Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(), in selectBitCast() local
1180 if (!Reg) in selectBitCast()
1183 --Iter; in selectBitCast()
1184 assert(Iter->isBitcast()); in selectBitCast()
1185 Iter->setPhysRegsDeadExcept(ArrayRef<Register>(), TRI); in selectBitCast()
1186 updateValueMap(I, Reg); in selectBitCast()
1192 if (Load->isAtomic()) in selectLoad()
1194 if (!WebAssembly::isDefaultAddressSpace(Load->getPointerAddressSpace())) in selectLoad()
1196 if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy()) in selectLoad()
1199 Address Addr; in selectLoad() local
1200 if (!computeAddress(Load->getPointerOperand(), Addr)) in selectLoad()
1203 // TODO: Fold a following sign-/zero-extend into the load instruction. in selectLoad()
1207 bool A64 = Subtarget->hasAddr64(); in selectLoad()
1208 switch (getSimpleType(Load->getType())) { in selectLoad()
1238 materializeLoadStoreOperands(Addr); in selectLoad()
1244 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load)); in selectLoad()
1252 if (Store->isAtomic()) in selectStore()
1254 if (!WebAssembly::isDefaultAddressSpace(Store->getPointerAddressSpace())) in selectStore()
1256 if (!Subtarget->hasSIMD128() && in selectStore()
1257 Store->getValueOperand()->getType()->isVectorTy()) in selectStore()
1260 Address Addr; in selectStore() local
1261 if (!computeAddress(Store->getPointerOperand(), Addr)) in selectStore()
1266 bool A64 = Subtarget->hasAddr64(); in selectStore()
1267 switch (getSimpleType(Store->getValueOperand()->getType())) { in selectStore()
1293 materializeLoadStoreOperands(Addr); in selectStore()
1295 Register ValueReg = getRegForValue(Store->getValueOperand()); in selectStore()
1299 ValueReg = maskI1Value(ValueReg, Store->getValueOperand()); in selectStore()
1303 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store)); in selectStore()
1311 if (Br->isUnconditional()) { in selectBr()
1312 MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)]; in selectBr()
1313 fastEmitBranch(MSucc, Br->getDebugLoc()); in selectBr()
1317 MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)]; in selectBr()
1318 MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)]; in selectBr()
1321 unsigned CondReg = getRegForI1Value(Br->getCondition(), Br->getParent(), Not); in selectBr()
1333 finishCondBranch(Br->getParent(), TBB, FBB); in selectBr()
1343 if (Ret->getNumOperands() == 0) { in selectRet()
1350 if (Ret->getNumOperands() > 1) in selectRet()
1353 Value *RV = Ret->getOperand(0); in selectRet()
1354 if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy()) in selectRet()
1357 switch (getSimpleType(RV->getType())) { in selectRet()
1379 unsigned Reg; in selectRet() local
1380 if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::SExt)) in selectRet()
1381 Reg = getRegForSignedValue(RV); in selectRet()
1382 else if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::ZExt)) in selectRet()
1383 Reg = getRegForUnsignedValue(RV); in selectRet()
1385 Reg = getRegForValue(RV); in selectRet()
1387 if (Reg == 0) in selectRet()
1392 .addReg(Reg); in selectRet()
1403 switch (I->getOpcode()) { in fastSelectInstruction()
1436 // Fall back to target-independent instruction selection. in fastSelectInstruction()
1437 return selectOperator(I, I->getOpcode()); in fastSelectInstruction()