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;
177 M68kDAGToDAGISel() =
delete;
191#include "M68kGenDAGISel.inc"
206 bool foldOffsetIntoAddress(
uint64_t Offset, M68kISelAddressMode &AM);
208 bool matchLoadInAddress(
LoadSDNode *
N, M68kISelAddressMode &AM);
209 bool matchAddress(
SDValue N, M68kISelAddressMode &AM);
210 bool matchAddressBase(
SDValue N, M68kISelAddressMode &AM);
211 bool matchAddressRecursively(
SDValue N, M68kISelAddressMode &AM,
213 bool matchADD(
SDValue &
N, M68kISelAddressMode &AM,
unsigned Depth);
214 bool matchWrapper(
SDValue N, M68kISelAddressMode &AM);
216 std::pair<bool, SDNode *> selectNode(
SDNode *
Node);
230 std::vector<SDValue> &OutOps)
override;
235 inline bool getFrameIndexAddress(M68kISelAddressMode &AM,
const SDLoc &
DL,
237 if (AM.BaseType == M68kISelAddressMode::Base::FrameIndexBase) {
238 Disp = getI32Imm(AM.Disp,
DL);
239 Base = CurDAG->getTargetFrameIndex(
240 AM.BaseFrameIndex, TLI->getPointerTy(CurDAG->getDataLayout()));
248 inline bool getSymbolicDisplacement(M68kISelAddressMode &AM,
const SDLoc &
DL,
251 Sym = CurDAG->getTargetGlobalAddress(AM.GV,
SDLoc(), MVT::i32, AM.Disp,
257 Sym = CurDAG->getTargetConstantPool(AM.CP, MVT::i32, AM.Alignment,
258 AM.Disp, AM.SymbolFlags);
263 assert(!AM.Disp &&
"Non-zero displacement is ignored with ES.");
264 Sym = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i32, AM.SymbolFlags);
269 assert(!AM.Disp &&
"Non-zero displacement is ignored with MCSym.");
270 assert(AM.SymbolFlags == 0 &&
"oo");
271 Sym = CurDAG->getMCSymbol(AM.MCSym, MVT::i32);
276 assert(!AM.Disp &&
"Non-zero displacement is ignored with JT.");
277 Sym = CurDAG->getTargetJumpTable(AM.JT, MVT::i32, AM.SymbolFlags);
282 Sym = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, AM.Disp,
292 return CurDAG->getSignedTargetConstant(Imm,
DL, MVT::i8);
297 return CurDAG->getSignedTargetConstant(Imm,
DL, MVT::i16);
302 return CurDAG->getSignedTargetConstant(Imm,
DL, MVT::i32);
314 SDNode *getGlobalBaseReg();
324char M68kDAGToDAGISelLegacy::ID;
332 if (OptLevel == CodeGenOptLevel::None)
336 switch (
U->getOpcode()) {
365 return new M68kDAGToDAGISelLegacy(TM);
369 if (!AM.isDispAddrType())
372 return isIntN(AM.getDispSize() - 1, AM.Disp);
376 if (!AM.isDispAddrType())
378 return isIntN(AM.getDispSize(), Val);
384SDNode *M68kDAGToDAGISel::getGlobalBaseReg() {
385 unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF);
386 auto &
DL = MF->getDataLayout();
387 return CurDAG->getRegister(GlobalBaseReg, TLI->getPointerTy(
DL)).getNode();
391 M68kISelAddressMode &AM) {
393 if (
Offset != 0 && (AM.ES || AM.MCSym))
396 int64_t Val = AM.Disp +
Offset;
412bool M68kDAGToDAGISel::matchAddressBase(
SDValue N, M68kISelAddressMode &AM) {
416 if (!AM.hasIndexReg()) {
427 AM.BaseType = M68kISelAddressMode::Base::RegBase;
433bool M68kDAGToDAGISel::matchLoadInAddress(
LoadSDNode *
N,
434 M68kISelAddressMode &AM) {
438bool M68kDAGToDAGISel::matchAddressRecursively(
SDValue N,
439 M68kISelAddressMode &AM,
445 return matchAddressBase(
N, AM);
450 if (AM.isPCRelative()) {
456 if (foldOffsetIntoAddress(Cst->getSExtValue(), AM))
461 switch (
N.getOpcode()) {
466 uint64_t Val = cast<ConstantSDNode>(
N)->getSExtValue();
467 if (foldOffsetIntoAddress(Val, AM))
474 if (matchWrapper(
N, AM))
479 if (matchLoadInAddress(cast<LoadSDNode>(
N), AM))
490 if (CurDAG->haveNoCommonBitsSet(
N.getOperand(0),
N.getOperand(1)) &&
496 if (matchADD(
N, AM,
Depth))
501 if (AM.isDispAddrType() &&
502 AM.BaseType == M68kISelAddressMode::Base::RegBase &&
504 AM.BaseType = M68kISelAddressMode::Base::FrameIndexBase;
505 AM.BaseFrameIndex = cast<FrameIndexSDNode>(
N)->getIndex();
518 return matchAddressBase(
N, AM);
523bool M68kDAGToDAGISel::matchAddress(
SDValue N, M68kISelAddressMode &AM) {
531 return matchAddressRecursively(
N, AM, 0);
534bool M68kDAGToDAGISel::matchADD(
SDValue &
N, M68kISelAddressMode &AM,
540 M68kISelAddressMode Backup = AM;
541 if (matchAddressRecursively(
N.getOperand(0), AM,
Depth + 1) &&
542 matchAddressRecursively(Handle.getValue().getOperand(1), AM,
Depth + 1)) {
548 if (matchAddressRecursively(Handle.getValue().getOperand(1), AM,
Depth + 1) &&
549 matchAddressRecursively(Handle.getValue().getOperand(0), AM,
Depth + 1)) {
557 if (!AM.hasBase() && !AM.hasIndexReg()) {
558 N = Handle.getValue();
559 AM.BaseReg =
N.getOperand(0);
560 AM.IndexReg =
N.getOperand(1);
565 N = Handle.getValue();
573bool M68kDAGToDAGISel::matchWrapper(
SDValue N, M68kISelAddressMode &AM) {
576 if (AM.hasSymbolicDisplacement())
584 M68kISelAddressMode Backup = AM;
590 if (
auto *
G = dyn_cast<GlobalAddressSDNode>(N0)) {
591 AM.GV =
G->getGlobal();
592 AM.SymbolFlags =
G->getTargetFlags();
593 if (!foldOffsetIntoAddress(
G->getOffset(), AM)) {
597 }
else if (
auto *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
598 AM.CP =
CP->getConstVal();
599 AM.Alignment =
CP->getAlign();
600 AM.SymbolFlags =
CP->getTargetFlags();
601 if (!foldOffsetIntoAddress(
CP->getOffset(), AM)) {
605 }
else if (
auto *S = dyn_cast<ExternalSymbolSDNode>(N0)) {
606 AM.ES = S->getSymbol();
607 AM.SymbolFlags = S->getTargetFlags();
608 }
else if (
auto *S = dyn_cast<MCSymbolSDNode>(N0)) {
609 AM.MCSym = S->getMCSymbol();
610 }
else if (
auto *J = dyn_cast<JumpTableSDNode>(N0)) {
611 AM.JT = J->getIndex();
612 AM.SymbolFlags = J->getTargetFlags();
613 }
else if (
auto *BA = dyn_cast<BlockAddressSDNode>(N0)) {
614 AM.BlockAddr = BA->getBlockAddress();
615 AM.SymbolFlags = BA->getTargetFlags();
616 if (!foldOffsetIntoAddress(BA->getOffset(), AM)) {
623 AM.setBaseReg(CurDAG->getRegister(M68k::PC, MVT::i32));
628 if (!AM.isDisp32()) {
633 if (
auto *
G = dyn_cast<GlobalAddressSDNode>(N0)) {
634 AM.GV =
G->getGlobal();
635 AM.Disp +=
G->getOffset();
636 AM.SymbolFlags =
G->getTargetFlags();
637 }
else if (
auto *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
638 AM.CP =
CP->getConstVal();
639 AM.Alignment =
CP->getAlign();
640 AM.Disp +=
CP->getOffset();
641 AM.SymbolFlags =
CP->getTargetFlags();
642 }
else if (
auto *S = dyn_cast<ExternalSymbolSDNode>(N0)) {
643 AM.ES = S->getSymbol();
644 AM.SymbolFlags = S->getTargetFlags();
645 }
else if (
auto *S = dyn_cast<MCSymbolSDNode>(N0)) {
646 AM.MCSym = S->getMCSymbol();
647 }
else if (
auto *J = dyn_cast<JumpTableSDNode>(N0)) {
648 AM.JT = J->getIndex();
649 AM.SymbolFlags = J->getTargetFlags();
650 }
else if (
auto *BA = dyn_cast<BlockAddressSDNode>(N0)) {
651 AM.BlockAddr = BA->getBlockAddress();
652 AM.Disp += BA->getOffset();
653 AM.SymbolFlags = BA->getTargetFlags();
667 unsigned Opcode =
Node->getOpcode();
672 if (
Node->isMachineOpcode()) {
683 SDValue GOT = CurDAG->getTargetExternalSymbol(
686 CurDAG->getMachineNode(M68k::LEA32q,
DL, MVT::i32, GOT);
687 ReplaceNode(
Node, Res);
692 ReplaceNode(
Node, getGlobalBaseReg());
728 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARID);
730 if (!matchAddress(
N, AM))
733 if (AM.isPCRelative()) {
734 LLVM_DEBUG(
dbgs() <<
"REJECT: Cannot match PC relative address\n");
739 if (getFrameIndexAddress(AM,
SDLoc(
N), Disp,
Base)) {
744 if (AM.hasIndexReg()) {
749 if (!AM.hasBaseReg()) {
756 if (getSymbolicDisplacement(AM,
SDLoc(
N), Disp)) {
758 "Should not be any displacement");
769 Disp = getI16Imm(AM.Disp,
SDLoc(
N));
776 switch (
N.getOpcode()) {
780 [](
const SDUse &U) { return isAddressBase(U.get()); });
807 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARII);
810 if (!matchAddress(
N, AM))
813 if (AM.isPCRelative()) {
818 if (!AM.hasIndexReg()) {
823 if (!AM.hasBaseReg()) {
836 if (AM.hasSymbolicDisplacement()) {
837 LLVM_DEBUG(
dbgs() <<
"REJECT, Cannot match symbolic displacement\n");
849 Disp = getI8Imm(AM.Disp,
SDLoc(
N));
857 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::AL);
859 if (!matchAddress(
N, AM)) {
864 if (AM.isPCRelative()) {
865 LLVM_DEBUG(
dbgs() <<
"REJECT: Cannot match PC relative address\n");
874 if (AM.hasIndexReg()) {
879 if (getSymbolicDisplacement(AM,
SDLoc(
N),
Sym)) {
897 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::PCD);
899 if (!matchAddress(
N, AM))
902 if (!AM.isPCRelative()) {
907 if (AM.hasIndexReg()) {
912 if (getSymbolicDisplacement(AM,
SDLoc(
N), Disp)) {
917 Disp = getI16Imm(AM.Disp,
SDLoc(
N));
926 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::PCI);
928 if (!matchAddress(
N, AM))
931 if (!AM.isPCRelative()) {
936 if (!AM.hasIndexReg()) {
943 if (getSymbolicDisplacement(AM,
SDLoc(
N), Disp)) {
944 assert(!AM.Disp &&
"Should not be any displacement");
949 Disp = getI8Imm(AM.Disp,
SDLoc(
N));
957 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARI);
959 if (!matchAddress(
N, AM)) {
964 if (AM.isPCRelative()) {
965 LLVM_DEBUG(
dbgs() <<
"REJECT: Cannot match PC relative address\n");
970 if (AM.hasIndexReg() || AM.Disp != 0) {
976 if (AM.hasSymbolicDisplacement()) {
981 if (AM.hasBaseReg()) {
990bool M68kDAGToDAGISel::SelectInlineAsmMemoryOperand(
992 std::vector<SDValue> &OutOps) {
998 auto addKind = [
this](
SDValue &Opnd, AMK
Kind) ->
bool {
999 Opnd = CurDAG->getTargetConstant(
unsigned(Kind),
SDLoc(), MVT::i32);
1003 switch (ConstraintID) {
1005 case InlineAsm::ConstraintCode::m: {
1036 case InlineAsm::ConstraintCode::Q: {
1041 if (SelectARI(
nullptr,
Op,
Base) && addKind(AMKind, AMK::j)) {
1042 OutOps.insert(OutOps.end(), {AMKind,
Base});
1048 case InlineAsm::ConstraintCode::Um: {
1051 if (SelectARID(
nullptr,
Op,
Offset,
Base) && addKind(AMKind, AMK::p)) {
1052 OutOps.insert(OutOps.end(), {AMKind,
Offset,
Base});
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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 allowARIDWithDisp(SDNode *Parent)
static bool doesDispFitFI(M68kISelAddressMode &AM)
static bool isAddressBase(const SDValue &N)
static bool AllowARIIWithZeroDisp(SDNode *Parent)
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 ...
#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.
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 ...
virtual bool runOnMachineFunction(MachineFunction &mf)
#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.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ 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...
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ 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.
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.