23#include "llvm/IR/IntrinsicsWebAssembly.h"
31#define DEBUG_TYPE "wasm-isel"
32#define PASS_NAME "WebAssembly Instruction Selection"
45 WebAssemblyDAGToDAGISel() =
delete;
53 "********** Function: "
67 std::vector<SDValue> &OutOps)
override;
73#include "WebAssemblyGenDAGISel.inc"
78 bool SelectAddrOperands(
MVT AddrType,
unsigned ConstOpc,
SDValue Op,
90 ID, std::make_unique<WebAssemblyDAGToDAGISel>(TM, OptLevel)) {}
94char WebAssemblyDAGToDAGISelLegacy::ID;
99void WebAssemblyDAGToDAGISel::PreprocessISelDAG() {
117 ? MF.createExternalSymbolName(
"__cpp_exception")
118 : MF.createExternalSymbolName(
"__c_longjmp");
122void WebAssemblyDAGToDAGISel::Select(
SDNode *
Node) {
124 if (
Node->isMachineOpcode()) {
130 MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout());
131 auto GlobalGetIns = PtrVT == MVT::i64 ? WebAssembly::GLOBAL_GET_I64
132 : WebAssembly::GLOBAL_GET_I32;
137 switch (
Node->getOpcode()) {
144 switch (SyncScopeID) {
149 Fence = CurDAG->getMachineNode(WebAssembly::COMPILER_FENCE,
158 Fence = CurDAG->getMachineNode(
159 WebAssembly::ATOMIC_FENCE,
162 CurDAG->getTargetConstant(0,
DL, MVT::i32),
170 ReplaceNode(
Node, Fence);
171 CurDAG->RemoveDeadNode(
Node);
176 unsigned IntNo =
Node->getConstantOperandVal(0);
178 case Intrinsic::wasm_tls_size: {
180 GlobalGetIns,
DL, PtrVT,
181 CurDAG->getTargetExternalSymbol(
"__tls_size", PtrVT));
182 ReplaceNode(
Node, TLSSize);
186 case Intrinsic::wasm_tls_align: {
188 GlobalGetIns,
DL, PtrVT,
189 CurDAG->getTargetExternalSymbol(
"__tls_align", PtrVT));
190 ReplaceNode(
Node, TLSAlign);
198 unsigned IntNo =
Node->getConstantOperandVal(1);
199 const auto &TLI = CurDAG->getTargetLoweringInfo();
200 MVT PtrVT = TLI.getPointerTy(CurDAG->getDataLayout());
202 case Intrinsic::wasm_tls_base: {
204 GlobalGetIns,
DL, PtrVT, MVT::Other,
205 CurDAG->getTargetExternalSymbol(
"__tls_base", PtrVT),
206 Node->getOperand(0));
207 ReplaceNode(
Node, TLSBase);
211 case Intrinsic::wasm_catch: {
212 int Tag =
Node->getConstantOperandVal(2);
215 CurDAG->getMachineNode(WebAssembly::CATCH,
DL,
232 unsigned IntNo =
Node->getConstantOperandVal(1);
234 case Intrinsic::wasm_throw: {
235 int Tag =
Node->getConstantOperandVal(2);
238 CurDAG->getMachineNode(WebAssembly::THROW,
DL,
245 ReplaceNode(
Node, Throw);
252 case WebAssemblyISD::CALL:
253 case WebAssemblyISD::RET_CALL: {
259 for (
size_t i = 1; i <
Node->getNumOperands(); ++i) {
267 if (i == 1 &&
Op->getOpcode() == WebAssemblyISD::Wrapper) {
269 if (
auto *GlobalOp = dyn_cast<GlobalAddressSDNode>(NewOp.
getNode())) {
271 GlobalOp->getGlobal()->stripPointerCastsAndAliases()))
273 }
else if (isa<ExternalSymbolSDNode>(NewOp.
getNode())) {
283 CurDAG->getMachineNode(WebAssembly::CALL_PARAMS,
DL, MVT::Glue, Ops);
285 unsigned Results =
Node->getOpcode() == WebAssemblyISD::CALL
286 ? WebAssembly::CALL_RESULTS
287 : WebAssembly::RET_CALL_RESULTS;
291 CurDAG->getMachineNode(
Results,
DL,
Node->getVTList(), Link);
292 ReplaceNode(
Node, CallResults);
304bool WebAssemblyDAGToDAGISel::SelectInlineAsmMemoryOperand(
306 std::vector<SDValue> &OutOps) {
307 switch (ConstraintID) {
308 case InlineAsm::ConstraintCode::m:
311 OutOps.push_back(
Op);
320bool WebAssemblyDAGToDAGISel::SelectAddrAddOperands(
MVT OffsetType,
SDValue N,
323 assert(
N.getNumOperands() == 2 &&
"Attempting to fold in a non-binary op");
328 if (
N.getOpcode() ==
ISD::ADD && !
N.getNode()->getFlags().hasNoUnsignedWrap())
332 for (
size_t i = 0; i < 2; ++i) {
334 SDValue OtherOp =
N.getOperand(i == 0 ? 1 : 0);
338 CurDAG->getTargetConstant(CN->getZExtValue(),
SDLoc(
N), OffsetType);
346bool WebAssemblyDAGToDAGISel::SelectAddrOperands(
MVT AddrType,
353 if (!
TM.isPositionIndependent()) {
355 if (
Op.getOpcode() == WebAssemblyISD::Wrapper)
356 Op =
Op.getOperand(0);
361 CurDAG->getMachineNode(ConstOpc,
DL, AddrType,
362 CurDAG->getTargetConstant(0,
DL, AddrType)),
379 CurDAG->MaskedValueIsZero(
N->getOperand(0), CN->getAPIntValue());
381 KnownBits Known0 = CurDAG->computeKnownBits(
N->getOperand(0), 0);
382 KnownBits Known1 = CurDAG->computeKnownBits(
N->getOperand(1), 0);
383 OrIsAdd = (~Known0.Zero & ~Known1.Zero) == 0;
386 if (OrIsAdd && SelectAddrAddOperands(AddrType,
N,
Offset,
Addr))
392 Offset = CurDAG->getTargetConstant(CN->getZExtValue(),
DL, AddrType);
394 CurDAG->getMachineNode(ConstOpc,
DL, AddrType,
395 CurDAG->getTargetConstant(0,
DL, AddrType)),
401 Offset = CurDAG->getTargetConstant(0,
DL, AddrType);
408 return SelectAddrOperands(MVT::i32, WebAssembly::CONST_I32,
Op,
Offset,
Addr);
413 return SelectAddrOperands(MVT::i64, WebAssembly::CONST_I64,
Op,
Offset,
Addr);
420 return new WebAssemblyDAGToDAGISelLegacy(TM, OptLevel);
amdgpu 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.
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