19#include "llvm/Config/llvm-config.h"
27#define DEBUG_TYPE "msp430-isel"
28#define PASS_NAME "MSP430 DAG->DAG Pattern Instruction Selection"
31 struct MSP430ISelAddressMode {
46 const char *ES =
nullptr;
50 MSP430ISelAddressMode() =
default;
52 bool hasSymbolicDisplacement()
const {
53 return GV !=
nullptr || CP !=
nullptr || ES !=
nullptr || JT != -1;
56#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
58 errs() <<
"MSP430ISelAddressMode " <<
this <<
'\n';
59 if (
BaseType == RegBase &&
Base.Reg.getNode() !=
nullptr) {
60 errs() <<
"Base.Reg ";
61 Base.Reg.getNode()->dump();
62 }
else if (
BaseType == FrameIndexBase) {
63 errs() <<
" Base.FrameIndex " <<
Base.FrameIndex <<
'\n';
65 errs() <<
" Disp " << Disp <<
'\n';
72 errs() <<
" Align" << Alignment.
value() <<
'\n';
77 errs() <<
" JT" << JT <<
" Align" << Alignment.
value() <<
'\n';
89 MSP430DAGToDAGISel() =
delete;
95 bool MatchAddress(
SDValue N, MSP430ISelAddressMode &AM);
96 bool MatchWrapper(
SDValue N, MSP430ISelAddressMode &AM);
97 bool MatchAddressBase(
SDValue N, MSP430ISelAddressMode &AM);
101 std::vector<SDValue> &OutOps)
override;
104 #include "MSP430GenDAGISel.inc"
121 ID,
std::make_unique<MSP430DAGToDAGISel>(
TM, OptLevel)) {}
125char MSP430DAGToDAGISelLegacy::ID;
134 return new MSP430DAGToDAGISelLegacy(TM, OptLevel);
140bool MSP430DAGToDAGISel::MatchWrapper(
SDValue N, MSP430ISelAddressMode &AM) {
143 if (AM.hasSymbolicDisplacement())
149 AM.GV =
G->getGlobal();
150 AM.Disp +=
G->getOffset();
153 AM.CP =
CP->getConstVal();
154 AM.Alignment =
CP->getAlign();
155 AM.Disp +=
CP->getOffset();
158 AM.ES = S->getSymbol();
161 AM.JT = J->getIndex();
164 AM.BlockAddr = cast<BlockAddressSDNode>(N0)->getBlockAddress();
172bool MSP430DAGToDAGISel::MatchAddressBase(
SDValue N, MSP430ISelAddressMode &AM) {
174 if (AM.BaseType != MSP430ISelAddressMode::RegBase || AM.Base.Reg.getNode()) {
180 AM.BaseType = MSP430ISelAddressMode::RegBase;
185bool MSP430DAGToDAGISel::MatchAddress(
SDValue N, MSP430ISelAddressMode &AM) {
188 switch (
N.getOpcode()) {
191 uint64_t Val = cast<ConstantSDNode>(
N)->getSExtValue();
197 if (!MatchWrapper(
N, AM))
202 if (AM.BaseType == MSP430ISelAddressMode::RegBase
203 && AM.Base.Reg.getNode() ==
nullptr) {
204 AM.BaseType = MSP430ISelAddressMode::FrameIndexBase;
205 AM.Base.FrameIndex = cast<FrameIndexSDNode>(
N)->getIndex();
211 MSP430ISelAddressMode Backup = AM;
212 if (!MatchAddress(
N.getNode()->getOperand(0), AM) &&
213 !MatchAddress(
N.getNode()->getOperand(1), AM))
216 if (!MatchAddress(
N.getNode()->getOperand(1), AM) &&
217 !MatchAddress(
N.getNode()->getOperand(0), AM))
227 MSP430ISelAddressMode Backup = AM;
230 if (!MatchAddress(
N.getOperand(0), AM) &&
234 CurDAG->MaskedValueIsZero(
N.getOperand(0), CN->getAPIntValue())) {
243 return MatchAddressBase(
N, AM);
249bool MSP430DAGToDAGISel::SelectAddr(
SDValue N,
251 MSP430ISelAddressMode AM;
253 if (MatchAddress(
N, AM))
256 if (AM.BaseType == MSP430ISelAddressMode::RegBase)
257 if (!AM.Base.Reg.getNode())
258 AM.Base.Reg = CurDAG->getRegister(MSP430::SR, MVT::i16);
260 Base = (AM.BaseType == MSP430ISelAddressMode::FrameIndexBase)
261 ? CurDAG->getTargetFrameIndex(
267 Disp = CurDAG->getTargetGlobalAddress(AM.GV,
SDLoc(
N),
271 Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i16, AM.Alignment, AM.Disp,
274 Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i16, 0);
275 else if (AM.JT != -1)
276 Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i16, 0);
277 else if (AM.BlockAddr)
278 Disp = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, 0,
281 Disp = CurDAG->getSignedTargetConstant(AM.Disp,
SDLoc(
N), MVT::i16);
286bool MSP430DAGToDAGISel::SelectInlineAsmMemoryOperand(
288 std::vector<SDValue> &OutOps) {
290 switch (ConstraintID) {
291 default:
return true;
292 case InlineAsm::ConstraintCode::m:
293 if (!SelectAddr(
Op, Op0, Op1))
298 OutOps.push_back(Op0);
299 OutOps.push_back(Op1);
308 EVT VT = LD->getMemoryVT();
312 if (LD->getOffset()->getAsZExtVal() != 1)
317 if (LD->getOffset()->getAsZExtVal() != 2)
328bool MSP430DAGToDAGISel::tryIndexedLoad(
SDNode *
N) {
333 MVT VT =
LD->getMemoryVT().getSimpleVT();
338 Opcode = MSP430::MOV8rp;
341 Opcode = MSP430::MOV16rp;
348 CurDAG->getMachineNode(Opcode,
SDLoc(
N), VT, MVT::i16, MVT::Other,
349 LD->getBasePtr(),
LD->getChain()));
354 unsigned Opc8,
unsigned Opc16) {
357 IsLegalToFold(N1,
Op,
Op, OptLevel)) {
362 MVT VT =
LD->getMemoryVT().getSimpleVT();
363 unsigned Opc = (VT == MVT::i16 ? Opc16 : Opc8);
365 SDValue Ops0[] = { N2,
LD->getBasePtr(),
LD->getChain() };
367 CurDAG->SelectNodeTo(
Op, Opc, VT, MVT::i16, MVT::Other, Ops0);
368 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {
MemRef});
380void MSP430DAGToDAGISel::Select(
SDNode *
Node) {
384 if (
Node->isMachineOpcode()) {
391 switch (
Node->getOpcode()) {
395 int FI = cast<FrameIndexSDNode>(
Node)->getIndex();
396 SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i16);
397 if (
Node->hasOneUse()) {
398 CurDAG->SelectNodeTo(
Node, MSP430::ADDframe, MVT::i16, TFI,
399 CurDAG->getTargetConstant(0, dl, MVT::i16));
402 ReplaceNode(
Node, CurDAG->getMachineNode(
403 MSP430::ADDframe, dl, MVT::i16, TFI,
404 CurDAG->getTargetConstant(0, dl, MVT::i16)));
408 if (tryIndexedLoad(
Node))
413 if (tryIndexedBinOp(
Node,
Node->getOperand(0),
Node->getOperand(1),
414 MSP430::ADD8rp, MSP430::ADD16rp))
416 else if (tryIndexedBinOp(
Node,
Node->getOperand(1),
Node->getOperand(0),
417 MSP430::ADD8rp, MSP430::ADD16rp))
423 if (tryIndexedBinOp(
Node,
Node->getOperand(0),
Node->getOperand(1),
424 MSP430::SUB8rp, MSP430::SUB16rp))
430 if (tryIndexedBinOp(
Node,
Node->getOperand(0),
Node->getOperand(1),
431 MSP430::AND8rp, MSP430::AND16rp))
433 else if (tryIndexedBinOp(
Node,
Node->getOperand(1),
Node->getOperand(0),
434 MSP430::AND8rp, MSP430::AND16rp))
440 if (tryIndexedBinOp(
Node,
Node->getOperand(0),
Node->getOperand(1),
441 MSP430::BIS8rp, MSP430::BIS16rp))
443 else if (tryIndexedBinOp(
Node,
Node->getOperand(1),
Node->getOperand(0),
444 MSP430::BIS8rp, MSP430::BIS16rp))
450 if (tryIndexedBinOp(
Node,
Node->getOperand(0),
Node->getOperand(1),
451 MSP430::XOR8rp, MSP430::XOR16rp))
453 else if (tryIndexedBinOp(
Node,
Node->getOperand(1),
Node->getOperand(0),
454 MSP430::XOR8rp, MSP430::XOR16rp))
AMDGPU Register Bank Select
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool isValidIndexedLoad(const LoadSDNode *LD)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
DEMANGLE_DUMP_METHOD void dump() const
The address of a basic block.
This is an important base class in LLVM.
This class represents an Operation in the Expression.
FunctionPass class - This class is used to implement most global optimizations.
This class is used to represent ISD::LOAD nodes.
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()
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ ADD
Simple integer binary arithmetic operators.
@ 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.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
@ Wrapper
Wrapper - A wrapper node for TargetConstantPool, TargetExternalSymbol, and TargetGlobalAddress.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
CodeGenOptLevel
Code generation optimization level.
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.
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.