LLVM 23.0.0git
MSP430ISelDAGToDAG.cpp
Go to the documentation of this file.
1//===-- MSP430ISelDAGToDAG.cpp - A dag to dag inst selector for MSP430 ----===//
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// This file defines an instruction selector for the MSP430 target.
10//
11//===----------------------------------------------------------------------===//
12
13#include "MSP430.h"
15#include "MSP430TargetMachine.h"
20#include "llvm/Config/llvm-config.h"
21#include "llvm/IR/Constants.h"
22#include "llvm/IR/Function.h"
23#include "llvm/Support/Debug.h"
26using namespace llvm;
27
28#define DEBUG_TYPE "msp430-isel"
29#define PASS_NAME "MSP430 DAG->DAG Pattern Instruction Selection"
30
31namespace {
32 struct MSP430ISelAddressMode {
33 enum {
34 RegBase,
35 FrameIndexBase
36 } BaseType = RegBase;
37
38 struct { // This is really a union, discriminated by BaseType!
40 int FrameIndex = 0;
41 } Base;
42
43 int16_t Disp = 0;
44 const GlobalValue *GV = nullptr;
45 const Constant *CP = nullptr;
46 const BlockAddress *BlockAddr = nullptr;
47 const char *ES = nullptr;
48 int JT = -1;
49 Align Alignment; // CP alignment.
50
51 MSP430ISelAddressMode() = default;
52
53 bool hasSymbolicDisplacement() const {
54 return GV != nullptr || CP != nullptr || ES != nullptr || JT != -1;
55 }
56
57#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
58 LLVM_DUMP_METHOD void dump() {
59 errs() << "MSP430ISelAddressMode " << this << '\n';
60 if (BaseType == RegBase && Base.Reg.getNode() != nullptr) {
61 errs() << "Base.Reg ";
62 Base.Reg.getNode()->dump();
63 } else if (BaseType == FrameIndexBase) {
64 errs() << " Base.FrameIndex " << Base.FrameIndex << '\n';
65 }
66 errs() << " Disp " << Disp << '\n';
67 if (GV) {
68 errs() << "GV ";
69 GV->dump();
70 } else if (CP) {
71 errs() << " CP ";
72 CP->dump();
73 errs() << " Align" << Alignment.value() << '\n';
74 } else if (ES) {
75 errs() << "ES ";
76 errs() << ES << '\n';
77 } else if (JT != -1)
78 errs() << " JT" << JT << " Align" << Alignment.value() << '\n';
79 }
80#endif
81 };
82}
83
84/// MSP430DAGToDAGISel - MSP430 specific code to select MSP430 machine
85/// instructions for SelectionDAG operations.
86///
87namespace {
88 class MSP430DAGToDAGISel : public SelectionDAGISel {
89 public:
90 MSP430DAGToDAGISel() = delete;
91
92 MSP430DAGToDAGISel(MSP430TargetMachine &TM, CodeGenOptLevel OptLevel)
93 : SelectionDAGISel(TM, OptLevel) {}
94
95 private:
96 bool MatchAddress(SDValue N, MSP430ISelAddressMode &AM);
97 bool MatchWrapper(SDValue N, MSP430ISelAddressMode &AM);
98 bool MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM);
99
100 bool SelectInlineAsmMemoryOperand(const SDValue &Op,
101 InlineAsm::ConstraintCode ConstraintID,
102 std::vector<SDValue> &OutOps) override;
103
104 // Include the pieces autogenerated from the target description.
105 #include "MSP430GenDAGISel.inc"
106
107 // Main method to transform nodes into machine nodes.
108 void Select(SDNode *N) override;
109
110 bool tryIndexedLoad(SDNode *Op);
111 bool tryIndexedBinOp(SDNode *Op, SDValue N1, SDValue N2, unsigned Opc8,
112 unsigned Opc16);
113
114 bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Disp);
115 };
116
117 class MSP430DAGToDAGISelLegacy : public SelectionDAGISelLegacy {
118 public:
119 static char ID;
120 MSP430DAGToDAGISelLegacy(MSP430TargetMachine &TM, CodeGenOptLevel OptLevel)
121 : SelectionDAGISelLegacy(
122 ID, std::make_unique<MSP430DAGToDAGISel>(TM, OptLevel)) {}
123 };
124} // end anonymous namespace
125
126char MSP430DAGToDAGISelLegacy::ID;
127
128INITIALIZE_PASS(MSP430DAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)
129
130/// createMSP430ISelDag - This pass converts a legalized DAG into a
131/// MSP430-specific DAG, ready for instruction scheduling.
132///
134 CodeGenOptLevel OptLevel) {
135 return new MSP430DAGToDAGISelLegacy(TM, OptLevel);
136}
137
139 CodeGenOptLevel OptLevel)
140 : SelectionDAGISelPass(std::make_unique<MSP430DAGToDAGISel>(TM, OptLevel)) {
141}
142
143/// MatchWrapper - Try to match MSP430ISD::Wrapper node into an addressing mode.
144/// These wrap things that will resolve down into a symbol reference. If no
145/// match is possible, this returns true, otherwise it returns false.
146bool MSP430DAGToDAGISel::MatchWrapper(SDValue N, MSP430ISelAddressMode &AM) {
147 // If the addressing mode already has a symbol as the displacement, we can
148 // never match another symbol.
149 if (AM.hasSymbolicDisplacement())
150 return true;
151
152 SDValue N0 = N.getOperand(0);
153
155 AM.GV = G->getGlobal();
156 AM.Disp += G->getOffset();
157 //AM.SymbolFlags = G->getTargetFlags();
159 AM.CP = CP->getConstVal();
160 AM.Alignment = CP->getAlign();
161 AM.Disp += CP->getOffset();
162 //AM.SymbolFlags = CP->getTargetFlags();
164 AM.ES = S->getSymbol();
165 //AM.SymbolFlags = S->getTargetFlags();
166 } else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) {
167 AM.JT = J->getIndex();
168 //AM.SymbolFlags = J->getTargetFlags();
169 } else {
170 AM.BlockAddr = cast<BlockAddressSDNode>(N0)->getBlockAddress();
171 //AM.SymbolFlags = cast<BlockAddressSDNode>(N0)->getTargetFlags();
172 }
173 return false;
174}
175
176/// MatchAddressBase - Helper for MatchAddress. Add the specified node to the
177/// specified addressing mode without any further recursion.
178bool MSP430DAGToDAGISel::MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM) {
179 // Is the base register already occupied?
180 if (AM.BaseType != MSP430ISelAddressMode::RegBase || AM.Base.Reg.getNode()) {
181 // If so, we cannot select it.
182 return true;
183 }
184
185 // Default, generate it as a register.
186 AM.BaseType = MSP430ISelAddressMode::RegBase;
187 AM.Base.Reg = N;
188 return false;
189}
190
191bool MSP430DAGToDAGISel::MatchAddress(SDValue N, MSP430ISelAddressMode &AM) {
192 LLVM_DEBUG(errs() << "MatchAddress: "; AM.dump());
193
194 switch (N.getOpcode()) {
195 default: break;
196 case ISD::Constant: {
197 uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue();
198 AM.Disp += Val;
199 return false;
200 }
201
202 case MSP430ISD::Wrapper:
203 if (!MatchWrapper(N, AM))
204 return false;
205 break;
206
207 case ISD::FrameIndex:
208 if (AM.BaseType == MSP430ISelAddressMode::RegBase
209 && AM.Base.Reg.getNode() == nullptr) {
210 AM.BaseType = MSP430ISelAddressMode::FrameIndexBase;
211 AM.Base.FrameIndex = cast<FrameIndexSDNode>(N)->getIndex();
212 return false;
213 }
214 break;
215
216 case ISD::ADD: {
217 MSP430ISelAddressMode Backup = AM;
218 if (!MatchAddress(N.getNode()->getOperand(0), AM) &&
219 !MatchAddress(N.getNode()->getOperand(1), AM))
220 return false;
221 AM = Backup;
222 if (!MatchAddress(N.getNode()->getOperand(1), AM) &&
223 !MatchAddress(N.getNode()->getOperand(0), AM))
224 return false;
225 AM = Backup;
226
227 break;
228 }
229
230 case ISD::OR:
231 // Handle "X | C" as "X + C" iff X is known to have C bits clear.
232 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
233 MSP430ISelAddressMode Backup = AM;
234 uint64_t Offset = CN->getSExtValue();
235 // Start with the LHS as an addr mode.
236 if (!MatchAddress(N.getOperand(0), AM) &&
237 // Address could not have picked a GV address for the displacement.
238 AM.GV == nullptr &&
239 // Check to see if the LHS & C is zero.
240 CurDAG->MaskedValueIsZero(N.getOperand(0), CN->getAPIntValue())) {
241 AM.Disp += Offset;
242 return false;
243 }
244 AM = Backup;
245 }
246 break;
247 }
248
249 return MatchAddressBase(N, AM);
250}
251
252/// SelectAddr - returns true if it is able pattern match an addressing mode.
253/// It returns the operands which make up the maximal addressing mode it can
254/// match by reference.
255bool MSP430DAGToDAGISel::SelectAddr(SDValue N,
256 SDValue &Base, SDValue &Disp) {
257 MSP430ISelAddressMode AM;
258
259 if (MatchAddress(N, AM))
260 return false;
261
262 if (AM.BaseType == MSP430ISelAddressMode::RegBase)
263 if (!AM.Base.Reg.getNode())
264 AM.Base.Reg = CurDAG->getRegister(MSP430::SR, MVT::i16);
265
266 Base = (AM.BaseType == MSP430ISelAddressMode::FrameIndexBase)
267 ? CurDAG->getTargetFrameIndex(
268 AM.Base.FrameIndex,
269 N.getValueType())
270 : AM.Base.Reg;
271
272 if (AM.GV)
273 Disp = CurDAG->getTargetGlobalAddress(AM.GV, SDLoc(N),
274 MVT::i16, AM.Disp,
275 0/*AM.SymbolFlags*/);
276 else if (AM.CP)
277 Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i16, AM.Alignment, AM.Disp,
278 0 /*AM.SymbolFlags*/);
279 else if (AM.ES)
280 Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i16, 0/*AM.SymbolFlags*/);
281 else if (AM.JT != -1)
282 Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i16, 0/*AM.SymbolFlags*/);
283 else if (AM.BlockAddr)
284 Disp = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, 0,
285 0/*AM.SymbolFlags*/);
286 else
287 Disp = CurDAG->getSignedTargetConstant(AM.Disp, SDLoc(N), MVT::i16);
288
289 return true;
290}
291
292bool MSP430DAGToDAGISel::SelectInlineAsmMemoryOperand(
293 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
294 std::vector<SDValue> &OutOps) {
295 SDValue Op0, Op1;
296 switch (ConstraintID) {
297 default: return true;
298 case InlineAsm::ConstraintCode::m: // memory
299 if (!SelectAddr(Op, Op0, Op1))
300 return true;
301 break;
302 }
303
304 OutOps.push_back(Op0);
305 OutOps.push_back(Op1);
306 return false;
307}
308
309static bool isValidIndexedLoad(const LoadSDNode *LD) {
310 ISD::MemIndexedMode AM = LD->getAddressingMode();
311 if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD)
312 return false;
313
314 EVT VT = LD->getMemoryVT();
315
316 switch (VT.getSimpleVT().SimpleTy) {
317 case MVT::i8:
318 if (LD->getOffset()->getAsZExtVal() != 1)
319 return false;
320
321 break;
322 case MVT::i16:
323 if (LD->getOffset()->getAsZExtVal() != 2)
324 return false;
325
326 break;
327 default:
328 return false;
329 }
330
331 return true;
332}
333
334bool MSP430DAGToDAGISel::tryIndexedLoad(SDNode *N) {
336 if (!isValidIndexedLoad(LD))
337 return false;
338
339 MVT VT = LD->getMemoryVT().getSimpleVT();
340
341 unsigned Opcode = 0;
342 switch (VT.SimpleTy) {
343 case MVT::i8:
344 Opcode = MSP430::MOV8rp;
345 break;
346 case MVT::i16:
347 Opcode = MSP430::MOV16rp;
348 break;
349 default:
350 return false;
351 }
352
353 ReplaceNode(N,
354 CurDAG->getMachineNode(Opcode, SDLoc(N), VT, MVT::i16, MVT::Other,
355 LD->getBasePtr(), LD->getChain()));
356 return true;
357}
358
359bool MSP430DAGToDAGISel::tryIndexedBinOp(SDNode *Op, SDValue N1, SDValue N2,
360 unsigned Opc8, unsigned Opc16) {
361 if (N1.getOpcode() == ISD::LOAD &&
362 N1.hasOneUse() &&
363 IsLegalToFold(N1, Op, Op, OptLevel)) {
365 if (!isValidIndexedLoad(LD))
366 return false;
367
368 MVT VT = LD->getMemoryVT().getSimpleVT();
369 unsigned Opc = (VT == MVT::i16 ? Opc16 : Opc8);
370 MachineMemOperand *MemRef = cast<MemSDNode>(N1)->getMemOperand();
371 SDValue Ops0[] = { N2, LD->getBasePtr(), LD->getChain() };
372 SDNode *ResNode =
373 CurDAG->SelectNodeTo(Op, Opc, VT, MVT::i16, MVT::Other, Ops0);
374 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {MemRef});
375 // Transfer chain.
376 ReplaceUses(SDValue(N1.getNode(), 2), SDValue(ResNode, 2));
377 // Transfer writeback.
378 ReplaceUses(SDValue(N1.getNode(), 1), SDValue(ResNode, 1));
379 return true;
380 }
381
382 return false;
383}
384
385
386void MSP430DAGToDAGISel::Select(SDNode *Node) {
387 SDLoc dl(Node);
388
389 // If we have a custom node, we already have selected!
390 if (Node->isMachineOpcode()) {
391 LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
392 Node->setNodeId(-1);
393 return;
394 }
395
396 // Few custom selection stuff.
397 switch (Node->getOpcode()) {
398 default: break;
399 case ISD::FrameIndex: {
400 assert(Node->getValueType(0) == MVT::i16);
401 int FI = cast<FrameIndexSDNode>(Node)->getIndex();
402 SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i16);
403 if (Node->hasOneUse()) {
404 CurDAG->SelectNodeTo(Node, MSP430::ADDframe, MVT::i16, TFI,
405 CurDAG->getTargetConstant(0, dl, MVT::i16));
406 return;
407 }
408 ReplaceNode(Node, CurDAG->getMachineNode(
409 MSP430::ADDframe, dl, MVT::i16, TFI,
410 CurDAG->getTargetConstant(0, dl, MVT::i16)));
411 return;
412 }
413 case ISD::LOAD:
414 if (tryIndexedLoad(Node))
415 return;
416 // Other cases are autogenerated.
417 break;
418 case ISD::ADD:
419 if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
420 MSP430::ADD8rp, MSP430::ADD16rp))
421 return;
422 else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
423 MSP430::ADD8rp, MSP430::ADD16rp))
424 return;
425
426 // Other cases are autogenerated.
427 break;
428 case ISD::SUB:
429 if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
430 MSP430::SUB8rp, MSP430::SUB16rp))
431 return;
432
433 // Other cases are autogenerated.
434 break;
435 case ISD::AND:
436 if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
437 MSP430::AND8rp, MSP430::AND16rp))
438 return;
439 else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
440 MSP430::AND8rp, MSP430::AND16rp))
441 return;
442
443 // Other cases are autogenerated.
444 break;
445 case ISD::OR:
446 if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
447 MSP430::BIS8rp, MSP430::BIS16rp))
448 return;
449 else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
450 MSP430::BIS8rp, MSP430::BIS16rp))
451 return;
452
453 // Other cases are autogenerated.
454 break;
455 case ISD::XOR:
456 if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
457 MSP430::XOR8rp, MSP430::XOR16rp))
458 return;
459 else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
460 MSP430::XOR8rp, MSP430::XOR16rp))
461 return;
462
463 // Other cases are autogenerated.
464 break;
465 }
466
467 // Select the default instruction
468 SelectCode(Node);
469}
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:663
This file contains the declarations for the subclasses of Constant, which represent the different fla...
#define DEBUG_TYPE
#define G(x, y, z)
Definition MD5.cpp:55
static bool isValidIndexedLoad(const LoadSDNode *LD)
Register Reg
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
#define LLVM_DEBUG(...)
Definition Debug.h:119
#define PASS_NAME
The address of a basic block.
Definition Constants.h:1088
This is an important base class in LLVM.
Definition Constant.h:43
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
This class is used to represent ISD::LOAD nodes.
MSP430ISelDAGToDAGPass(MSP430TargetMachine &TM, CodeGenOptLevel OptLevel)
Machine Value Type.
SimpleValueType SimpleTy
A description of a memory reference used in the backend.
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
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
unsigned getOpcode() const
Storage of either a normal Value address, or a select condition together with a pair of addresses for...
SelectionDAGISelPass(std::unique_ptr< SelectionDAGISel > Selector)
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
LLVM_ABI void dump() const
Support for debugging, callable in GDB: V->dump()
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:739
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
@ Offset
Definition DWP.cpp:573
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
CodeGenOptLevel
Code generation optimization level.
Definition CodeGen.h:82
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
FunctionPass * createMSP430ISelDag(MSP430TargetMachine &TM, CodeGenOptLevel OptLevel)
createMSP430ISelDag - This pass converts a legalized DAG into a MSP430-specific DAG,...
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:860
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77
Extended Value Type.
Definition ValueTypes.h:35
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition ValueTypes.h:339