LLVM  13.0.0git
WebAssemblyISelDAGToDAG.cpp
Go to the documentation of this file.
1 //- WebAssemblyISelDAGToDAG.cpp - A dag to dag inst selector for WebAssembly -//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file defines an instruction selector for the WebAssembly target.
11 ///
12 //===----------------------------------------------------------------------===//
13 
15 #include "WebAssembly.h"
18 #include "llvm/IR/DiagnosticInfo.h"
19 #include "llvm/IR/Function.h" // To access function attributes.
20 #include "llvm/IR/IntrinsicsWebAssembly.h"
21 #include "llvm/Support/Debug.h"
22 #include "llvm/Support/KnownBits.h"
25 using namespace llvm;
26 
27 #define DEBUG_TYPE "wasm-isel"
28 
29 //===--------------------------------------------------------------------===//
30 /// WebAssembly-specific code to select WebAssembly machine instructions for
31 /// SelectionDAG operations.
32 ///
33 namespace {
34 class WebAssemblyDAGToDAGISel final : public SelectionDAGISel {
35  /// Keep a pointer to the WebAssemblySubtarget around so that we can make the
36  /// right decision when generating code for different targets.
37  const WebAssemblySubtarget *Subtarget;
38 
39 public:
40  WebAssemblyDAGToDAGISel(WebAssemblyTargetMachine &TM,
41  CodeGenOpt::Level OptLevel)
42  : SelectionDAGISel(TM, OptLevel), Subtarget(nullptr) {
43  }
44 
45  StringRef getPassName() const override {
46  return "WebAssembly Instruction Selection";
47  }
48 
49  bool runOnMachineFunction(MachineFunction &MF) override {
50  LLVM_DEBUG(dbgs() << "********** ISelDAGToDAG **********\n"
51  "********** Function: "
52  << MF.getName() << '\n');
53 
54  Subtarget = &MF.getSubtarget<WebAssemblySubtarget>();
55 
57  }
58 
59  void Select(SDNode *Node) override;
60 
61  bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
62  std::vector<SDValue> &OutOps) override;
63 
64 // Include the pieces autogenerated from the target description.
65 #include "WebAssemblyGenDAGISel.inc"
66 
67 private:
68  // add select functions here...
69 };
70 } // end anonymous namespace
71 
73  // If we have a custom node, we already have selected!
74  if (Node->isMachineOpcode()) {
75  LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
76  Node->setNodeId(-1);
77  return;
78  }
79 
80  MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout());
81  auto GlobalGetIns = PtrVT == MVT::i64 ? WebAssembly::GLOBAL_GET_I64
82  : WebAssembly::GLOBAL_GET_I32;
83 
84  // Few custom selection stuff.
85  SDLoc DL(Node);
86  MachineFunction &MF = CurDAG->getMachineFunction();
87  switch (Node->getOpcode()) {
88  case ISD::ATOMIC_FENCE: {
90  break;
91 
92  uint64_t SyncScopeID =
93  cast<ConstantSDNode>(Node->getOperand(2).getNode())->getZExtValue();
94  MachineSDNode *Fence = nullptr;
95  switch (SyncScopeID) {
97  // We lower a single-thread fence to a pseudo compiler barrier instruction
98  // preventing instruction reordering. This will not be emitted in final
99  // binary.
100  Fence = CurDAG->getMachineNode(WebAssembly::COMPILER_FENCE,
101  DL, // debug loc
102  MVT::Other, // outchain type
103  Node->getOperand(0) // inchain
104  );
105  break;
106  case SyncScope::System:
107  // Currently wasm only supports sequentially consistent atomics, so we
108  // always set the order to 0 (sequentially consistent).
109  Fence = CurDAG->getMachineNode(
111  DL, // debug loc
112  MVT::Other, // outchain type
113  CurDAG->getTargetConstant(0, DL, MVT::i32), // order
114  Node->getOperand(0) // inchain
115  );
116  break;
117  default:
118  llvm_unreachable("Unknown scope!");
119  }
120 
121  ReplaceNode(Node, Fence);
122  CurDAG->RemoveDeadNode(Node);
123  return;
124  }
125 
127  unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(0))->getZExtValue();
128  switch (IntNo) {
129  case Intrinsic::wasm_tls_size: {
130  MachineSDNode *TLSSize = CurDAG->getMachineNode(
131  GlobalGetIns, DL, PtrVT,
132  CurDAG->getTargetExternalSymbol("__tls_size", PtrVT));
133  ReplaceNode(Node, TLSSize);
134  return;
135  }
136  case Intrinsic::wasm_tls_align: {
137  MachineSDNode *TLSAlign = CurDAG->getMachineNode(
138  GlobalGetIns, DL, PtrVT,
139  CurDAG->getTargetExternalSymbol("__tls_align", PtrVT));
140  ReplaceNode(Node, TLSAlign);
141  return;
142  }
143  }
144  break;
145  }
146  case ISD::INTRINSIC_W_CHAIN: {
147  unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
148  switch (IntNo) {
149  case Intrinsic::wasm_tls_base: {
150  MachineSDNode *TLSBase = CurDAG->getMachineNode(
151  GlobalGetIns, DL, PtrVT, MVT::Other,
152  CurDAG->getTargetExternalSymbol("__tls_base", PtrVT),
153  Node->getOperand(0));
154  ReplaceNode(Node, TLSBase);
155  return;
156  }
157  }
158  break;
159  }
161  case WebAssemblyISD::RET_CALL: {
162  // CALL has both variable operands and variable results, but ISel only
163  // supports one or the other. Split calls into two nodes glued together, one
164  // for the operands and one for the results. These two nodes will be
165  // recombined in a custom inserter hook into a single MachineInstr.
167  for (size_t i = 1; i < Node->getNumOperands(); ++i) {
168  SDValue Op = Node->getOperand(i);
169  if (i == 1 && Op->getOpcode() == WebAssemblyISD::Wrapper)
170  Op = Op->getOperand(0);
171  Ops.push_back(Op);
172  }
173 
174  // Add the chain last
175  Ops.push_back(Node->getOperand(0));
176  MachineSDNode *CallParams =
177  CurDAG->getMachineNode(WebAssembly::CALL_PARAMS, DL, MVT::Glue, Ops);
178 
179  unsigned Results = Node->getOpcode() == WebAssemblyISD::CALL
180  ? WebAssembly::CALL_RESULTS
181  : WebAssembly::RET_CALL_RESULTS;
182 
183  SDValue Link(CallParams, 0);
184  MachineSDNode *CallResults =
185  CurDAG->getMachineNode(Results, DL, Node->getVTList(), Link);
186  ReplaceNode(Node, CallResults);
187  return;
188  }
189 
190  default:
191  break;
192  }
193 
194  // Select the default instruction.
195  SelectCode(Node);
196 }
197 
198 bool WebAssemblyDAGToDAGISel::SelectInlineAsmMemoryOperand(
199  const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) {
200  switch (ConstraintID) {
202  // We just support simple memory operands that just have a single address
203  // operand and need no special handling.
204  OutOps.push_back(Op);
205  return false;
206  default:
207  break;
208  }
209 
210  return true;
211 }
212 
213 /// This pass converts a legalized DAG into a WebAssembly-specific DAG, ready
214 /// for instruction scheduling.
216  CodeGenOpt::Level OptLevel) {
217  return new WebAssemblyDAGToDAGISel(TM, OptLevel);
218 }
i
i
Definition: README.txt:29
MathExtras.h
llvm
This class represents lattice values for constants.
Definition: AllocatorList.h:23
WebAssembly.h
llvm::SystemZISD::TM
@ TM
Definition: SystemZISelLowering.h:65
llvm::SDLoc
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Definition: SelectionDAGNodes.h:1078
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
Wrapper
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
Definition: AMDGPUAliasAnalysis.cpp:30
llvm::MachineSDNode
An SDNode that represents everything that will be needed to construct a MachineInstr.
Definition: SelectionDAGNodes.h:2517
llvm::createWebAssemblyISelDag
FunctionPass * createWebAssemblyISelDag(WebAssemblyTargetMachine &TM, CodeGenOpt::Level OptLevel)
This pass converts a legalized DAG into a WebAssembly-specific DAG, ready for instruction scheduling.
Definition: WebAssemblyISelDAGToDAG.cpp:215
llvm::SDNode
Represents one node in the SelectionDAG.
Definition: SelectionDAGNodes.h:455
llvm::MVT::Glue
@ Glue
Definition: MachineValueType.h:240
llvm::AArch64ISD::CALL
@ CALL
Definition: AArch64ISelLowering.h:52
Results
Function Alias Analysis Results
Definition: AliasAnalysis.cpp:847
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:894
WebAssemblyTargetMachine.h
llvm::codeview::Link
@ Link
Definition: CodeView.h:151
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:122
KnownBits.h
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
llvm::WebAssemblyTargetMachine
Definition: WebAssemblyTargetMachine.h:23
llvm::SyncScope::System
@ System
Synchronized with respect to all concurrently executing threads.
Definition: LLVMContext.h:58
WebAssemblyMCTargetDesc.h
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition: MachineFunction.h:555
llvm::ISD::ATOMIC_FENCE
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
Definition: ISDOpcodes.h:1060
llvm::MachineFunction::getName
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Definition: MachineFunction.cpp:522
llvm::MVT::Other
@ Other
Definition: MachineValueType.h:39
llvm::MVT
Machine Value Type.
Definition: MachineValueType.h:30
llvm::MachineFunction
Definition: MachineFunction.h:227
SelectionDAGISel.h
llvm::SyncScope::SingleThread
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
Definition: LLVMContext.h:55
llvm::MVT::i64
@ i64
Definition: MachineValueType.h:44
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:136
DL
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Definition: AArch64SLSHardening.cpp:76
llvm::WebAssemblySubtarget
Definition: WebAssemblySubtarget.h:35
llvm::CodeGenOpt::Level
Level
Definition: CodeGen.h:52
llvm::ISD::INTRINSIC_WO_CHAIN
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition: ISDOpcodes.h:177
llvm::MCID::Select
@ Select
Definition: MCInstrDesc.h:163
llvm::InlineAsm::Constraint_m
@ Constraint_m
Definition: InlineAsm.h:245
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:302
DiagnosticInfo.h
Function.h
llvm::MVT::i32
@ i32
Definition: MachineValueType.h:43
llvm::SDValue
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
Definition: SelectionDAGNodes.h:138
llvm::SelectionDAGISel
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
Definition: SelectionDAGISel.h:39
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
llvm::ISD::INTRINSIC_W_CHAIN
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition: ISDOpcodes.h:185
llvm::WebAssemblySubtarget::hasAtomics
bool hasAtomics() const
Definition: WebAssemblySubtarget.h:96
raw_ostream.h
llvm::SelectionDAGISel::runOnMachineFunction
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Definition: SelectionDAGISel.cpp:411
Debug.h