Go to the documentation of this file.
34 #include "llvm/IR/IntrinsicsWebAssembly.h"
43 #define DEBUG_TYPE "wasm-lower"
58 Subtarget->
hasAddr64() ? WebAssembly::SP64 : WebAssembly::SP32);
301 if (
MVT(
T) != MemT) {
339 setLibcallName(RTLIB::RETURN_ADDRESS,
"emscripten_return_address");
366 WebAssemblyTargetLowering::shouldExpandAtomicRMWInIR(
AtomicRMWInst *AI)
const {
382 bool WebAssemblyTargetLowering::shouldScalarizeBinop(
SDValue VecOp)
const {
402 FastISel *WebAssemblyTargetLowering::createFastISel(
407 MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(
const DataLayout & ,
418 "32-bit shift counts ought to be enough for anyone");
423 "Unable to represent scalar shift amount type");
433 bool IsUnsigned,
bool Int64,
434 bool Float64,
unsigned LoweredOpcode) {
440 unsigned Abs = Float64 ? WebAssembly::ABS_F64 : WebAssembly::ABS_F32;
441 unsigned FConst = Float64 ? WebAssembly::CONST_F64 : WebAssembly::CONST_F32;
442 unsigned LT = Float64 ? WebAssembly::LT_F64 : WebAssembly::LT_F32;
443 unsigned GE = Float64 ? WebAssembly::GE_F64 : WebAssembly::GE_F32;
444 unsigned IConst = Int64 ? WebAssembly::CONST_I64 : WebAssembly::CONST_I32;
445 unsigned Eqz = WebAssembly::EQZ_I32;
446 unsigned And = WebAssembly::AND_I32;
447 int64_t Limit = Int64 ?
INT64_MIN : INT32_MIN;
448 int64_t Substitute = IsUnsigned ? 0 : Limit;
449 double CmpVal = IsUnsigned ? -(
double)Limit * 2.0 : -(
double)Limit;
450 auto &
Context =
BB->getParent()->getFunction().getContext();
460 F->insert(It, FalseMBB);
461 F->insert(It, TrueMBB);
462 F->insert(It, DoneMBB);
468 BB->addSuccessor(TrueMBB);
469 BB->addSuccessor(FalseMBB);
473 unsigned Tmp0, Tmp1, CmpReg, EqzReg, FalseReg, TrueReg;
481 MI.eraseFromParent();
530 CallResults.
getOpcode() == WebAssembly::RET_CALL_RESULTS);
533 bool IsRetCall = CallResults.
getOpcode() == WebAssembly::RET_CALL_RESULTS;
535 bool IsFuncrefCall =
false;
541 IsFuncrefCall = (TRC == &WebAssembly::FUNCREFRegClass);
546 if (IsIndirect && IsRetCall) {
547 CallOp = WebAssembly::RET_CALL_INDIRECT;
548 }
else if (IsIndirect) {
549 CallOp = WebAssembly::CALL_INDIRECT;
550 }
else if (IsRetCall) {
551 CallOp = WebAssembly::RET_CALL;
569 TII.get(WebAssembly::I32_WRAP_I64), Reg32)
595 for (
auto Def : CallResults.
defs())
618 for (
auto Use : CallParams.
uses())
634 if (IsIndirect && IsFuncrefCall) {
646 BuildMI(MF,
DL,
TII.get(WebAssembly::REF_NULL_FUNCREF), RegFuncref);
650 BuildMI(MF,
DL,
TII.get(WebAssembly::TABLE_SET_FUNCREF))
665 switch (
MI.getOpcode()) {
668 case WebAssembly::FP_TO_SINT_I32_F32:
670 WebAssembly::I32_TRUNC_S_F32);
671 case WebAssembly::FP_TO_UINT_I32_F32:
673 WebAssembly::I32_TRUNC_U_F32);
674 case WebAssembly::FP_TO_SINT_I64_F32:
676 WebAssembly::I64_TRUNC_S_F32);
677 case WebAssembly::FP_TO_UINT_I64_F32:
679 WebAssembly::I64_TRUNC_U_F32);
680 case WebAssembly::FP_TO_SINT_I32_F64:
682 WebAssembly::I32_TRUNC_S_F64);
683 case WebAssembly::FP_TO_UINT_I32_F64:
685 WebAssembly::I32_TRUNC_U_F64);
686 case WebAssembly::FP_TO_SINT_I64_F64:
688 WebAssembly::I64_TRUNC_S_F64);
689 case WebAssembly::FP_TO_UINT_I64_F64:
691 WebAssembly::I64_TRUNC_U_F64);
692 case WebAssembly::CALL_RESULTS:
693 case WebAssembly::RET_CALL_RESULTS:
699 WebAssemblyTargetLowering::getTargetNodeName(
unsigned Opcode)
const {
704 #define HANDLE_NODETYPE(NODE) \
705 case WebAssemblyISD::NODE: \
706 return "WebAssemblyISD::" #NODE;
707 #define HANDLE_MEM_NODETYPE(NODE) HANDLE_NODETYPE(NODE)
708 #include "WebAssemblyISD.def"
709 #undef HANDLE_MEM_NODETYPE
710 #undef HANDLE_NODETYPE
715 std::pair<unsigned, const TargetRegisterClass *>
716 WebAssemblyTargetLowering::getRegForInlineAsmConstraint(
720 if (Constraint.
size() == 1) {
721 switch (Constraint[0]) {
726 return std::make_pair(0U, &WebAssembly::V128RegClass);
730 return std::make_pair(0U, &WebAssembly::I32RegClass);
732 return std::make_pair(0U, &WebAssembly::I64RegClass);
737 return std::make_pair(0U, &WebAssembly::F32RegClass);
739 return std::make_pair(0U, &WebAssembly::F64RegClass);
753 bool WebAssemblyTargetLowering::isCheapToSpeculateCttz()
const {
758 bool WebAssemblyTargetLowering::isCheapToSpeculateCtlz()
const {
763 bool WebAssemblyTargetLowering::isLegalAddressingMode(
const DataLayout &
DL,
765 Type *Ty,
unsigned AS,
781 bool WebAssemblyTargetLowering::allowsMisalignedMemoryAccesses(
795 bool WebAssemblyTargetLowering::isIntDivCheap(
EVT VT,
802 bool WebAssemblyTargetLowering::isVectorLoadExtDesirable(
SDValue ExtVal)
const {
804 EVT MemT = cast<LoadSDNode>(ExtVal->
getOperand(0))->getValueType(0);
810 bool WebAssemblyTargetLowering::isOffsetFoldingLegal(
817 EVT WebAssemblyTargetLowering::getSetCCResultType(
const DataLayout &
DL,
830 bool WebAssemblyTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &
Info,
833 unsigned Intrinsic)
const {
835 case Intrinsic::wasm_memory_atomic_notify:
838 Info.ptrVal =
I.getArgOperand(0);
849 case Intrinsic::wasm_memory_atomic_wait32:
852 Info.ptrVal =
I.getArgOperand(0);
857 case Intrinsic::wasm_memory_atomic_wait64:
860 Info.ptrVal =
I.getArgOperand(0);
870 void WebAssemblyTargetLowering::computeKnownBitsForTargetNode(
873 switch (
Op.getOpcode()) {
877 unsigned IntNo =
Op.getConstantOperandVal(0);
881 case Intrinsic::wasm_bitmask: {
883 EVT VT =
Op.getOperand(1).getSimpleValueType();
886 Known.
Zero |= ZeroMask;
895 WebAssemblyTargetLowering::getPreferredVectorAction(
MVT VT)
const {
909 bool WebAssemblyTargetLowering::shouldSimplifyDemandedVectorElts(
910 SDValue Op,
const TargetLoweringOpt &TLO)
const {
963 WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
975 "WebAssembly doesn't support language-specific or target-specific "
976 "calling conventions yet");
977 if (CLI.IsPatchPoint)
978 fail(
DL, DAG,
"WebAssembly doesn't support patch point yet");
980 if (CLI.IsTailCall) {
981 auto NoTail = [&](
const char *
Msg) {
982 if (CLI.CB && CLI.CB->isMustTailCall())
984 CLI.IsTailCall =
false;
988 NoTail(
"WebAssembly 'tail-call' feature not enabled");
992 NoTail(
"WebAssembly does not support varargs tail calls");
997 Type *RetTy =
F.getReturnType();
1002 bool TypesMatch = CallerRetTys.size() == CalleeRetTys.size() &&
1003 std::equal(CallerRetTys.begin(), CallerRetTys.end(),
1004 CalleeRetTys.begin());
1006 NoTail(
"WebAssembly tail call requires caller and callee return types to "
1011 for (
auto &
Arg : CLI.CB->args()) {
1016 if (
auto *
GEP = dyn_cast<GetElementPtrInst>(Src))
1017 Src =
GEP->getPointerOperand();
1022 if (isa<AllocaInst>(Val)) {
1024 "WebAssembly does not support tail calling with stack arguments");
1039 Outs[0].Flags.isSRet()) {
1044 bool HasSwiftSelfArg =
false;
1045 bool HasSwiftErrorArg =
false;
1047 for (
unsigned I = 0;
I < Outs.size(); ++
I) {
1053 fail(
DL, DAG,
"WebAssembly hasn't implemented nest arguments");
1055 fail(
DL, DAG,
"WebAssembly hasn't implemented inalloca arguments");
1057 fail(
DL, DAG,
"WebAssembly hasn't implemented cons regs arguments");
1059 fail(
DL, DAG,
"WebAssembly hasn't implemented cons regs last arguments");
1078 bool IsVarArg = CLI.IsVarArg;
1086 if (!HasSwiftSelfArg) {
1089 Arg.Flags.setSwiftSelf();
1090 CLI.Outs.push_back(
Arg);
1092 CLI.OutVals.push_back(ArgVal);
1094 if (!HasSwiftErrorArg) {
1097 Arg.Flags.setSwiftError();
1098 CLI.Outs.push_back(
Arg);
1100 CLI.OutVals.push_back(ArgVal);
1114 EVT VT =
Arg.getValueType();
1120 CCInfo.AllocateStack(Layout.getTypeAllocSize(Ty), Alignment);
1127 unsigned NumBytes = CCInfo.getAlignedCallFrameSize();
1130 if (IsVarArg && NumBytes) {
1134 Layout.getStackAlignment(),
1139 assert(ArgLocs[ValNo].getValNo() == ValNo &&
1140 "ArgLocs should remain in order and only hold varargs args");
1141 unsigned Offset = ArgLocs[ValNo++].getLocMemOffset();
1149 if (!Chains.empty())
1151 }
else if (IsVarArg) {
1169 Ops.push_back(Chain);
1170 Ops.push_back(Callee);
1174 Ops.
append(OutVals.begin(),
1175 IsVarArg ? OutVals.begin() +
NumFixedArgs : OutVals.end());
1178 Ops.push_back(FINode);
1181 for (
const auto &
In :
Ins) {
1182 assert(!
In.Flags.isByVal() &&
"byval is not valid for return values");
1183 assert(!
In.Flags.isNest() &&
"nest is not valid for return values");
1184 if (
In.Flags.isInAlloca())
1185 fail(
DL, DAG,
"WebAssembly hasn't implemented inalloca return values");
1186 if (
In.Flags.isInConsecutiveRegs())
1187 fail(
DL, DAG,
"WebAssembly hasn't implemented cons regs return values");
1188 if (
In.Flags.isInConsecutiveRegsLast())
1190 "WebAssembly hasn't implemented cons regs last return values");
1193 InTys.push_back(
In.VT);
1219 CLI.CB->getCalledOperand()->getPointerAlignment(DAG.
getDataLayout()),
1225 if (CLI.IsTailCall) {
1228 return DAG.
getNode(WebAssemblyISD::RET_CALL,
DL, NodeTys, Ops);
1235 for (
size_t I = 0;
I <
Ins.size(); ++
I)
1242 bool WebAssemblyTargetLowering::CanLowerReturn(
1250 SDValue WebAssemblyTargetLowering::LowerReturn(
1256 "MVP WebAssembly can only return up to one value");
1258 fail(
DL, DAG,
"WebAssembly doesn't support non-C calling conventions");
1261 RetOps.append(OutVals.begin(), OutVals.end());
1268 assert(Out.
IsFixed &&
"non-fixed return value is not valid");
1270 fail(
DL, DAG,
"WebAssembly hasn't implemented inalloca results");
1272 fail(
DL, DAG,
"WebAssembly hasn't implemented cons regs results");
1274 fail(
DL, DAG,
"WebAssembly hasn't implemented cons regs last results");
1280 SDValue WebAssemblyTargetLowering::LowerFormalArguments(
1285 fail(
DL, DAG,
"WebAssembly doesn't support non-C calling conventions");
1294 bool HasSwiftErrorArg =
false;
1295 bool HasSwiftSelfArg =
false;
1297 HasSwiftSelfArg |=
In.Flags.isSwiftSelf();
1298 HasSwiftErrorArg |=
In.Flags.isSwiftError();
1299 if (
In.Flags.isInAlloca())
1300 fail(
DL, DAG,
"WebAssembly hasn't implemented inalloca arguments");
1301 if (
In.Flags.isNest())
1302 fail(
DL, DAG,
"WebAssembly hasn't implemented nest arguments");
1303 if (
In.Flags.isInConsecutiveRegs())
1304 fail(
DL, DAG,
"WebAssembly hasn't implemented cons regs arguments");
1305 if (
In.Flags.isInConsecutiveRegsLast())
1306 fail(
DL, DAG,
"WebAssembly hasn't implemented cons regs last arguments");
1309 InVals.push_back(
In.Used ? DAG.
getNode(WebAssemblyISD::ARGUMENT,
DL,
In.VT,
1315 MFI->addParam(
In.VT);
1324 if (!HasSwiftSelfArg) {
1325 MFI->addParam(PtrVT);
1327 if (!HasSwiftErrorArg) {
1328 MFI->addParam(PtrVT);
1337 MFI->setVarargBufferVreg(VarargVreg);
1339 Chain,
DL, VarargVreg,
1340 DAG.
getNode(WebAssemblyISD::ARGUMENT,
DL, PtrVT,
1342 MFI->addParam(PtrVT);
1354 assert(MFI->getParams().size() == Params.size() &&
1355 std::equal(MFI->getParams().begin(), MFI->getParams().end(),
1361 void WebAssemblyTargetLowering::ReplaceNodeResults(
1363 switch (
N->getOpcode()) {
1372 "ReplaceNodeResults not implemented for this op for WebAssembly!");
1383 switch (
Op.getOpcode()) {
1388 return LowerFrameIndex(
Op, DAG);
1390 return LowerGlobalAddress(
Op, DAG);
1392 return LowerGlobalTLSAddress(
Op, DAG);
1394 return LowerExternalSymbol(
Op, DAG);
1396 return LowerJumpTable(
Op, DAG);
1398 return LowerBR_JT(
Op, DAG);
1400 return LowerVASTART(
Op, DAG);
1403 fail(
DL, DAG,
"WebAssembly hasn't implemented computed gotos");
1406 return LowerRETURNADDR(
Op, DAG);
1408 return LowerFRAMEADDR(
Op, DAG);
1410 return LowerCopyToReg(
Op, DAG);
1413 return LowerAccessVectorElement(
Op, DAG);
1417 return LowerIntrinsic(
Op, DAG);
1419 return LowerSIGN_EXTEND_INREG(
Op, DAG);
1421 return LowerBUILD_VECTOR(
Op, DAG);
1423 return LowerVECTOR_SHUFFLE(
Op, DAG);
1425 return LowerSETCC(
Op, DAG);
1429 return LowerShift(
Op, DAG);
1432 return LowerFP_TO_INT_SAT(
Op, DAG);
1434 return LowerLoad(
Op, DAG);
1436 return LowerStore(
Op, DAG);
1475 if (
Op->getOpcode() ==
ISD::ADD &&
Op->getNumOperands() == 2)
1476 return (
Op->getOperand(1).getSimpleValueType() ==
MVT::i32 &&
1478 (
Op->getOperand(0).getSimpleValueType() ==
MVT::i32 &&
1485 bool WebAssemblyTargetLowering::MatchTableForLowering(
SelectionDAG &DAG,
1508 GA = cast<GlobalAddressSDNode>(
Base);
1511 GA = dyn_cast<GlobalAddressSDNode>(
Base->getOperand(0));
1514 Idx =
Base->getOperand(1);
1519 GA = dyn_cast<GlobalAddressSDNode>(V->
getOperand(1));
1544 "unexpected offset when loading from webassembly table",
false);
1549 if (!MatchTableForLowering(DAG,
DL,
Base, GA, Idx))
1580 return DAG.
getNode(WebAssemblyISD::LOCAL_SET,
DL, Tys, Ops);
1596 "unexpected offset when loading from webassembly table",
false);
1601 if (!MatchTableForLowering(DAG,
DL,
Base, GA, Idx))
1616 "unexpected offset when loading from webassembly global",
false);
1627 "unexpected offset when loading from webassembly local",
false);
1634 assert(
Result->getNumValues() == 2 &&
"Loads must carry a chain!");
1644 if (isa<FrameIndexSDNode>(Src.getNode())) {
1652 Register Reg = cast<RegisterSDNode>(
Op.getOperand(1))->getReg();
1653 EVT VT = Src.getValueType();
1655 : WebAssembly::COPY_I64,
1658 return Op.getNode()->getNumValues() == 1
1661 Op.getNumOperands() == 4 ?
Op.getOperand(3)
1669 int FI = cast<FrameIndexSDNode>(
Op)->getIndex();
1679 "Non-Emscripten WebAssembly hasn't implemented "
1680 "__builtin_return_address");
1687 unsigned Depth =
Op.getConstantOperandVal(0);
1688 MakeLibCallOptions CallOptions;
1689 return makeLibCall(DAG, RTLIB::RETURN_ADDRESS,
Op.getValueType(),
1690 {DAG.getConstant(Depth, DL, MVT::i32)}, CallOptions,
DL)
1699 if (
Op.getConstantOperandVal(0) > 0)
1703 EVT VT =
Op.getValueType();
1710 WebAssemblyTargetLowering::LowerGlobalTLSAddress(
SDValue Op,
1713 const auto *GA = cast<GlobalAddressSDNode>(
Op);
1730 "non-Emscripten OSes: variable " +
1748 auto GlobalGet = PtrVT ==
MVT::i64 ? WebAssembly::GLOBAL_GET_I64
1749 : WebAssembly::GLOBAL_GET_I32;
1760 DAG.
getNode(WebAssemblyISD::WrapperREL,
DL, PtrVT, TLSOffset);
1767 EVT VT =
Op.getValueType();
1777 const auto *GA = cast<GlobalAddressSDNode>(
Op);
1778 EVT VT =
Op.getValueType();
1780 "Unexpected target flags on generic GlobalAddressSDNode");
1782 fail(
DL, DAG,
"Invalid address space for WebAssembly target");
1790 const char *BaseName;
1804 WebAssemblyISD::WrapperREL,
DL, VT,
1819 WebAssemblyTargetLowering::LowerExternalSymbol(
SDValue Op,
1822 const auto *ES = cast<ExternalSymbolSDNode>(
Op);
1823 EVT VT =
Op.getValueType();
1824 assert(ES->getTargetFlags() == 0 &&
1825 "Unexpected target flags on generic ExternalSymbolSDNode");
1837 JT->getTargetFlags());
1844 const auto *
JT = cast<JumpTableSDNode>(
Op.getOperand(1));
1846 assert(
JT->getTargetFlags() == 0 &&
"WebAssembly doesn't set target flags");
1849 Ops.push_back(Chain);
1850 Ops.push_back(Index);
1856 for (
auto MBB : MBBs)
1872 const Value *SV = cast<SrcValueSDNode>(
Op.getOperand(2))->getValue();
1875 MFI->getVarargBufferVreg(), PtrVT);
1876 return DAG.
getStore(
Op.getOperand(0),
DL, ArgN,
Op.getOperand(1),
1884 switch (
Op.getOpcode()) {
1887 IntNo =
Op.getConstantOperandVal(1);
1890 IntNo =
Op.getConstantOperandVal(0);
1901 case Intrinsic::wasm_lsda: {
1913 DAG.
getNode(WebAssemblyISD::WrapperREL,
DL, PtrVT, Node);
1920 case Intrinsic::wasm_shuffle: {
1924 Ops[OpIdx++] =
Op.getOperand(1);
1925 Ops[OpIdx++] =
Op.getOperand(2);
1926 while (OpIdx < 18) {
1927 const SDValue &MaskIdx =
Op.getOperand(OpIdx + 1);
1929 cast<ConstantSDNode>(MaskIdx.
getNode())->getZExtValue() >= 32) {
1932 Ops[OpIdx++] = MaskIdx;
1935 return DAG.
getNode(WebAssemblyISD::SHUFFLE,
DL,
Op.getValueType(), Ops);
1941 WebAssemblyTargetLowering::LowerSIGN_EXTEND_INREG(
SDValue Op,
1955 const SDValue &Extract =
Op.getOperand(0);
1959 MVT ExtractedLaneT =
1960 cast<VTSDNode>(
Op.getOperand(1).getNode())->
getVT().getSimpleVT();
1963 if (ExtractedVecT == VecT)
1968 if (!isa<ConstantSDNode>(Index))
1970 unsigned IndexVal = cast<ConstantSDNode>(Index)->getZExtValue();
1989 unsigned &Index) ->
bool {
1990 switch (
Op.getOpcode()) {
1992 Opcode = WebAssemblyISD::CONVERT_LOW_S;
1995 Opcode = WebAssemblyISD::CONVERT_LOW_U;
1998 Opcode = WebAssemblyISD::PROMOTE_LOW;
2004 auto ExtractVector =
Op.getOperand(0);
2008 if (!isa<ConstantSDNode>(ExtractVector.getOperand(1).getNode()))
2011 SrcVec = ExtractVector.getOperand(0);
2012 Index = ExtractVector.getConstantOperandVal(1);
2016 unsigned LHSOpcode, RHSOpcode, LHSIndex, RHSIndex;
2018 if (!GetConvertedLane(
Op.getOperand(0), LHSOpcode, LHSSrcVec, LHSIndex) ||
2019 !GetConvertedLane(
Op.getOperand(1), RHSOpcode, RHSSrcVec, RHSIndex))
2022 if (LHSOpcode != RHSOpcode)
2026 switch (LHSOpcode) {
2027 case WebAssemblyISD::CONVERT_LOW_S:
2028 case WebAssemblyISD::CONVERT_LOW_U:
2031 case WebAssemblyISD::PROMOTE_LOW:
2038 auto Src = LHSSrcVec;
2039 if (LHSIndex != 0 || RHSIndex != 1 || LHSSrcVec != RHSSrcVec) {
2042 ExpectedSrcVT,
DL, LHSSrcVec, RHSSrcVec,
2043 {
static_cast<int>(LHSIndex),
static_cast<int>(RHSIndex) + 4, -1, -1});
2054 const EVT VecT =
Op.getValueType();
2055 const EVT LaneT =
Op.getOperand(0).getValueType();
2056 const size_t Lanes =
Op.getNumOperands();
2078 auto GetSwizzleSrcs = [](
size_t I,
const SDValue &Lane) {
2093 Index->getConstantOperandVal(1) !=
I)
2095 return std::make_pair(SwizzleSrc, SwizzleIndices);
2102 auto GetShuffleSrc = [&](
const SDValue &Lane) {
2105 if (!isa<ConstantSDNode>(Lane->getOperand(1).getNode()))
2107 if (Lane->getOperand(0).getValueType().getVectorNumElements() >
2113 using ValueEntry = std::pair<SDValue, size_t>;
2116 using SwizzleEntry = std::pair<std::pair<SDValue, SDValue>,
size_t>;
2119 using ShuffleEntry = std::pair<SDValue, size_t>;
2122 auto AddCount = [](
auto &Counts,
const auto &Val) {
2125 if (CountIt == Counts.end()) {
2126 Counts.emplace_back(Val, 1);
2132 auto GetMostCommon = [](
auto &Counts) {
2134 std::max_element(Counts.begin(), Counts.end(),
2135 [](
auto A,
auto B) { return A.second < B.second; });
2136 assert(CommonIt != Counts.end() &&
"Unexpected all-undef build_vector");
2140 size_t NumConstantLanes = 0;
2143 for (
size_t I = 0;
I < Lanes; ++
I) {
2148 AddCount(SplatValueCounts, Lane);
2152 if (
auto ShuffleSrc = GetShuffleSrc(Lane))
2153 AddCount(ShuffleCounts, ShuffleSrc);
2155 auto SwizzleSrcs = GetSwizzleSrcs(
I, Lane);
2156 if (SwizzleSrcs.first)
2157 AddCount(SwizzleCounts, SwizzleSrcs);
2162 size_t NumSplatLanes;
2163 std::tie(SplatValue, NumSplatLanes) = GetMostCommon(SplatValueCounts);
2167 size_t NumSwizzleLanes = 0;
2168 if (SwizzleCounts.size())
2169 std::forward_as_tuple(std::tie(SwizzleSrc, SwizzleIndices),
2170 NumSwizzleLanes) = GetMostCommon(SwizzleCounts);
2174 SDValue ShuffleSrc1, ShuffleSrc2;
2175 size_t NumShuffleLanes = 0;
2176 if (ShuffleCounts.size()) {
2177 std::tie(ShuffleSrc1, NumShuffleLanes) = GetMostCommon(ShuffleCounts);
2179 [&](
const auto &Pair) {
return Pair.first == ShuffleSrc1; });
2181 if (ShuffleCounts.size()) {
2182 size_t AdditionalShuffleLanes;
2183 std::tie(ShuffleSrc2, AdditionalShuffleLanes) =
2184 GetMostCommon(ShuffleCounts);
2185 NumShuffleLanes += AdditionalShuffleLanes;
2193 if (NumSwizzleLanes >= NumShuffleLanes &&
2194 NumSwizzleLanes >= NumConstantLanes && NumSwizzleLanes >= NumSplatLanes) {
2197 auto Swizzled = std::make_pair(SwizzleSrc, SwizzleIndices);
2198 IsLaneConstructed = [&, Swizzled](
size_t I,
const SDValue &Lane) {
2199 return Swizzled == GetSwizzleSrcs(
I, Lane);
2201 }
else if (NumShuffleLanes >= NumConstantLanes &&
2202 NumShuffleLanes >= NumSplatLanes) {
2212 assert(LaneSize > DestLaneSize);
2213 Scale1 = LaneSize / DestLaneSize;
2219 assert(LaneSize > DestLaneSize);
2220 Scale2 = LaneSize / DestLaneSize;
2225 assert(DestLaneCount <= 16);
2226 for (
size_t I = 0;
I < DestLaneCount; ++
I) {
2228 SDValue Src = GetShuffleSrc(Lane);
2229 if (Src == ShuffleSrc1) {
2231 }
else if (Src && Src == ShuffleSrc2) {
2239 IsLaneConstructed = [&](size_t,
const SDValue &Lane) {
2240 auto Src = GetShuffleSrc(Lane);
2241 return Src == ShuffleSrc1 || (Src && Src == ShuffleSrc2);
2243 }
else if (NumConstantLanes >= NumSplatLanes) {
2245 for (
const SDValue &Lane :
Op->op_values()) {
2253 auto *
Const = dyn_cast<ConstantSDNode>(Lane.
getNode());
2254 int64_t Val =
Const ?
Const->getSExtValue() : 0;
2256 assert((LaneBits == 64 || Val >= -(1
ll << (LaneBits - 1))) &&
2257 "Unexpected out of bounds negative value");
2258 if (Const && LaneBits != 64 && Val > (1
ll << (LaneBits - 1)) - 1) {
2259 auto NewVal = ((
uint64_t)Val % (1
ll << LaneBits)) - (1
ll << LaneBits);
2262 ConstLanes.push_back(Lane);
2277 if ((SplattedLoad = dyn_cast<LoadSDNode>(SplatValue)) &&
2280 WebAssemblyISD::LOAD_SPLAT,
DL, DAG.
getVTList(VecT),
2281 {SplattedLoad->getChain(), SplattedLoad->getBasePtr(),
2282 SplattedLoad->getOffset()},
2287 IsLaneConstructed = [&SplatValue](
size_t _,
const SDValue &Lane) {
2288 return Lane == SplatValue;
2293 assert(IsLaneConstructed);
2296 for (
size_t I = 0;
I < Lanes; ++
I) {
2298 if (!Lane.
isUndef() && !IsLaneConstructed(
I, Lane))
2307 WebAssemblyTargetLowering::LowerVECTOR_SHUFFLE(
SDValue Op,
2312 assert(
VecType.is128BitVector() &&
"Unexpected shuffle vector type");
2313 size_t LaneBytes =
VecType.getVectorElementType().getSizeInBits() / 8;
2318 Ops[OpIdx++] =
Op.getOperand(0);
2319 Ops[OpIdx++] =
Op.getOperand(1);
2322 for (
int M :
Mask) {
2323 for (
size_t J = 0; J < LaneBytes; ++J) {
2330 return DAG.
getNode(WebAssemblyISD::SHUFFLE,
DL,
Op.getValueType(), Ops);
2343 auto MakeLane = [&](
unsigned I) {
2349 {MakeLane(0), MakeLane(1)});
2353 WebAssemblyTargetLowering::LowerAccessVectorElement(
SDValue Op,
2356 SDNode *IdxNode =
Op.getOperand(
Op.getNumOperands() - 1).getNode();
2357 if (isa<ConstantSDNode>(IdxNode) || IdxNode->
isUndef())
2365 EVT LaneT =
Op.getSimpleValueType().getVectorElementType();
2371 size_t NumLanes =
Op.getSimpleValueType().getVectorNumElements();
2373 unsigned ShiftOpcode =
Op.getOpcode();
2379 for (
size_t i = 0;
i < NumLanes; ++
i) {
2382 SDValue ShiftedValue = ShiftedElements[
i];
2386 UnrolledOps.push_back(
2397 assert(
Op.getSimpleValueType().isVector());
2407 switch (
Op.getOpcode()) {
2409 Opcode = WebAssemblyISD::VEC_SHL;
2412 Opcode = WebAssemblyISD::VEC_SHR_S;
2415 Opcode = WebAssemblyISD::VEC_SHR_U;
2421 return DAG.
getNode(Opcode,
DL,
Op.getValueType(),
Op.getOperand(0), ShiftVal);
2427 EVT ResT =
Op.getValueType();
2428 EVT SatVT = cast<VTSDNode>(
Op.getOperand(1))->getVT();
2445 auto &DAG = DCI.
DAG;
2446 auto Shuffle = cast<ShuffleVectorSDNode>(
N);
2455 if (!
N->getOperand(1).isUndef())
2464 SrcType,
SDLoc(
N), CastOp, DAG.
getUNDEF(SrcType), Shuffle->getMask());
2470 auto &DAG = DCI.
DAG;
2476 auto Extract =
N->getOperand(0);
2480 auto *IndexNode = dyn_cast<ConstantSDNode>(Extract.
getOperand(1));
2481 if (IndexNode ==
nullptr)
2483 auto Index = IndexNode->getZExtValue();
2487 EVT ResVT =
N->getValueType(0);
2505 bool IsLow = Index == 0;
2507 unsigned Op = IsSext ? (IsLow ? WebAssemblyISD::EXTEND_LOW_S
2508 : WebAssemblyISD::EXTEND_HIGH_S)
2509 : (IsLow ? WebAssemblyISD::EXTEND_LOW_U
2510 : WebAssemblyISD::EXTEND_HIGH_U);
2517 auto &DAG = DCI.
DAG;
2519 auto GetWasmConversionOp = [](
unsigned Op) {
2522 return WebAssemblyISD::TRUNC_SAT_ZERO_S;
2524 return WebAssemblyISD::TRUNC_SAT_ZERO_U;
2526 return WebAssemblyISD::DEMOTE_ZERO;
2531 auto IsZeroSplat = [](
SDValue SplatVal) {
2532 auto *Splat = dyn_cast<BuildVectorSDNode>(SplatVal.getNode());
2533 APInt SplatValue, SplatUndef;
2534 unsigned SplatBitSize;
2537 Splat->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
2555 EVT ExpectedConversionType;
2558 switch (ConversionOp) {
2572 if (
N->getValueType(0) != ResVT)
2575 if (
Conversion.getValueType() != ExpectedConversionType)
2582 if (!IsZeroSplat(
N->getOperand(1)) ||
2583 N->getOperand(1).getValueType() != ExpectedConversionType)
2586 unsigned Op = GetWasmConversionOp(ConversionOp);
2602 auto ConversionOp =
N->getOpcode();
2603 switch (ConversionOp) {
2615 if (
N->getValueType(0) != ResVT)
2618 auto Concat =
N->getOperand(0);
2626 if (!IsZeroSplat(
Concat.getOperand(1)) ||
2630 unsigned Op = GetWasmConversionOp(ConversionOp);
2636 const SDLoc &
DL,
unsigned VectorWidth) {
2644 unsigned ElemsPerChunk = VectorWidth / ElVT.
getSizeInBits();
2649 IdxVal &= ~(ElemsPerChunk - 1);
2654 Vec->
ops().slice(IdxVal, ElemsPerChunk));
2666 EVT SrcVT =
In.getValueType();
2689 unsigned SubSizeInBits = SrcSizeInBits / 2;
2691 OutVT =
EVT::getVectorVT(Ctx, OutVT, SubSizeInBits / OutVT.getSizeInBits());
2717 auto &DAG = DCI.
DAG;
2720 EVT InVT =
In.getValueType();
2724 EVT OutVT =
N->getValueType(0);
2743 WebAssemblyTargetLowering::PerformDAGCombine(
SDNode *
N,
2744 DAGCombinerInfo &DCI)
const {
2745 switch (
N->getOpcode()) {
virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
static Optional< unsigned > IsWebAssemblyLocal(SDValue Op, SelectionDAG &DAG)
void addLiveIn(MCRegister Reg, Register vreg=Register())
addLiveIn - Add the specified register as a live-in.
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
static SDValue performVectorExtendCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
const SDValue & getOffset() const
const WebAssemblyRegisterInfo * getRegisterInfo() const override
virtual MVT getPointerMemTy(const DataLayout &DL, uint32_t AS=0) const
Return the in-memory pointer type for the given address space, defaults to the pointer type from the ...
static SDValue performTruncateCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
const SDValue & getBasePtr() const
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
const Triple & getTargetTriple() const
MVT getVectorElementType() const
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
iterator_range< mop_iterator > uses()
Returns a range that includes all operands that are register uses.
const Value * stripPointerCastsAndAliases() const
Strip off pointer casts, all-zero GEPs, address space casts, and aliases.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
This is an optimization pass for GlobalISel generic memory operations.
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
const MachineInstrBuilder & addFPImm(const ConstantFP *Val) const
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
bool isFixedLengthVector() const
A parsed version of the target data layout string in and methods for querying it.
bool isInteger() const
Return true if this is an integer or a vector integer type.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
@ BR_JT
BR_JT - Jumptable branch.
Diagnostic information for unsupported feature in backend.
CCState - This class holds information needed while lowering arguments and return values.
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, unsigned Reg, SDValue N)
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
SDNode * getNode() const
get the SDNode which holds the desired result
const MachineInstrBuilder & add(const MachineOperand &MO) const
MCContext & getContext() const
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
bool isInConsecutiveRegsLast() const
@ BSWAP
Byte Swap and Counting operators.
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
bool isUndef() const
Return true if the type of the node type undefined.
SDValue getValueType(EVT)
@ ADDC
Carry-setting nodes for multiple precision addition and subtraction.
@ WASM_ADDRESS_SPACE_FUNCREF
MCSymbolWasm * getOrCreateFunctionTableSymbol(MCContext &Ctx, const WebAssemblySubtarget *Subtarget)
Returns the __indirect_function_table, for use in call_indirect and in function bitcasts.
bool hasMultivalue() const
into xmm2 addss xmm2 xmm1 xmm3 addss xmm3 movaps xmm0 unpcklps xmm0 ret seems silly when it could just be one addps Expand libm rounding functions main should enable SSE DAZ mode and other fast SSE modes Think about doing i64 math in SSE regs on x86 This testcase should have no SSE instructions in and only one load from a constant double
BinOp getOperation() const
SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
bool isVector() const
Return true if this is a vector value type.
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
static SDValue performVectorTruncZeroCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
@ Bitcast
Perform the operation on a different, but equivalently sized type.
static SDValue extractSubVector(SDValue Vec, unsigned IdxVal, SelectionDAG &DAG, const SDLoc &DL, unsigned VectorWidth)
bool isFuncrefType(const Type *Ty)
Reg
All possible values of the reg field in the ModR/M byte.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
EVT getMemoryVT() const
Return the type of the in-memory value.
unsigned getFunctionNumber() const
getFunctionNumber - Return a unique ID for the current function.
const SDValue & getChain() const
Represents one node in the SelectionDAG.
unsigned getTargetFlags() const
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
This class is used to represent ISD::LOAD nodes.
iterator_range< mop_iterator > defs()
Returns a range over all explicit operands that are register definitions.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
bool isPositionIndependent() const
MachineInstr * CreateMachineInstr(const MCInstrDesc &MCID, DebugLoc DL, bool NoImplicit=false)
CreateMachineInstr - Allocate a new MachineInstr.
The instances of the Type class are immutable: once they are created, they are never changed.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ WASM_ADDRESS_SPACE_EXTERNREF
SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
void ExtractVectorElements(SDValue Op, SmallVectorImpl< SDValue > &Args, unsigned Start=0, unsigned Count=0, EVT EltVT=EVT())
Append the extracted elements from Start to Count out of the vector Op in Args.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
static SDValue performVECTOR_SHUFFLECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
Function Alias Analysis Results
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
bool isOSEmscripten() const
Tests whether the OS is Emscripten.
unsigned const TargetRegisterInfo * TRI
static MachineBasicBlock * LowerCallResults(MachineInstr &CallResults, DebugLoc DL, MachineBasicBlock *BB, const WebAssemblySubtarget *Subtarget, const TargetInstrInfo &TII)
LLVMContext * getContext() const
static bool IsWebAssemblyTable(SDValue Op)
LLVM Basic Block Representation.
static bool IsWebAssemblyTableWithOffset(SDValue Op)
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool is256BitVector() const
Return true if this is a 256-bit vector type.
WebAssemblyTargetLowering(const TargetMachine &TM, const WebAssemblySubtarget &STI)
@ BRIND
BRIND - Indirect branch.
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
static auto integer_valuetypes()
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ BR_CC
BR_CC - Conditional branch.
bool isArrayTy() const
True if this is an instance of ArrayType.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo)
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
TargetInstrInfo - Interface to description of machine instruction set.
SDValue getTargetFrameIndex(int FI, EVT VT)
@ And
Bitwise or logical AND of integers.
EVT getValueType() const
Return the ValueType of the referenced return value.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
void setOperationAction(ArrayRef< unsigned > Ops, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
OperandFlags
These are flags set on operands, but should be considered private, all access should go through the M...
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
static SDValue LowerConvertLow(SDValue Op, SelectionDAG &DAG)
(vector float) vec_cmpeq(*A, *B) C
static Type * getDoubleTy(LLVMContext &C)
const MachineOperand & getOperand(unsigned i) const
SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
ThreadLocalMode getThreadLocalMode() const
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ ZeroOrNegativeOneBooleanContent
static SDValue unrollVectorShift(SDValue Op, SelectionDAG &DAG)
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
@ WASM_EmscriptenInvoke
Calling convention for emscripten __invoke_* functions.
const HexagonInstrInfo * TII
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
Describe properties that are true of each instruction in the target description file.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const SDValue & getOffset() const
Analysis the ScalarEvolution expression for r is< loop > Outside the this could be evaluated simply however ScalarEvolution currently evaluates it it involves i65 which is very inefficient when expanded into code In formatValue in test CodeGen X86 lsr delayed fold ll
static constexpr int Concat[]
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, uint64_t Size=0, const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
@ INVALID_SIMPLE_VALUE_TYPE
Analysis containing CSE Info
@ AND
Bitwise operators - logical and, logical or, logical xor.
const GlobalValue * getGlobal() const
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
This struct is a compact representation of a valid (non-zero power of two) alignment.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
bool isFunctionTy() const
True if this is an instance of FunctionType.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
Register getFrameRegister(const MachineFunction &MF) const override
Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Align getNonZeroOrigAlign() const
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const
Return true if folding a constant offset with the given GlobalAddress is legal.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
void setLibcallName(ArrayRef< RTLIB::Libcall > Calls, const char *Name)
Rename the default libcall routine name for the specified libcall.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Type * getArrayElementType() const
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
const std::vector< MachineJumpTableEntry > & getJumpTables() const
@ Fast
Fast - This calling convention attempts to make calls as fast as possible (e.g.
bool hasReferenceTypes() const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Representation of each machine instruction.
MachineMemOperand * getMemOperand() const
Return a MachineMemOperand object describing the memory reference performed by operation.
Module * getParent()
Get the module that this global value is contained inside of...
bool verifyReturnAddressArgumentIsConstant(SDValue Op, SelectionDAG &DAG) const
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
bool hasNontrappingFPToInt() const
@ TRAP
TRAP - Trapping instruction.
This class contains a discriminated union of information about pointers in memory operands,...
This is an important class for using LLVM in a threaded context.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT)
OutputArg - This struct carries flags and a value for a single outgoing (actual) argument or outgoing...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
const SDValue & getOperand(unsigned Num) const
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
static CCValAssign getMem(unsigned ValNo, MVT ValVT, unsigned Offset, MVT LocVT, LocInfo HTP)
const WebAssemblyInstrInfo * getInstrInfo() const override
int64_t getOffset() const
Flags
Flags values. These may be or'd together.
unsigned getVectorNumElements() const
This class is used to represent ISD::STORE nodes.
SDValue getValue(unsigned R) const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
Primary interface to the complete machine description for the target machine.
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
print Print MemDeps of function
MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
Register getReg() const
getReg - Returns the register number.
const SDValue & getValue() const
bool isRefType(const Type *Ty)
Class for arbitrary precision integers.
static MVT getVectorVT(MVT VT, unsigned NumElements)
void computeLegalValueVTs(const WebAssemblyTargetLowering &TLI, LLVMContext &Ctx, const DataLayout &DL, Type *Ty, SmallVectorImpl< MVT > &ValueVTs)
static auto fixedlen_vector_valuetypes()
bool isVector() const
Return true if this is a vector value type.
int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
StringRef - Represent a constant reference to a string, i.e.
uint64_t getScalarSizeInBits() const
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static MachineBasicBlock * LowerFPToInt(MachineInstr &MI, DebugLoc DL, MachineBasicBlock *BB, const TargetInstrInfo &TII, bool IsUnsigned, bool Int64, bool Float64, unsigned LoweredOpcode)
MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const override
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
@ C
C - The default llvm calling convention, compatible with C.
bool hasBulkMemory() const
bool is128BitVector() const
Return true if this is a 128-bit vector type.
const SDValue & getOperand(unsigned i) const
self_iterator getIterator()
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
ArrayRef< SDUse > ops() const
SDValue getBasicBlock(MachineBasicBlock *MBB)
StringRef getName() const
Return a constant reference to the value's name.
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
@ MOVolatile
The memory access is volatile.
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
an instruction that atomically reads a memory location, combines it with another value,...
@ MOLoad
The memory access reads data.
unsigned const MachineRegisterInfo * MRI
Wrapper class representing virtual and physical registers.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
const SDValue & getBasePtr() const
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
static unsigned NumFixedArgs
const CustomOperand< const MCSubtargetInfo & > Msg[]
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
amdgpu Simplify well known AMD library false FunctionCallee Callee
const TargetMachine & getTargetMachine() const
static bool callingConvSupported(CallingConv::ID CallConv)
constexpr LLVM_NODISCARD size_t size() const
size - Get the string size.
void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc, const Function &ContextFunc, const TargetMachine &TM, SmallVectorImpl< MVT > &Params, SmallVectorImpl< MVT > &Results)
unsigned getByValSize() const
Function & getFunction()
Return the LLVM function that this machine code represents.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
unsigned getNumOperands() const
Return the number of values used by this operation.
SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
@ BR
Control flow instructions. These all have token chains.
MCSymbolWasm * getOrCreateFuncrefCallTableSymbol(MCContext &Ctx, const WebAssemblySubtarget *Subtarget)
Returns the __funcref_call_table, for use in funcref calls when lowered to table.set + call_indirect.
Iterator for intrusive lists based on ilist_node.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
static bool IsWebAssemblyGlobal(SDValue Op)
const DataLayout & getDataLayout() const
static Constant * get(Type *Ty, double V)
This returns a ConstantFP, or a vector containing a splat of a ConstantFP, for the specified value in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
constexpr unsigned BitWidth
SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
SDValue getMCSymbol(MCSymbol *Sym, EVT VT)
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
Provides information about what library functions are available for the current target.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
@ ZeroOrOneBooleanContent
MVT getPointerMemTy(const DataLayout &DL, uint32_t AS=0) const override
Return the in-memory pointer type for the given address space, defaults to the pointer type from the ...
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ MOStore
The memory access writes data.
@ ADD
Simple integer binary arithmetic operators.
bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
static SDValue truncateVectorWithNARROW(EVT DstVT, SDValue In, const SDLoc &DL, SelectionDAG &DAG)
EVT getVectorElementType() const
Given a vector type, return the type of each element.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
Function Alias Analysis false
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
@ SHL
Shift and rotation operations.
static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
Align getNonZeroByValAlign() const
bool isWasmVarAddressSpace(unsigned AS)
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
void setMinimumJumpTableEntries(unsigned Val)
Indicate the minimum number of blocks to generate jump tables.
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
std::string to_string(const T &Value)
bool isInConsecutiveRegs() const
Align max(MaybeAlign Lhs, Align Rhs)
static MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
unsigned getAddressSpace() const
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
unsigned getOpcode() const
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
void setLoadExtAction(ArrayRef< unsigned > ExtTypes, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
Type * getValueType() const
const char LLVMTargetMachineRef TM
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
This class represents a function call, abstracting a target machine's calling convention.
MachineFunction & getMachineFunction() const
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
bool isSwiftError() const
const char * createExternalSymbolName(StringRef Name)
Allocate a string and populate it with the given external symbol name.
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
unsigned getBitWidth() const
Get the bit width of this value.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
void setFrameAddressIsTaken(bool T)
bool bitsGE(EVT VT) const
Return true if this has no less bits than VT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
@ SIGN_EXTEND
Conversion operators.
SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, bool isTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes())
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from where P can be anything The alignment inference code cannot handle loads from globals in static non mode because it doesn t look through the extra dyld stub load If you try vec_align ll without relocation model
static Optional< unsigned > getLocalForStackObject(MachineFunction &MF, int FrameIndex)
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
SDValue getSplatValue(SDValue V, bool LegalTypes=false)
If V is a splat vector, return its scalar source operand by extracting that element from the source v...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ ADDE
Carry-using nodes for multiple precision addition and subtraction.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
LLVM Value Representation.
const TargetMachine & getTarget() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
bool isValidAddressSpace(unsigned AS)
static Type * getFloatTy(LLVMContext &C)
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
A Use represents the edge between a Value definition and its users.
static void fail(const SDLoc &DL, SelectionDAG &DAG, const char *Msg)
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
static MVT getIntegerVT(unsigned BitWidth)
static auto integer_fixedlen_vector_valuetypes()
bool IsFixed
IsFixed - Is this a "fixed" value, ie not passed through a vararg "...".