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