20#include "llvm/Config/llvm-config.h"
28#define DEBUG_TYPE "msp430-isel"
29#define PASS_NAME "MSP430 DAG->DAG Pattern Instruction Selection"
32 struct MSP430ISelAddressMode {
47 const char *ES =
nullptr;
51 MSP430ISelAddressMode() =
default;
53 bool hasSymbolicDisplacement()
const {
54 return GV !=
nullptr || CP !=
nullptr || ES !=
nullptr || JT != -1;
57#if !defined(NDEBUG) || defined(LLVM_ENABLE_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';
66 errs() <<
" Disp " << Disp <<
'\n';
73 errs() <<
" Align" << Alignment.
value() <<
'\n';
78 errs() <<
" JT" << JT <<
" Align" << Alignment.
value() <<
'\n';
90 MSP430DAGToDAGISel() =
delete;
93 : SelectionDAGISel(TM, OptLevel) {}
96 bool MatchAddress(
SDValue N, MSP430ISelAddressMode &AM);
97 bool MatchWrapper(
SDValue N, MSP430ISelAddressMode &AM);
98 bool MatchAddressBase(
SDValue N, MSP430ISelAddressMode &AM);
100 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
102 std::vector<SDValue> &OutOps)
override;
105 #include "MSP430GenDAGISel.inc"
108 void Select(SDNode *
N)
override;
110 bool tryIndexedLoad(SDNode *
Op);
120 MSP430DAGToDAGISelLegacy(MSP430TargetMachine &TM,
CodeGenOptLevel OptLevel)
121 : SelectionDAGISelLegacy(
122 ID, std::make_unique<MSP430DAGToDAGISel>(TM, OptLevel)) {}
126char MSP430DAGToDAGISelLegacy::ID;
135 return new MSP430DAGToDAGISelLegacy(TM, OptLevel);
146bool MSP430DAGToDAGISel::MatchWrapper(
SDValue N, MSP430ISelAddressMode &AM) {
149 if (AM.hasSymbolicDisplacement())
155 AM.GV =
G->getGlobal();
156 AM.Disp +=
G->getOffset();
159 AM.CP = CP->getConstVal();
160 AM.Alignment = CP->getAlign();
161 AM.Disp += CP->getOffset();
164 AM.ES = S->getSymbol();
167 AM.JT = J->getIndex();
178bool MSP430DAGToDAGISel::MatchAddressBase(
SDValue N, MSP430ISelAddressMode &AM) {
180 if (AM.BaseType != MSP430ISelAddressMode::RegBase || AM.Base.Reg.getNode()) {
186 AM.BaseType = MSP430ISelAddressMode::RegBase;
191bool MSP430DAGToDAGISel::MatchAddress(
SDValue N, MSP430ISelAddressMode &AM) {
194 switch (
N.getOpcode()) {
202 case MSP430ISD::Wrapper:
203 if (!MatchWrapper(
N, AM))
208 if (AM.BaseType == MSP430ISelAddressMode::RegBase
209 && AM.Base.Reg.getNode() ==
nullptr) {
210 AM.BaseType = MSP430ISelAddressMode::FrameIndexBase;
217 MSP430ISelAddressMode Backup = AM;
218 if (!MatchAddress(
N.getNode()->getOperand(0), AM) &&
219 !MatchAddress(
N.getNode()->getOperand(1), AM))
222 if (!MatchAddress(
N.getNode()->getOperand(1), AM) &&
223 !MatchAddress(
N.getNode()->getOperand(0), AM))
233 MSP430ISelAddressMode Backup = AM;
234 uint64_t
Offset = CN->getSExtValue();
236 if (!MatchAddress(
N.getOperand(0), AM) &&
240 CurDAG->MaskedValueIsZero(
N.getOperand(0), CN->getAPIntValue())) {
249 return MatchAddressBase(
N, AM);
255bool MSP430DAGToDAGISel::SelectAddr(
SDValue N,
257 MSP430ISelAddressMode AM;
259 if (MatchAddress(
N, AM))
262 if (AM.BaseType == MSP430ISelAddressMode::RegBase)
263 if (!AM.Base.Reg.getNode())
264 AM.Base.Reg = CurDAG->getRegister(MSP430::SR, MVT::i16);
266 Base = (AM.BaseType == MSP430ISelAddressMode::FrameIndexBase)
267 ? CurDAG->getTargetFrameIndex(
273 Disp = CurDAG->getTargetGlobalAddress(AM.GV,
SDLoc(
N),
277 Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i16, AM.Alignment, AM.Disp,
280 Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i16, 0);
281 else if (AM.JT != -1)
282 Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i16, 0);
283 else if (AM.BlockAddr)
284 Disp = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, 0,
287 Disp = CurDAG->getSignedTargetConstant(AM.Disp,
SDLoc(
N), MVT::i16);
292bool MSP430DAGToDAGISel::SelectInlineAsmMemoryOperand(
294 std::vector<SDValue> &OutOps) {
296 switch (ConstraintID) {
297 default:
return true;
304 OutOps.push_back(Op0);
305 OutOps.push_back(Op1);
314 EVT VT = LD->getMemoryVT();
318 if (LD->getOffset()->getAsZExtVal() != 1)
323 if (LD->getOffset()->getAsZExtVal() != 2)
334bool MSP430DAGToDAGISel::tryIndexedLoad(
SDNode *
N) {
339 MVT VT =
LD->getMemoryVT().getSimpleVT();
344 Opcode = MSP430::MOV8rp;
347 Opcode = MSP430::MOV16rp;
354 CurDAG->getMachineNode(Opcode,
SDLoc(
N), VT, MVT::i16, MVT::Other,
355 LD->getBasePtr(),
LD->getChain()));
360 unsigned Opc8,
unsigned Opc16) {
363 IsLegalToFold(N1,
Op,
Op, OptLevel)) {
368 MVT VT =
LD->getMemoryVT().getSimpleVT();
369 unsigned Opc = (VT == MVT::i16 ? Opc16 : Opc8);
371 SDValue Ops0[] = { N2,
LD->getBasePtr(),
LD->getChain() };
373 CurDAG->SelectNodeTo(
Op,
Opc, VT, MVT::i16, MVT::Other, Ops0);
386void MSP430DAGToDAGISel::Select(
SDNode *Node) {
390 if (
Node->isMachineOpcode()) {
397 switch (
Node->getOpcode()) {
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));
408 ReplaceNode(Node, CurDAG->getMachineNode(
409 MSP430::ADDframe, dl, MVT::i16, TFI,
410 CurDAG->getTargetConstant(0, dl, MVT::i16)));
414 if (tryIndexedLoad(Node))
419 if (tryIndexedBinOp(Node,
Node->getOperand(0),
Node->getOperand(1),
420 MSP430::ADD8rp, MSP430::ADD16rp))
422 else if (tryIndexedBinOp(Node,
Node->getOperand(1),
Node->getOperand(0),
423 MSP430::ADD8rp, MSP430::ADD16rp))
429 if (tryIndexedBinOp(Node,
Node->getOperand(0),
Node->getOperand(1),
430 MSP430::SUB8rp, MSP430::SUB16rp))
436 if (tryIndexedBinOp(Node,
Node->getOperand(0),
Node->getOperand(1),
437 MSP430::AND8rp, MSP430::AND16rp))
439 else if (tryIndexedBinOp(Node,
Node->getOperand(1),
Node->getOperand(0),
440 MSP430::AND8rp, MSP430::AND16rp))
446 if (tryIndexedBinOp(Node,
Node->getOperand(0),
Node->getOperand(1),
447 MSP430::BIS8rp, MSP430::BIS16rp))
449 else if (tryIndexedBinOp(Node,
Node->getOperand(1),
Node->getOperand(0),
450 MSP430::BIS8rp, MSP430::BIS16rp))
456 if (tryIndexedBinOp(Node,
Node->getOperand(0),
Node->getOperand(1),
457 MSP430::XOR8rp, MSP430::XOR16rp))
459 else if (tryIndexedBinOp(Node,
Node->getOperand(1),
Node->getOperand(0),
460 MSP430::XOR8rp, MSP430::XOR16rp))
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.
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)
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
The address of a basic block.
This is an important base class in LLVM.
FunctionPass class - This class is used to implement most global optimizations.
This class is used to represent ISD::LOAD nodes.
MSP430ISelDAGToDAGPass(MSP430TargetMachine &TM, CodeGenOptLevel OptLevel)
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.
@ 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.
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
CodeGenOptLevel
Code generation optimization level.
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.
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.
constexpr 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.