23#include "llvm/IR/IntrinsicsWebAssembly.h"
31#define DEBUG_TYPE "wasm-isel"
32#define PASS_NAME "WebAssembly Instruction Selection"
47 WebAssemblyDAGToDAGISel() =
delete;
55 "********** Function: "
68 std::vector<SDValue> &OutOps)
override;
74#include "WebAssemblyGenDAGISel.inc"
79 bool SelectAddrOperands(
MVT AddrType,
unsigned ConstOpc,
SDValue Op,
86char WebAssemblyDAGToDAGISel::ID;
90void WebAssemblyDAGToDAGISel::PreprocessISelDAG() {
108 ? MF.createExternalSymbolName(
"__cpp_exception")
109 : MF.createExternalSymbolName(
"__c_longjmp");
113void WebAssemblyDAGToDAGISel::Select(
SDNode *
Node) {
115 if (
Node->isMachineOpcode()) {
121 MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout());
122 auto GlobalGetIns = PtrVT == MVT::i64 ? WebAssembly::GLOBAL_GET_I64
123 : WebAssembly::GLOBAL_GET_I32;
128 switch (
Node->getOpcode()) {
135 switch (SyncScopeID) {
140 Fence = CurDAG->getMachineNode(WebAssembly::COMPILER_FENCE,
149 Fence = CurDAG->getMachineNode(
150 WebAssembly::ATOMIC_FENCE,
153 CurDAG->getTargetConstant(0,
DL, MVT::i32),
161 ReplaceNode(
Node, Fence);
162 CurDAG->RemoveDeadNode(
Node);
167 unsigned IntNo =
Node->getConstantOperandVal(0);
169 case Intrinsic::wasm_tls_size: {
171 GlobalGetIns,
DL, PtrVT,
172 CurDAG->getTargetExternalSymbol(
"__tls_size", PtrVT));
173 ReplaceNode(
Node, TLSSize);
177 case Intrinsic::wasm_tls_align: {
179 GlobalGetIns,
DL, PtrVT,
180 CurDAG->getTargetExternalSymbol(
"__tls_align", PtrVT));
181 ReplaceNode(
Node, TLSAlign);
189 unsigned IntNo =
Node->getConstantOperandVal(1);
190 const auto &TLI = CurDAG->getTargetLoweringInfo();
191 MVT PtrVT = TLI.getPointerTy(CurDAG->getDataLayout());
193 case Intrinsic::wasm_tls_base: {
195 GlobalGetIns,
DL, PtrVT, MVT::Other,
196 CurDAG->getTargetExternalSymbol(
"__tls_base", PtrVT),
197 Node->getOperand(0));
198 ReplaceNode(
Node, TLSBase);
202 case Intrinsic::wasm_catch: {
203 int Tag =
Node->getConstantOperandVal(2);
206 CurDAG->getMachineNode(WebAssembly::CATCH,
DL,
223 unsigned IntNo =
Node->getConstantOperandVal(1);
225 case Intrinsic::wasm_throw: {
226 int Tag =
Node->getConstantOperandVal(2);
229 CurDAG->getMachineNode(WebAssembly::THROW,
DL,
236 ReplaceNode(
Node, Throw);
243 case WebAssemblyISD::CALL:
244 case WebAssemblyISD::RET_CALL: {
250 for (
size_t i = 1; i <
Node->getNumOperands(); ++i) {
258 if (i == 1 &&
Op->getOpcode() == WebAssemblyISD::Wrapper) {
260 if (
auto *GlobalOp = dyn_cast<GlobalAddressSDNode>(NewOp.
getNode())) {
262 GlobalOp->getGlobal()->stripPointerCastsAndAliases()))
264 }
else if (isa<ExternalSymbolSDNode>(NewOp.
getNode())) {
274 CurDAG->getMachineNode(WebAssembly::CALL_PARAMS,
DL, MVT::Glue, Ops);
276 unsigned Results =
Node->getOpcode() == WebAssemblyISD::CALL
277 ? WebAssembly::CALL_RESULTS
278 : WebAssembly::RET_CALL_RESULTS;
282 CurDAG->getMachineNode(
Results,
DL,
Node->getVTList(), Link);
283 ReplaceNode(
Node, CallResults);
295bool WebAssemblyDAGToDAGISel::SelectInlineAsmMemoryOperand(
296 const SDValue &Op,
unsigned ConstraintID, std::vector<SDValue> &OutOps) {
297 switch (ConstraintID) {
301 OutOps.push_back(Op);
310bool WebAssemblyDAGToDAGISel::SelectAddrAddOperands(
MVT OffsetType,
SDValue N,
313 assert(
N.getNumOperands() == 2 &&
"Attempting to fold in a non-binary op");
318 if (
N.getOpcode() ==
ISD::ADD && !
N.getNode()->getFlags().hasNoUnsignedWrap())
322 for (
size_t i = 0; i < 2; ++i) {
324 SDValue OtherOp =
N.getOperand(i == 0 ? 1 : 0);
328 CurDAG->getTargetConstant(CN->getZExtValue(),
SDLoc(
N), OffsetType);
336bool WebAssemblyDAGToDAGISel::SelectAddrOperands(
MVT AddrType,
343 if (!
TM.isPositionIndependent()) {
345 if (
Op.getOpcode() == WebAssemblyISD::Wrapper)
346 Op =
Op.getOperand(0);
351 CurDAG->getMachineNode(ConstOpc,
DL, AddrType,
352 CurDAG->getTargetConstant(0,
DL, AddrType)),
369 CurDAG->MaskedValueIsZero(
N->getOperand(0), CN->getAPIntValue());
371 KnownBits Known0 = CurDAG->computeKnownBits(
N->getOperand(0), 0);
372 KnownBits Known1 = CurDAG->computeKnownBits(
N->getOperand(1), 0);
373 OrIsAdd = (~Known0.Zero & ~Known1.Zero) == 0;
376 if (OrIsAdd && SelectAddrAddOperands(AddrType,
N,
Offset,
Addr))
382 Offset = CurDAG->getTargetConstant(CN->getZExtValue(),
DL, AddrType);
384 CurDAG->getMachineNode(ConstOpc,
DL, AddrType,
385 CurDAG->getTargetConstant(0,
DL, AddrType)),
391 Offset = CurDAG->getTargetConstant(0,
DL, AddrType);
398 return SelectAddrOperands(MVT::i32, WebAssembly::CONST_I32, Op,
Offset,
Addr);
403 return SelectAddrOperands(MVT::i64, WebAssembly::CONST_I64, Op,
Offset,
Addr);
410 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
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 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...
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, std::vector< SDValue > &OutOps)
SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode,...
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.
Level
Code generation optimization level.
@ 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.
FunctionPass * createWebAssemblyISelDag(WebAssemblyTargetMachine &TM, CodeGenOpt::Level OptLevel)
This pass converts a legalized DAG into a WebAssembly-specific DAG, ready for instruction scheduling.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.