23#include "llvm/IR/IntrinsicsWebAssembly.h"
31#define DEBUG_TYPE "wasm-isel"
32#define PASS_NAME "WebAssembly Instruction Selection"
47 WebAssemblyDAGToDAGISel() =
delete;
55 "********** Function: "
69 std::vector<SDValue> &OutOps)
override;
75#include "WebAssemblyGenDAGISel.inc"
80 bool SelectAddrOperands(
MVT AddrType,
unsigned ConstOpc,
SDValue Op,
87char WebAssemblyDAGToDAGISel::ID;
91void WebAssemblyDAGToDAGISel::PreprocessISelDAG() {
109 ? MF.createExternalSymbolName(
"__cpp_exception")
110 : MF.createExternalSymbolName(
"__c_longjmp");
114void WebAssemblyDAGToDAGISel::Select(
SDNode *
Node) {
116 if (
Node->isMachineOpcode()) {
122 MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout());
123 auto GlobalGetIns = PtrVT == MVT::i64 ? WebAssembly::GLOBAL_GET_I64
124 : WebAssembly::GLOBAL_GET_I32;
129 switch (
Node->getOpcode()) {
136 switch (SyncScopeID) {
141 Fence = CurDAG->getMachineNode(WebAssembly::COMPILER_FENCE,
150 Fence = CurDAG->getMachineNode(
151 WebAssembly::ATOMIC_FENCE,
154 CurDAG->getTargetConstant(0,
DL, MVT::i32),
162 ReplaceNode(
Node, Fence);
163 CurDAG->RemoveDeadNode(
Node);
168 unsigned IntNo =
Node->getConstantOperandVal(0);
170 case Intrinsic::wasm_tls_size: {
172 GlobalGetIns,
DL, PtrVT,
173 CurDAG->getTargetExternalSymbol(
"__tls_size", PtrVT));
174 ReplaceNode(
Node, TLSSize);
178 case Intrinsic::wasm_tls_align: {
180 GlobalGetIns,
DL, PtrVT,
181 CurDAG->getTargetExternalSymbol(
"__tls_align", PtrVT));
182 ReplaceNode(
Node, TLSAlign);
190 unsigned IntNo =
Node->getConstantOperandVal(1);
191 const auto &TLI = CurDAG->getTargetLoweringInfo();
192 MVT PtrVT = TLI.getPointerTy(CurDAG->getDataLayout());
194 case Intrinsic::wasm_tls_base: {
196 GlobalGetIns,
DL, PtrVT, MVT::Other,
197 CurDAG->getTargetExternalSymbol(
"__tls_base", PtrVT),
198 Node->getOperand(0));
199 ReplaceNode(
Node, TLSBase);
203 case Intrinsic::wasm_catch: {
204 int Tag =
Node->getConstantOperandVal(2);
207 CurDAG->getMachineNode(WebAssembly::CATCH,
DL,
224 unsigned IntNo =
Node->getConstantOperandVal(1);
226 case Intrinsic::wasm_throw: {
227 int Tag =
Node->getConstantOperandVal(2);
230 CurDAG->getMachineNode(WebAssembly::THROW,
DL,
237 ReplaceNode(
Node, Throw);
244 case WebAssemblyISD::CALL:
245 case WebAssemblyISD::RET_CALL: {
251 for (
size_t i = 1; i <
Node->getNumOperands(); ++i) {
259 if (i == 1 &&
Op->getOpcode() == WebAssemblyISD::Wrapper) {
261 if (
auto *GlobalOp = dyn_cast<GlobalAddressSDNode>(NewOp.
getNode())) {
263 GlobalOp->getGlobal()->stripPointerCastsAndAliases()))
265 }
else if (isa<ExternalSymbolSDNode>(NewOp.
getNode())) {
275 CurDAG->getMachineNode(WebAssembly::CALL_PARAMS,
DL, MVT::Glue, Ops);
277 unsigned Results =
Node->getOpcode() == WebAssemblyISD::CALL
278 ? WebAssembly::CALL_RESULTS
279 : WebAssembly::RET_CALL_RESULTS;
283 CurDAG->getMachineNode(
Results,
DL,
Node->getVTList(), Link);
284 ReplaceNode(
Node, CallResults);
296bool WebAssemblyDAGToDAGISel::SelectInlineAsmMemoryOperand(
298 std::vector<SDValue> &OutOps) {
299 switch (ConstraintID) {
300 case InlineAsm::ConstraintCode::m:
303 OutOps.push_back(
Op);
312bool WebAssemblyDAGToDAGISel::SelectAddrAddOperands(
MVT OffsetType,
SDValue N,
315 assert(
N.getNumOperands() == 2 &&
"Attempting to fold in a non-binary op");
320 if (
N.getOpcode() ==
ISD::ADD && !
N.getNode()->getFlags().hasNoUnsignedWrap())
324 for (
size_t i = 0; i < 2; ++i) {
326 SDValue OtherOp =
N.getOperand(i == 0 ? 1 : 0);
330 CurDAG->getTargetConstant(CN->getZExtValue(),
SDLoc(
N), OffsetType);
338bool WebAssemblyDAGToDAGISel::SelectAddrOperands(
MVT AddrType,
345 if (!
TM.isPositionIndependent()) {
347 if (
Op.getOpcode() == WebAssemblyISD::Wrapper)
348 Op =
Op.getOperand(0);
353 CurDAG->getMachineNode(ConstOpc,
DL, AddrType,
354 CurDAG->getTargetConstant(0,
DL, AddrType)),
371 CurDAG->MaskedValueIsZero(
N->getOperand(0), CN->getAPIntValue());
373 KnownBits Known0 = CurDAG->computeKnownBits(
N->getOperand(0), 0);
374 KnownBits Known1 = CurDAG->computeKnownBits(
N->getOperand(1), 0);
375 OrIsAdd = (~Known0.Zero & ~Known1.Zero) == 0;
378 if (OrIsAdd && SelectAddrAddOperands(AddrType,
N,
Offset,
Addr))
384 Offset = CurDAG->getTargetConstant(CN->getZExtValue(),
DL, AddrType);
386 CurDAG->getMachineNode(ConstOpc,
DL, AddrType,
387 CurDAG->getTargetConstant(0,
DL, AddrType)),
393 Offset = CurDAG->getTargetConstant(0,
DL, AddrType);
400 return SelectAddrOperands(MVT::i32, WebAssembly::CONST_I32,
Op,
Offset,
Addr);
405 return SelectAddrOperands(MVT::i64, WebAssembly::CONST_I64,
Op,
Offset,
Addr);
412 return new WebAssemblyDAGToDAGISel(
TM, OptLevel);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu AMDGPU Register Bank Select
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
const char LLVMTargetMachineRef TM
#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...
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
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