LLVM 19.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 static char ID;
95
96 MSP430DAGToDAGISel() = delete;
97
98 MSP430DAGToDAGISel(MSP430TargetMachine &TM, CodeGenOptLevel OptLevel)
99 : SelectionDAGISel(ID, TM, OptLevel) {}
100
101 private:
102 bool MatchAddress(SDValue N, MSP430ISelAddressMode &AM);
103 bool MatchWrapper(SDValue N, MSP430ISelAddressMode &AM);
104 bool MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM);
105
107 InlineAsm::ConstraintCode ConstraintID,
108 std::vector<SDValue> &OutOps) override;
109
110 // Include the pieces autogenerated from the target description.
111 #include "MSP430GenDAGISel.inc"
112
113 // Main method to transform nodes into machine nodes.
114 void Select(SDNode *N) override;
115
116 bool tryIndexedLoad(SDNode *Op);
117 bool tryIndexedBinOp(SDNode *Op, SDValue N1, SDValue N2, unsigned Opc8,
118 unsigned Opc16);
119
120 bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Disp);
121 };
122} // end anonymous namespace
123
124char MSP430DAGToDAGISel::ID;
125
126INITIALIZE_PASS(MSP430DAGToDAGISel, DEBUG_TYPE, PASS_NAME, false, false)
127
128/// createMSP430ISelDag - This pass converts a legalized DAG into a
129/// MSP430-specific DAG, ready for instruction scheduling.
130///
132 CodeGenOptLevel OptLevel) {
133 return new MSP430DAGToDAGISel(TM, OptLevel);
134}
135
136/// MatchWrapper - Try to match MSP430ISD::Wrapper node into an addressing mode.
137/// These wrap things that will resolve down into a symbol reference. If no
138/// match is possible, this returns true, otherwise it returns false.
139bool MSP430DAGToDAGISel::MatchWrapper(SDValue N, MSP430ISelAddressMode &AM) {
140 // If the addressing mode already has a symbol as the displacement, we can
141 // never match another symbol.
142 if (AM.hasSymbolicDisplacement())
143 return true;
144
145 SDValue N0 = N.getOperand(0);
146
147 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) {
148 AM.GV = G->getGlobal();
149 AM.Disp += G->getOffset();
150 //AM.SymbolFlags = G->getTargetFlags();
151 } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
152 AM.CP = CP->getConstVal();
153 AM.Alignment = CP->getAlign();
154 AM.Disp += CP->getOffset();
155 //AM.SymbolFlags = CP->getTargetFlags();
156 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(N0)) {
157 AM.ES = S->getSymbol();
158 //AM.SymbolFlags = S->getTargetFlags();
159 } else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) {
160 AM.JT = J->getIndex();
161 //AM.SymbolFlags = J->getTargetFlags();
162 } else {
163 AM.BlockAddr = cast<BlockAddressSDNode>(N0)->getBlockAddress();
164 //AM.SymbolFlags = cast<BlockAddressSDNode>(N0)->getTargetFlags();
165 }
166 return false;
167}
168
169/// MatchAddressBase - Helper for MatchAddress. Add the specified node to the
170/// specified addressing mode without any further recursion.
171bool MSP430DAGToDAGISel::MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM) {
172 // Is the base register already occupied?
173 if (AM.BaseType != MSP430ISelAddressMode::RegBase || AM.Base.Reg.getNode()) {
174 // If so, we cannot select it.
175 return true;
176 }
177
178 // Default, generate it as a register.
179 AM.BaseType = MSP430ISelAddressMode::RegBase;
180 AM.Base.Reg = N;
181 return false;
182}
183
184bool MSP430DAGToDAGISel::MatchAddress(SDValue N, MSP430ISelAddressMode &AM) {
185 LLVM_DEBUG(errs() << "MatchAddress: "; AM.dump());
186
187 switch (N.getOpcode()) {
188 default: break;
189 case ISD::Constant: {
190 uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue();
191 AM.Disp += Val;
192 return false;
193 }
194
196 if (!MatchWrapper(N, AM))
197 return false;
198 break;
199
200 case ISD::FrameIndex:
201 if (AM.BaseType == MSP430ISelAddressMode::RegBase
202 && AM.Base.Reg.getNode() == nullptr) {
203 AM.BaseType = MSP430ISelAddressMode::FrameIndexBase;
204 AM.Base.FrameIndex = cast<FrameIndexSDNode>(N)->getIndex();
205 return false;
206 }
207 break;
208
209 case ISD::ADD: {
210 MSP430ISelAddressMode Backup = AM;
211 if (!MatchAddress(N.getNode()->getOperand(0), AM) &&
212 !MatchAddress(N.getNode()->getOperand(1), AM))
213 return false;
214 AM = Backup;
215 if (!MatchAddress(N.getNode()->getOperand(1), AM) &&
216 !MatchAddress(N.getNode()->getOperand(0), AM))
217 return false;
218 AM = Backup;
219
220 break;
221 }
222
223 case ISD::OR:
224 // Handle "X | C" as "X + C" iff X is known to have C bits clear.
225 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
226 MSP430ISelAddressMode Backup = AM;
227 uint64_t Offset = CN->getSExtValue();
228 // Start with the LHS as an addr mode.
229 if (!MatchAddress(N.getOperand(0), AM) &&
230 // Address could not have picked a GV address for the displacement.
231 AM.GV == nullptr &&
232 // Check to see if the LHS & C is zero.
233 CurDAG->MaskedValueIsZero(N.getOperand(0), CN->getAPIntValue())) {
234 AM.Disp += Offset;
235 return false;
236 }
237 AM = Backup;
238 }
239 break;
240 }
241
242 return MatchAddressBase(N, AM);
243}
244
245/// SelectAddr - returns true if it is able pattern match an addressing mode.
246/// It returns the operands which make up the maximal addressing mode it can
247/// match by reference.
248bool MSP430DAGToDAGISel::SelectAddr(SDValue N,
249 SDValue &Base, SDValue &Disp) {
250 MSP430ISelAddressMode AM;
251
252 if (MatchAddress(N, AM))
253 return false;
254
255 if (AM.BaseType == MSP430ISelAddressMode::RegBase)
256 if (!AM.Base.Reg.getNode())
257 AM.Base.Reg = CurDAG->getRegister(MSP430::SR, MVT::i16);
258
259 Base = (AM.BaseType == MSP430ISelAddressMode::FrameIndexBase)
260 ? CurDAG->getTargetFrameIndex(
261 AM.Base.FrameIndex,
262 N.getValueType())
263 : AM.Base.Reg;
264
265 if (AM.GV)
266 Disp = CurDAG->getTargetGlobalAddress(AM.GV, SDLoc(N),
267 MVT::i16, AM.Disp,
268 0/*AM.SymbolFlags*/);
269 else if (AM.CP)
270 Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i16, AM.Alignment, AM.Disp,
271 0 /*AM.SymbolFlags*/);
272 else if (AM.ES)
273 Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i16, 0/*AM.SymbolFlags*/);
274 else if (AM.JT != -1)
275 Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i16, 0/*AM.SymbolFlags*/);
276 else if (AM.BlockAddr)
277 Disp = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, 0,
278 0/*AM.SymbolFlags*/);
279 else
280 Disp = CurDAG->getTargetConstant(AM.Disp, SDLoc(N), MVT::i16);
281
282 return true;
283}
284
285bool MSP430DAGToDAGISel::SelectInlineAsmMemoryOperand(
286 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
287 std::vector<SDValue> &OutOps) {
288 SDValue Op0, Op1;
289 switch (ConstraintID) {
290 default: return true;
291 case InlineAsm::ConstraintCode::m: // memory
292 if (!SelectAddr(Op, Op0, Op1))
293 return true;
294 break;
295 }
296
297 OutOps.push_back(Op0);
298 OutOps.push_back(Op1);
299 return false;
300}
301
302static bool isValidIndexedLoad(const LoadSDNode *LD) {
303 ISD::MemIndexedMode AM = LD->getAddressingMode();
304 if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD)
305 return false;
306
307 EVT VT = LD->getMemoryVT();
308
309 switch (VT.getSimpleVT().SimpleTy) {
310 case MVT::i8:
311 if (LD->getOffset()->getAsZExtVal() != 1)
312 return false;
313
314 break;
315 case MVT::i16:
316 if (LD->getOffset()->getAsZExtVal() != 2)
317 return false;
318
319 break;
320 default:
321 return false;
322 }
323
324 return true;
325}
326
327bool MSP430DAGToDAGISel::tryIndexedLoad(SDNode *N) {
328 LoadSDNode *LD = cast<LoadSDNode>(N);
329 if (!isValidIndexedLoad(LD))
330 return false;
331
332 MVT VT = LD->getMemoryVT().getSimpleVT();
333
334 unsigned Opcode = 0;
335 switch (VT.SimpleTy) {
336 case MVT::i8:
337 Opcode = MSP430::MOV8rp;
338 break;
339 case MVT::i16:
340 Opcode = MSP430::MOV16rp;
341 break;
342 default:
343 return false;
344 }
345
346 ReplaceNode(N,
347 CurDAG->getMachineNode(Opcode, SDLoc(N), VT, MVT::i16, MVT::Other,
348 LD->getBasePtr(), LD->getChain()));
349 return true;
350}
351
352bool MSP430DAGToDAGISel::tryIndexedBinOp(SDNode *Op, SDValue N1, SDValue N2,
353 unsigned Opc8, unsigned Opc16) {
354 if (N1.getOpcode() == ISD::LOAD &&
355 N1.hasOneUse() &&
356 IsLegalToFold(N1, Op, Op, OptLevel)) {
357 LoadSDNode *LD = cast<LoadSDNode>(N1);
358 if (!isValidIndexedLoad(LD))
359 return false;
360
361 MVT VT = LD->getMemoryVT().getSimpleVT();
362 unsigned Opc = (VT == MVT::i16 ? Opc16 : Opc8);
363 MachineMemOperand *MemRef = cast<MemSDNode>(N1)->getMemOperand();
364 SDValue Ops0[] = { N2, LD->getBasePtr(), LD->getChain() };
365 SDNode *ResNode =
366 CurDAG->SelectNodeTo(Op, Opc, VT, MVT::i16, MVT::Other, Ops0);
367 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {MemRef});
368 // Transfer chain.
369 ReplaceUses(SDValue(N1.getNode(), 2), SDValue(ResNode, 2));
370 // Transfer writeback.
371 ReplaceUses(SDValue(N1.getNode(), 1), SDValue(ResNode, 1));
372 return true;
373 }
374
375 return false;
376}
377
378
379void MSP430DAGToDAGISel::Select(SDNode *Node) {
380 SDLoc dl(Node);
381
382 // If we have a custom node, we already have selected!
383 if (Node->isMachineOpcode()) {
384 LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
385 Node->setNodeId(-1);
386 return;
387 }
388
389 // Few custom selection stuff.
390 switch (Node->getOpcode()) {
391 default: break;
392 case ISD::FrameIndex: {
393 assert(Node->getValueType(0) == MVT::i16);
394 int FI = cast<FrameIndexSDNode>(Node)->getIndex();
395 SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i16);
396 if (Node->hasOneUse()) {
397 CurDAG->SelectNodeTo(Node, MSP430::ADDframe, MVT::i16, TFI,
398 CurDAG->getTargetConstant(0, dl, MVT::i16));
399 return;
400 }
401 ReplaceNode(Node, CurDAG->getMachineNode(
402 MSP430::ADDframe, dl, MVT::i16, TFI,
403 CurDAG->getTargetConstant(0, dl, MVT::i16)));
404 return;
405 }
406 case ISD::LOAD:
407 if (tryIndexedLoad(Node))
408 return;
409 // Other cases are autogenerated.
410 break;
411 case ISD::ADD:
412 if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
413 MSP430::ADD8rp, MSP430::ADD16rp))
414 return;
415 else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
416 MSP430::ADD8rp, MSP430::ADD16rp))
417 return;
418
419 // Other cases are autogenerated.
420 break;
421 case ISD::SUB:
422 if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
423 MSP430::SUB8rp, MSP430::SUB16rp))
424 return;
425
426 // Other cases are autogenerated.
427 break;
428 case ISD::AND:
429 if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
430 MSP430::AND8rp, MSP430::AND16rp))
431 return;
432 else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
433 MSP430::AND8rp, MSP430::AND16rp))
434 return;
435
436 // Other cases are autogenerated.
437 break;
438 case ISD::OR:
439 if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
440 MSP430::BIS8rp, MSP430::BIS16rp))
441 return;
442 else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
443 MSP430::BIS8rp, MSP430::BIS16rp))
444 return;
445
446 // Other cases are autogenerated.
447 break;
448 case ISD::XOR:
449 if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
450 MSP430::XOR8rp, MSP430::XOR16rp))
451 return;
452 else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
453 MSP430::XOR8rp, MSP430::XOR16rp))
454 return;
455
456 // Other cases are autogenerated.
457 break;
458 }
459
460 // Select the default instruction
461 SelectCode(Node);
462}
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:529
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(VerifyEach)
const char LLVMTargetMachineRef TM
#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:889
This is an important base class in LLVM.
Definition: Constant.h:41
This class represents an Operation in the Expression.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:311
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:5239
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:239
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
Definition: ISDOpcodes.h:1031
@ FrameIndex
Definition: ISDOpcodes.h:80
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:680
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
Definition: ISDOpcodes.h:1472
@ 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:456
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,...
#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:34
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition: ValueTypes.h:306