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);
231 std::vector<SDValue> &OutOps)
override;
236 inline bool getFrameIndexAddress(M68kISelAddressMode &AM,
const SDLoc &
DL,
238 if (AM.BaseType == M68kISelAddressMode::Base::FrameIndexBase) {
239 Disp = getI32Imm(AM.Disp,
DL);
240 Base = CurDAG->getTargetFrameIndex(
241 AM.BaseFrameIndex, TLI->getPointerTy(CurDAG->getDataLayout()));
249 inline bool getSymbolicDisplacement(M68kISelAddressMode &AM,
const SDLoc &
DL,
252 Sym = CurDAG->getTargetGlobalAddress(AM.GV,
SDLoc(), MVT::i32, AM.Disp,
258 Sym = CurDAG->getTargetConstantPool(AM.CP, MVT::i32, AM.Alignment,
259 AM.Disp, AM.SymbolFlags);
264 assert(!AM.Disp &&
"Non-zero displacement is ignored with ES.");
265 Sym = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i32, AM.SymbolFlags);
270 assert(!AM.Disp &&
"Non-zero displacement is ignored with MCSym.");
271 assert(AM.SymbolFlags == 0 &&
"oo");
272 Sym = CurDAG->getMCSymbol(AM.MCSym, MVT::i32);
277 assert(!AM.Disp &&
"Non-zero displacement is ignored with JT.");
278 Sym = CurDAG->getTargetJumpTable(AM.JT, MVT::i32, AM.SymbolFlags);
283 Sym = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, AM.Disp,
293 return CurDAG->getTargetConstant(Imm,
DL, MVT::i8);
298 return CurDAG->getTargetConstant(Imm,
DL, MVT::i16);
303 return CurDAG->getTargetConstant(Imm,
DL, MVT::i32);
315 SDNode *getGlobalBaseReg();
318char M68kDAGToDAGISel::ID;
330 switch (
U->getOpcode()) {
359 return new M68kDAGToDAGISel(
TM);
363 if (!AM.isDispAddrType())
366 return isIntN(AM.getDispSize() - 1, AM.Disp);
370 if (!AM.isDispAddrType())
372 return isIntN(AM.getDispSize(), Val);
378SDNode *M68kDAGToDAGISel::getGlobalBaseReg() {
379 unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF);
380 auto &
DL = MF->getDataLayout();
381 return CurDAG->getRegister(GlobalBaseReg, TLI->getPointerTy(
DL)).getNode();
385 M68kISelAddressMode &AM) {
387 if (
Offset != 0 && (AM.ES || AM.MCSym))
390 int64_t Val = AM.Disp +
Offset;
406bool M68kDAGToDAGISel::matchAddressBase(
SDValue N, M68kISelAddressMode &AM) {
410 if (!AM.hasIndexReg()) {
421 AM.BaseType = M68kISelAddressMode::Base::RegBase;
427bool M68kDAGToDAGISel::matchLoadInAddress(
LoadSDNode *
N,
428 M68kISelAddressMode &AM) {
432bool M68kDAGToDAGISel::matchAddressRecursively(
SDValue N,
433 M68kISelAddressMode &AM,
439 return matchAddressBase(
N, AM);
444 if (AM.isPCRelative()) {
450 if (foldOffsetIntoAddress(Cst->getSExtValue(), AM))
455 switch (
N.getOpcode()) {
460 uint64_t Val = cast<ConstantSDNode>(
N)->getSExtValue();
461 if (foldOffsetIntoAddress(Val, AM))
468 if (matchWrapper(
N, AM))
473 if (matchLoadInAddress(cast<LoadSDNode>(
N), AM))
484 if (CurDAG->haveNoCommonBitsSet(
N.getOperand(0),
N.getOperand(1)) &&
490 if (matchADD(
N, AM,
Depth))
495 if (AM.isDispAddrType() &&
496 AM.BaseType == M68kISelAddressMode::Base::RegBase &&
498 AM.BaseType = M68kISelAddressMode::Base::FrameIndexBase;
499 AM.BaseFrameIndex = cast<FrameIndexSDNode>(
N)->getIndex();
505 return matchAddressBase(
N, AM);
510bool M68kDAGToDAGISel::matchAddress(
SDValue N, M68kISelAddressMode &AM) {
518 return matchAddressRecursively(
N, AM, 0);
521bool M68kDAGToDAGISel::matchADD(
SDValue &
N, M68kISelAddressMode &AM,
527 M68kISelAddressMode Backup = AM;
528 if (matchAddressRecursively(
N.getOperand(0), AM,
Depth + 1) &&
529 matchAddressRecursively(Handle.getValue().getOperand(1), AM,
Depth + 1)) {
535 if (matchAddressRecursively(Handle.getValue().getOperand(1), AM,
Depth + 1) &&
536 matchAddressRecursively(Handle.getValue().getOperand(0), AM,
Depth + 1)) {
544 if (!AM.hasBase() && !AM.hasIndexReg()) {
545 N = Handle.getValue();
546 AM.BaseReg =
N.getOperand(0);
547 AM.IndexReg =
N.getOperand(1);
552 N = Handle.getValue();
560bool M68kDAGToDAGISel::matchWrapper(
SDValue N, M68kISelAddressMode &AM) {
563 if (AM.hasSymbolicDisplacement())
571 M68kISelAddressMode Backup = AM;
577 if (
auto *
G = dyn_cast<GlobalAddressSDNode>(N0)) {
578 AM.GV =
G->getGlobal();
579 AM.SymbolFlags =
G->getTargetFlags();
580 if (!foldOffsetIntoAddress(
G->getOffset(), AM)) {
584 }
else if (
auto *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
585 AM.CP =
CP->getConstVal();
586 AM.Alignment =
CP->getAlign();
587 AM.SymbolFlags =
CP->getTargetFlags();
588 if (!foldOffsetIntoAddress(
CP->getOffset(), AM)) {
592 }
else if (
auto *S = dyn_cast<ExternalSymbolSDNode>(N0)) {
593 AM.ES = S->getSymbol();
594 AM.SymbolFlags = S->getTargetFlags();
595 }
else if (
auto *S = dyn_cast<MCSymbolSDNode>(N0)) {
596 AM.MCSym = S->getMCSymbol();
597 }
else if (
auto *J = dyn_cast<JumpTableSDNode>(N0)) {
598 AM.JT = J->getIndex();
599 AM.SymbolFlags = J->getTargetFlags();
600 }
else if (
auto *BA = dyn_cast<BlockAddressSDNode>(N0)) {
601 AM.BlockAddr = BA->getBlockAddress();
602 AM.SymbolFlags = BA->getTargetFlags();
603 if (!foldOffsetIntoAddress(BA->getOffset(), AM)) {
610 AM.setBaseReg(CurDAG->getRegister(M68k::PC, MVT::i32));
615 if (!AM.isDisp32()) {
620 if (
auto *
G = dyn_cast<GlobalAddressSDNode>(N0)) {
621 AM.GV =
G->getGlobal();
622 AM.Disp +=
G->getOffset();
623 AM.SymbolFlags =
G->getTargetFlags();
624 }
else if (
auto *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
625 AM.CP =
CP->getConstVal();
626 AM.Alignment =
CP->getAlign();
627 AM.Disp +=
CP->getOffset();
628 AM.SymbolFlags =
CP->getTargetFlags();
629 }
else if (
auto *S = dyn_cast<ExternalSymbolSDNode>(N0)) {
630 AM.ES = S->getSymbol();
631 AM.SymbolFlags = S->getTargetFlags();
632 }
else if (
auto *S = dyn_cast<MCSymbolSDNode>(N0)) {
633 AM.MCSym = S->getMCSymbol();
634 }
else if (
auto *J = dyn_cast<JumpTableSDNode>(N0)) {
635 AM.JT = J->getIndex();
636 AM.SymbolFlags = J->getTargetFlags();
637 }
else if (
auto *BA = dyn_cast<BlockAddressSDNode>(N0)) {
638 AM.BlockAddr = BA->getBlockAddress();
639 AM.Disp += BA->getOffset();
640 AM.SymbolFlags = BA->getTargetFlags();
654 unsigned Opcode =
Node->getOpcode();
659 if (
Node->isMachineOpcode()) {
670 SDValue GOT = CurDAG->getTargetExternalSymbol(
673 CurDAG->getMachineNode(M68k::LEA32q,
DL, MVT::i32, GOT);
674 ReplaceNode(
Node, Res);
679 ReplaceNode(
Node, getGlobalBaseReg());
701 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARID);
703 if (!matchAddress(
N, AM))
706 if (AM.isPCRelative()) {
707 LLVM_DEBUG(
dbgs() <<
"REJECT: Cannot match PC relative address\n");
712 if (getFrameIndexAddress(AM,
SDLoc(
N), Disp,
Base)) {
717 if (AM.hasIndexReg()) {
722 if (!AM.hasBaseReg()) {
727 if (getSymbolicDisplacement(AM,
SDLoc(
N), Disp)) {
728 assert(!AM.Disp &&
"Should not be any displacement");
740 Disp = getI16Imm(AM.Disp,
SDLoc(
N));
747 switch (
N.getOpcode()) {
751 [](
const SDUse &U) { return isAddressBase(U.get()); });
763 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARII);
766 if (!matchAddress(
N, AM))
769 if (AM.isPCRelative()) {
774 if (!AM.hasIndexReg()) {
779 if (!AM.hasBaseReg()) {
792 if (AM.hasSymbolicDisplacement()) {
793 LLVM_DEBUG(
dbgs() <<
"REJECT, Cannot match symbolic displacement\n");
806 Disp = getI8Imm(AM.Disp,
SDLoc(
N));
814 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::AL);
816 if (!matchAddress(
N, AM)) {
821 if (AM.isPCRelative()) {
822 LLVM_DEBUG(
dbgs() <<
"REJECT: Cannot match PC relative address\n");
831 if (AM.hasIndexReg()) {
836 if (getSymbolicDisplacement(AM,
SDLoc(
N),
Sym)) {
854 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::PCD);
856 if (!matchAddress(
N, AM))
859 if (!AM.isPCRelative()) {
864 if (AM.hasIndexReg()) {
869 if (getSymbolicDisplacement(AM,
SDLoc(
N), Disp)) {
874 Disp = getI16Imm(AM.Disp,
SDLoc(
N));
883 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::PCI);
885 if (!matchAddress(
N, AM))
888 if (!AM.isPCRelative()) {
893 if (!AM.hasIndexReg()) {
900 if (getSymbolicDisplacement(AM,
SDLoc(
N), Disp)) {
901 assert(!AM.Disp &&
"Should not be any displacement");
906 Disp = getI8Imm(AM.Disp,
SDLoc(
N));
914 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARI);
916 if (!matchAddress(
N, AM)) {
921 if (AM.isPCRelative()) {
922 LLVM_DEBUG(
dbgs() <<
"REJECT: Cannot match PC relative address\n");
927 if (AM.hasIndexReg() || AM.Disp != 0) {
933 if (AM.hasSymbolicDisplacement()) {
938 if (AM.hasBaseReg()) {
947bool M68kDAGToDAGISel::SelectInlineAsmMemoryOperand(
948 const SDValue &Op,
unsigned ConstraintID, std::vector<SDValue> &OutOps) {
954 auto addKind = [
this](
SDValue &Opnd, AMK
Kind) ->
bool {
955 Opnd = CurDAG->getTargetConstant(
unsigned(Kind),
SDLoc(), MVT::i32);
959 switch (ConstraintID) {
982 if ((SelectPCD(
nullptr, Op,
Operands[1]) && addKind(
Operands[0], AMK::q)) ||
997 if (SelectARI(
nullptr, Op,
Base) && addKind(AMKind, AMK::j)) {
998 OutOps.insert(OutOps.end(), {AMKind,
Base});
1007 if (SelectARID(
nullptr, Op,
Offset,
Base) && addKind(AMKind, AMK::p)) {
1008 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())
DEMANGLE_DUMP_METHOD void dump() const
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 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 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...
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, std::vector< SDValue > &OutOps)
SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode,...
#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.