41#define DEBUG_TYPE "m68k-isel"
42#define PASS_NAME "M68k DAG->DAG Pattern Instruction Selection"
48struct M68kISelAddressMode {
61 enum class Base { RegBase, FrameIndexBase };
81 unsigned char SymbolFlags;
83 M68kISelAddressMode(AddrType AT)
84 : AM(AT),
BaseType(Base::RegBase), Disp(0), BaseFrameIndex(0), IndexReg(),
85 Scale(1), GV(
nullptr), CP(
nullptr), BlockAddr(
nullptr), ES(
nullptr),
88 bool hasSymbolicDisplacement()
const {
89 return GV !=
nullptr || CP !=
nullptr || ES !=
nullptr ||
90 MCSym !=
nullptr || JT != -1 || BlockAddr !=
nullptr;
93 bool hasBase()
const {
94 return BaseType == Base::FrameIndexBase || BaseReg.
getNode() !=
nullptr;
97 bool hasFrameIndex()
const {
return BaseType == Base::FrameIndexBase; }
99 bool hasBaseReg()
const {
103 bool hasIndexReg()
const {
108 bool isDispAddrType()
const {
109 return AM == AddrType::ARII || AM == AddrType::PCI ||
110 AM == AddrType::ARID || AM == AddrType::PCD || AM == AddrType::AL;
113 unsigned getDispSize()
const {
129 bool hasDisp()
const {
return getDispSize() != 0; }
130 bool isDisp8()
const {
return getDispSize() == 8; }
131 bool isDisp16()
const {
return getDispSize() == 16; }
132 bool isDisp32()
const {
return getDispSize() == 32; }
135 bool isPCRelative()
const {
138 if (
auto *RegNode = dyn_cast_or_null<RegisterSDNode>(BaseReg.
getNode()))
139 return RegNode->getReg() == M68k::PC;
148 void setIndexReg(
SDValue Reg) { IndexReg = Reg; }
150#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
152 dbgs() <<
"M68kISelAddressMode " <<
this;
153 dbgs() <<
"\nDisp: " << Disp;
154 dbgs() <<
", BaseReg: ";
159 dbgs() <<
", BaseFI: " << BaseFrameIndex;
160 dbgs() <<
", IndexReg: ";
165 dbgs() <<
", Scale: " << Scale;
179 M68kDAGToDAGISel() =
delete;
193#include "M68kGenDAGISel.inc"
208 bool foldOffsetIntoAddress(
uint64_t Offset, M68kISelAddressMode &AM);
210 bool matchLoadInAddress(
LoadSDNode *
N, M68kISelAddressMode &AM);
211 bool matchAddress(
SDValue N, M68kISelAddressMode &AM);
212 bool matchAddressBase(
SDValue N, M68kISelAddressMode &AM);
213 bool matchAddressRecursively(
SDValue N, M68kISelAddressMode &AM,
215 bool matchADD(
SDValue &
N, M68kISelAddressMode &AM,
unsigned Depth);
216 bool matchWrapper(
SDValue N, M68kISelAddressMode &AM);
218 std::pair<bool, SDNode *> selectNode(
SDNode *
Node);
232 std::vector<SDValue> &OutOps)
override;
237 inline bool getFrameIndexAddress(M68kISelAddressMode &AM,
const SDLoc &
DL,
239 if (AM.BaseType == M68kISelAddressMode::Base::FrameIndexBase) {
240 Disp = getI32Imm(AM.Disp,
DL);
241 Base = CurDAG->getTargetFrameIndex(
242 AM.BaseFrameIndex, TLI->getPointerTy(CurDAG->getDataLayout()));
250 inline bool getSymbolicDisplacement(M68kISelAddressMode &AM,
const SDLoc &
DL,
253 Sym = CurDAG->getTargetGlobalAddress(AM.GV,
SDLoc(), MVT::i32, AM.Disp,
259 Sym = CurDAG->getTargetConstantPool(AM.CP, MVT::i32, AM.Alignment,
260 AM.Disp, AM.SymbolFlags);
265 assert(!AM.Disp &&
"Non-zero displacement is ignored with ES.");
266 Sym = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i32, AM.SymbolFlags);
271 assert(!AM.Disp &&
"Non-zero displacement is ignored with MCSym.");
272 assert(AM.SymbolFlags == 0 &&
"oo");
273 Sym = CurDAG->getMCSymbol(AM.MCSym, MVT::i32);
278 assert(!AM.Disp &&
"Non-zero displacement is ignored with JT.");
279 Sym = CurDAG->getTargetJumpTable(AM.JT, MVT::i32, AM.SymbolFlags);
284 Sym = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, AM.Disp,
294 return CurDAG->getTargetConstant(Imm,
DL, MVT::i8);
299 return CurDAG->getTargetConstant(Imm,
DL, MVT::i16);
304 return CurDAG->getTargetConstant(Imm,
DL, MVT::i32);
316 SDNode *getGlobalBaseReg();
319char M68kDAGToDAGISel::ID;
327 if (OptLevel == CodeGenOptLevel::None)
331 switch (
U->getOpcode()) {
360 return new M68kDAGToDAGISel(
TM);
364 if (!AM.isDispAddrType())
367 return isIntN(AM.getDispSize() - 1, AM.Disp);
371 if (!AM.isDispAddrType())
373 return isIntN(AM.getDispSize(), Val);
379SDNode *M68kDAGToDAGISel::getGlobalBaseReg() {
380 unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF);
381 auto &
DL = MF->getDataLayout();
382 return CurDAG->getRegister(GlobalBaseReg, TLI->getPointerTy(
DL)).getNode();
386 M68kISelAddressMode &AM) {
388 if (
Offset != 0 && (AM.ES || AM.MCSym))
391 int64_t Val = AM.Disp +
Offset;
407bool M68kDAGToDAGISel::matchAddressBase(
SDValue N, M68kISelAddressMode &AM) {
411 if (!AM.hasIndexReg()) {
422 AM.BaseType = M68kISelAddressMode::Base::RegBase;
428bool M68kDAGToDAGISel::matchLoadInAddress(
LoadSDNode *
N,
429 M68kISelAddressMode &AM) {
433bool M68kDAGToDAGISel::matchAddressRecursively(
SDValue N,
434 M68kISelAddressMode &AM,
440 return matchAddressBase(
N, AM);
445 if (AM.isPCRelative()) {
451 if (foldOffsetIntoAddress(Cst->getSExtValue(), AM))
456 switch (
N.getOpcode()) {
461 uint64_t Val = cast<ConstantSDNode>(
N)->getSExtValue();
462 if (foldOffsetIntoAddress(Val, AM))
469 if (matchWrapper(
N, AM))
474 if (matchLoadInAddress(cast<LoadSDNode>(
N), AM))
485 if (CurDAG->haveNoCommonBitsSet(
N.getOperand(0),
N.getOperand(1)) &&
491 if (matchADD(
N, AM,
Depth))
496 if (AM.isDispAddrType() &&
497 AM.BaseType == M68kISelAddressMode::Base::RegBase &&
499 AM.BaseType = M68kISelAddressMode::Base::FrameIndexBase;
500 AM.BaseFrameIndex = cast<FrameIndexSDNode>(
N)->getIndex();
513 return matchAddressBase(
N, AM);
518bool M68kDAGToDAGISel::matchAddress(
SDValue N, M68kISelAddressMode &AM) {
526 return matchAddressRecursively(
N, AM, 0);
529bool M68kDAGToDAGISel::matchADD(
SDValue &
N, M68kISelAddressMode &AM,
535 M68kISelAddressMode Backup = AM;
536 if (matchAddressRecursively(
N.getOperand(0), AM,
Depth + 1) &&
537 matchAddressRecursively(Handle.getValue().getOperand(1), AM,
Depth + 1)) {
543 if (matchAddressRecursively(Handle.getValue().getOperand(1), AM,
Depth + 1) &&
544 matchAddressRecursively(Handle.getValue().getOperand(0), AM,
Depth + 1)) {
552 if (!AM.hasBase() && !AM.hasIndexReg()) {
553 N = Handle.getValue();
554 AM.BaseReg =
N.getOperand(0);
555 AM.IndexReg =
N.getOperand(1);
560 N = Handle.getValue();
568bool M68kDAGToDAGISel::matchWrapper(
SDValue N, M68kISelAddressMode &AM) {
571 if (AM.hasSymbolicDisplacement())
579 M68kISelAddressMode Backup = AM;
585 if (
auto *
G = dyn_cast<GlobalAddressSDNode>(N0)) {
586 AM.GV =
G->getGlobal();
587 AM.SymbolFlags =
G->getTargetFlags();
588 if (!foldOffsetIntoAddress(
G->getOffset(), AM)) {
592 }
else if (
auto *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
593 AM.CP =
CP->getConstVal();
594 AM.Alignment =
CP->getAlign();
595 AM.SymbolFlags =
CP->getTargetFlags();
596 if (!foldOffsetIntoAddress(
CP->getOffset(), AM)) {
600 }
else if (
auto *S = dyn_cast<ExternalSymbolSDNode>(N0)) {
601 AM.ES = S->getSymbol();
602 AM.SymbolFlags = S->getTargetFlags();
603 }
else if (
auto *S = dyn_cast<MCSymbolSDNode>(N0)) {
604 AM.MCSym = S->getMCSymbol();
605 }
else if (
auto *J = dyn_cast<JumpTableSDNode>(N0)) {
606 AM.JT = J->getIndex();
607 AM.SymbolFlags = J->getTargetFlags();
608 }
else if (
auto *BA = dyn_cast<BlockAddressSDNode>(N0)) {
609 AM.BlockAddr = BA->getBlockAddress();
610 AM.SymbolFlags = BA->getTargetFlags();
611 if (!foldOffsetIntoAddress(BA->getOffset(), AM)) {
618 AM.setBaseReg(CurDAG->getRegister(M68k::PC, MVT::i32));
623 if (!AM.isDisp32()) {
628 if (
auto *
G = dyn_cast<GlobalAddressSDNode>(N0)) {
629 AM.GV =
G->getGlobal();
630 AM.Disp +=
G->getOffset();
631 AM.SymbolFlags =
G->getTargetFlags();
632 }
else if (
auto *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
633 AM.CP =
CP->getConstVal();
634 AM.Alignment =
CP->getAlign();
635 AM.Disp +=
CP->getOffset();
636 AM.SymbolFlags =
CP->getTargetFlags();
637 }
else if (
auto *S = dyn_cast<ExternalSymbolSDNode>(N0)) {
638 AM.ES = S->getSymbol();
639 AM.SymbolFlags = S->getTargetFlags();
640 }
else if (
auto *S = dyn_cast<MCSymbolSDNode>(N0)) {
641 AM.MCSym = S->getMCSymbol();
642 }
else if (
auto *J = dyn_cast<JumpTableSDNode>(N0)) {
643 AM.JT = J->getIndex();
644 AM.SymbolFlags = J->getTargetFlags();
645 }
else if (
auto *BA = dyn_cast<BlockAddressSDNode>(N0)) {
646 AM.BlockAddr = BA->getBlockAddress();
647 AM.Disp += BA->getOffset();
648 AM.SymbolFlags = BA->getTargetFlags();
667 if (
Node->isMachineOpcode()) {
678 SDValue GOT = CurDAG->getTargetExternalSymbol(
681 CurDAG->getMachineNode(M68k::LEA32q,
DL, MVT::i32, GOT);
682 ReplaceNode(
Node, Res);
687 ReplaceNode(
Node, getGlobalBaseReg());
709 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARID);
711 if (!matchAddress(
N, AM))
714 if (AM.isPCRelative()) {
715 LLVM_DEBUG(
dbgs() <<
"REJECT: Cannot match PC relative address\n");
720 if (getFrameIndexAddress(AM,
SDLoc(
N), Disp,
Base)) {
725 if (AM.hasIndexReg()) {
730 if (!AM.hasBaseReg()) {
737 if (getSymbolicDisplacement(AM,
SDLoc(
N), Disp)) {
738 assert(!AM.Disp &&
"Should not be any displacement");
749 Disp = getI16Imm(AM.Disp,
SDLoc(
N));
756 switch (
N.getOpcode()) {
760 [](
const SDUse &U) { return isAddressBase(U.get()); });
772 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARII);
775 if (!matchAddress(
N, AM))
778 if (AM.isPCRelative()) {
783 if (!AM.hasIndexReg()) {
788 if (!AM.hasBaseReg()) {
801 if (AM.hasSymbolicDisplacement()) {
802 LLVM_DEBUG(
dbgs() <<
"REJECT, Cannot match symbolic displacement\n");
815 Disp = getI8Imm(AM.Disp,
SDLoc(
N));
823 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::AL);
825 if (!matchAddress(
N, AM)) {
830 if (AM.isPCRelative()) {
831 LLVM_DEBUG(
dbgs() <<
"REJECT: Cannot match PC relative address\n");
840 if (AM.hasIndexReg()) {
845 if (getSymbolicDisplacement(AM,
SDLoc(
N),
Sym)) {
863 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::PCD);
865 if (!matchAddress(
N, AM))
868 if (!AM.isPCRelative()) {
873 if (AM.hasIndexReg()) {
878 if (getSymbolicDisplacement(AM,
SDLoc(
N), Disp)) {
883 Disp = getI16Imm(AM.Disp,
SDLoc(
N));
892 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::PCI);
894 if (!matchAddress(
N, AM))
897 if (!AM.isPCRelative()) {
902 if (!AM.hasIndexReg()) {
909 if (getSymbolicDisplacement(AM,
SDLoc(
N), Disp)) {
910 assert(!AM.Disp &&
"Should not be any displacement");
915 Disp = getI8Imm(AM.Disp,
SDLoc(
N));
923 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARI);
925 if (!matchAddress(
N, AM)) {
930 if (AM.isPCRelative()) {
931 LLVM_DEBUG(
dbgs() <<
"REJECT: Cannot match PC relative address\n");
936 if (AM.hasIndexReg() || AM.Disp != 0) {
942 if (AM.hasSymbolicDisplacement()) {
947 if (AM.hasBaseReg()) {
956bool M68kDAGToDAGISel::SelectInlineAsmMemoryOperand(
958 std::vector<SDValue> &OutOps) {
964 auto addKind = [
this](
SDValue &Opnd, AMK
Kind) ->
bool {
965 Opnd = CurDAG->getTargetConstant(
unsigned(Kind),
SDLoc(), MVT::i32);
969 switch (ConstraintID) {
971 case InlineAsm::ConstraintCode::m: {
1002 case InlineAsm::ConstraintCode::Q: {
1007 if (SelectARI(
nullptr,
Op,
Base) && addKind(AMKind, AMK::j)) {
1008 OutOps.insert(OutOps.end(), {AMKind,
Base});
1014 case InlineAsm::ConstraintCode::Um: {
1017 if (SelectARID(
nullptr,
Op,
Offset,
Base) && addKind(AMKind, AMK::p)) {
1018 OutOps.insert(OutOps.end(), {AMKind,
Offset,
Base});
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu AMDGPU Register Bank Select
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
static bool doesDispFit(M68kISelAddressMode &AM, int64_t Val)
static bool doesDispFitFI(M68kISelAddressMode &AM)
static bool isAddressBase(const SDValue &N)
This file declares the M68k specific subclass of MachineFunctionInfo.
This file contains the M68k implementation of the TargetRegisterInfo class.
This file declares the M68k specific subclass of TargetMachine.
This file contains the entry points for global functions defined in the M68k target library,...
mir Rename Register Operands
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static constexpr uint32_t Opcode
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.
unsigned getTargetFlags() const
const GlobalValue * getGlobal() const
This class is used to form a handle around another node that is persistent and is updated across invo...
This class is used to represent ISD::LOAD nodes.
const M68kInstrInfo * getInstrInfo() const override
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
An SDNode that represents everything that will be needed to construct a MachineInstr.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
void dump() const
Dump this node, for debugging.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
Represents a use of a SDNode.
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
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,...
virtual bool IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const
IsProfitableToFold - Returns true if it's profitable to fold the specific operand node N of U during ...
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ ADDC
Carry-setting nodes for multiple precision addition and subtraction.
@ 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...
@ GLOBAL_OFFSET_TABLE
The address of the GOT.
@ MO_GOTPCREL
On a symbol operand this indicates that the immediate is offset to the GOT entry for the symbol name ...
@ WrapperPC
Special wrapper used under M68k PIC mode for PC relative displacements.
@ Wrapper
A wrapper node for TargetConstantPool, TargetExternalSymbol, and TargetGlobalAddress.
@ GlobalBaseReg
The result of the mflr at function entry, used for PIC code.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
FunctionPass * createM68kISelDag(M68kTargetMachine &TM)
This pass converts a legalized DAG into a M68k-specific DAG, ready for instruction scheduling.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
This struct is a compact representation of a valid (non-zero power of two) alignment.