23#include "llvm/IR/IntrinsicsWebAssembly.h"
30#define DEBUG_TYPE "wasm-isel"
31#define PASS_NAME "WebAssembly Instruction Selection"
44 WebAssemblyDAGToDAGISel() =
delete;
52 "********** Function: "
66 std::vector<SDValue> &OutOps)
override;
72#include "WebAssemblyGenDAGISel.inc"
77 bool SelectAddrOperands(
MVT AddrType,
unsigned ConstOpc,
SDValue Op,
89 ID, std::make_unique<WebAssemblyDAGToDAGISel>(TM, OptLevel)) {}
93char WebAssemblyDAGToDAGISelLegacy::ID;
98void WebAssemblyDAGToDAGISel::PreprocessISelDAG() {
116 ? MF.createExternalSymbolName(
"__cpp_exception")
117 : MF.createExternalSymbolName(
"__c_longjmp");
121void WebAssemblyDAGToDAGISel::Select(
SDNode *
Node) {
123 if (
Node->isMachineOpcode()) {
129 MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout());
130 auto GlobalGetIns = PtrVT == MVT::i64 ? WebAssembly::GLOBAL_GET_I64
131 : WebAssembly::GLOBAL_GET_I32;
136 switch (
Node->getOpcode()) {
143 switch (SyncScopeID) {
148 Fence = CurDAG->getMachineNode(WebAssembly::COMPILER_FENCE,
157 Fence = CurDAG->getMachineNode(
158 WebAssembly::ATOMIC_FENCE,
161 CurDAG->getTargetConstant(0,
DL, MVT::i32),
169 ReplaceNode(
Node, Fence);
170 CurDAG->RemoveDeadNode(
Node);
175 unsigned IntNo =
Node->getConstantOperandVal(0);
177 case Intrinsic::wasm_tls_size: {
179 GlobalGetIns,
DL, PtrVT,
180 CurDAG->getTargetExternalSymbol(
"__tls_size", PtrVT));
181 ReplaceNode(
Node, TLSSize);
185 case Intrinsic::wasm_tls_align: {
187 GlobalGetIns,
DL, PtrVT,
188 CurDAG->getTargetExternalSymbol(
"__tls_align", PtrVT));
189 ReplaceNode(
Node, TLSAlign);
197 unsigned IntNo =
Node->getConstantOperandVal(1);
198 const auto &TLI = CurDAG->getTargetLoweringInfo();
199 MVT PtrVT = TLI.getPointerTy(CurDAG->getDataLayout());
201 case Intrinsic::wasm_tls_base: {
203 GlobalGetIns,
DL, PtrVT, MVT::Other,
204 CurDAG->getTargetExternalSymbol(
"__tls_base", PtrVT),
205 Node->getOperand(0));
206 ReplaceNode(
Node, TLSBase);
210 case Intrinsic::wasm_catch: {
211 int Tag =
Node->getConstantOperandVal(2);
215 : WebAssembly::CATCH_LEGACY;
217 CurDAG->getMachineNode(CatchOpcode,
DL,
234 unsigned IntNo =
Node->getConstantOperandVal(1);
236 case Intrinsic::wasm_throw: {
237 int Tag =
Node->getConstantOperandVal(2);
240 CurDAG->getMachineNode(WebAssembly::THROW,
DL,
247 ReplaceNode(
Node, Throw);
250 case Intrinsic::wasm_rethrow: {
254 WebAssembly::RETHROW,
DL,
257 CurDAG->getConstant(0,
DL, MVT::i32),
260 ReplaceNode(
Node, Rethrow);
267 case WebAssemblyISD::CALL:
268 case WebAssemblyISD::RET_CALL: {
274 for (
size_t i = 1; i <
Node->getNumOperands(); ++i) {
282 if (i == 1 &&
Op->getOpcode() == WebAssemblyISD::Wrapper) {
284 if (
auto *GlobalOp = dyn_cast<GlobalAddressSDNode>(NewOp.
getNode())) {
286 GlobalOp->getGlobal()->stripPointerCastsAndAliases()))
288 }
else if (isa<ExternalSymbolSDNode>(NewOp.
getNode())) {
298 CurDAG->getMachineNode(WebAssembly::CALL_PARAMS,
DL, MVT::Glue, Ops);
300 unsigned Results =
Node->getOpcode() == WebAssemblyISD::CALL
301 ? WebAssembly::CALL_RESULTS
302 : WebAssembly::RET_CALL_RESULTS;
306 CurDAG->getMachineNode(
Results,
DL,
Node->getVTList(), Link);
307 ReplaceNode(
Node, CallResults);
319bool WebAssemblyDAGToDAGISel::SelectInlineAsmMemoryOperand(
321 std::vector<SDValue> &OutOps) {
322 switch (ConstraintID) {
323 case InlineAsm::ConstraintCode::m:
326 OutOps.push_back(
Op);
335bool WebAssemblyDAGToDAGISel::SelectAddrAddOperands(
MVT OffsetType,
SDValue N,
338 assert(
N.getNumOperands() == 2 &&
"Attempting to fold in a non-binary op");
343 if (
N.getOpcode() ==
ISD::ADD && !
N.getNode()->getFlags().hasNoUnsignedWrap())
347 for (
size_t i = 0; i < 2; ++i) {
349 SDValue OtherOp =
N.getOperand(i == 0 ? 1 : 0);
353 CurDAG->getTargetConstant(CN->getZExtValue(),
SDLoc(
N), OffsetType);
361bool WebAssemblyDAGToDAGISel::SelectAddrOperands(
MVT AddrType,
368 if (!
TM.isPositionIndependent()) {
370 if (
Op.getOpcode() == WebAssemblyISD::Wrapper)
371 Op =
Op.getOperand(0);
376 CurDAG->getMachineNode(ConstOpc,
DL, AddrType,
377 CurDAG->getTargetConstant(0,
DL, AddrType)),
394 CurDAG->MaskedValueIsZero(
N->getOperand(0), CN->getAPIntValue());
396 KnownBits Known0 = CurDAG->computeKnownBits(
N->getOperand(0), 0);
397 KnownBits Known1 = CurDAG->computeKnownBits(
N->getOperand(1), 0);
398 OrIsAdd = (~Known0.Zero & ~Known1.Zero) == 0;
401 if (OrIsAdd && SelectAddrAddOperands(AddrType,
N,
Offset,
Addr))
407 Offset = CurDAG->getTargetConstant(CN->getZExtValue(),
DL, AddrType);
409 CurDAG->getMachineNode(ConstOpc,
DL, AddrType,
410 CurDAG->getTargetConstant(0,
DL, AddrType)),
416 Offset = CurDAG->getTargetConstant(0,
DL, AddrType);
423 return SelectAddrOperands(MVT::i32, WebAssembly::CONST_I32,
Op,
Offset,
Addr);
428 return SelectAddrOperands(MVT::i64, WebAssembly::CONST_I64,
Op,
Offset,
Addr);
435 return new WebAssemblyDAGToDAGISelLegacy(TM, OptLevel);
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static SDValue getTagSymNode(int Tag, SelectionDAG *DAG)
This file defines the interfaces that WebAssembly uses to lower LLVM code into a selection DAG.
This file provides WebAssembly-specific target descriptions.
This file declares the WebAssembly-specific subclass of TargetMachine.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.
DEMANGLE_DUMP_METHOD void dump() const
This class represents an Operation in the Expression.
FunctionPass class - This class is used to implement most global optimizations.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
int getObjectIndexEnd() const
Return one past the maximum frame object index.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
An SDNode that represents everything that will be needed to construct a MachineInstr.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, std::vector< SDValue > &OutOps)
SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode,...
virtual void PreprocessISelDAG()
PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...
virtual bool runOnMachineFunction(MachineFunction &mf)
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
const TargetLowering & getTargetLoweringInfo() const
const DataLayout & getDataLayout() const
MachineFunction & getMachineFunction() const
SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static std::optional< unsigned > getLocalForStackObject(MachineFunction &MF, int FrameIndex)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ ADD
Simple integer binary arithmetic operators.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
@ System
Synchronized with respect to all concurrently executing threads.
cl::opt< bool > WasmEnableExnref
This is an optimization pass for GlobalISel generic memory operations.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createWebAssemblyISelDag(WebAssemblyTargetMachine &TM, CodeGenOptLevel OptLevel)
This pass converts a legalized DAG into a WebAssembly-specific DAG, ready for instruction scheduling.
CodeGenOptLevel
Code generation optimization level.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
DWARFExpression::Operation Op