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 ReplaceNode(
Node, getGlobalBaseReg());
692 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARID);
694 if (!matchAddress(
N, AM))
697 if (AM.isPCRelative()) {
698 LLVM_DEBUG(
dbgs() <<
"REJECT: Cannot match PC relative address\n");
703 if (getFrameIndexAddress(AM,
SDLoc(
N), Disp,
Base)) {
708 if (AM.hasIndexReg()) {
713 if (!AM.hasBaseReg()) {
718 if (getSymbolicDisplacement(AM,
SDLoc(
N), Disp)) {
719 assert(!AM.Disp &&
"Should not be any displacement");
731 Disp = getI16Imm(AM.Disp,
SDLoc(
N));
738 switch (
N.getOpcode()) {
742 [](
const SDUse &U) { return isAddressBase(U.get()); });
754 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARII);
757 if (!matchAddress(
N, AM))
760 if (AM.isPCRelative()) {
765 if (!AM.hasIndexReg()) {
770 if (!AM.hasBaseReg()) {
783 if (AM.hasSymbolicDisplacement()) {
784 LLVM_DEBUG(
dbgs() <<
"REJECT, Cannot match symbolic displacement\n");
797 Disp = getI8Imm(AM.Disp,
SDLoc(
N));
805 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::AL);
807 if (!matchAddress(
N, AM)) {
812 if (AM.isPCRelative()) {
813 LLVM_DEBUG(
dbgs() <<
"REJECT: Cannot match PC relative address\n");
822 if (AM.hasIndexReg()) {
827 if (getSymbolicDisplacement(AM,
SDLoc(
N), Sym)) {
833 Sym = getI32Imm(AM.Disp,
SDLoc(
N));
845 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::PCD);
847 if (!matchAddress(
N, AM))
850 if (!AM.isPCRelative()) {
855 if (AM.hasIndexReg()) {
860 if (getSymbolicDisplacement(AM,
SDLoc(
N), Disp)) {
865 Disp = getI16Imm(AM.Disp,
SDLoc(
N));
874 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::PCI);
876 if (!matchAddress(
N, AM))
879 if (!AM.isPCRelative()) {
884 if (!AM.hasIndexReg()) {
891 if (getSymbolicDisplacement(AM,
SDLoc(
N), Disp)) {
892 assert(!AM.Disp &&
"Should not be any displacement");
897 Disp = getI8Imm(AM.Disp,
SDLoc(
N));
905 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARI);
907 if (!matchAddress(
N, AM)) {
912 if (AM.isPCRelative()) {
913 LLVM_DEBUG(
dbgs() <<
"REJECT: Cannot match PC relative address\n");
918 if (AM.hasIndexReg() || AM.Disp != 0) {
924 if (AM.hasSymbolicDisplacement()) {
929 if (AM.hasBaseReg()) {
938bool M68kDAGToDAGISel::SelectInlineAsmMemoryOperand(
939 const SDValue &Op,
unsigned ConstraintID, std::vector<SDValue> &OutOps) {
945 auto addKind = [
this](
SDValue &Opnd, AMK
Kind) ->
bool {
946 Opnd = CurDAG->getTargetConstant(
unsigned(Kind),
SDLoc(),
MVT::i32);
950 switch (ConstraintID) {
973 if ((SelectPCD(
nullptr, Op,
Operands[1]) && addKind(
Operands[0], AMK::q)) ||
988 if (SelectARI(
nullptr, Op,
Base) && addKind(AMKind, AMK::j)) {
989 OutOps.insert(OutOps.end(), {AMKind,
Base});
998 if (SelectARID(
nullptr, Op,
Offset,
Base) && addKind(AMKind, AMK::p)) {
999 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.
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...
@ 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.