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 {
100 return BaseType == Base::RegBase && BaseReg.getNode() !=
nullptr;
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 {
139 return RegNode->getReg() == M68k::PC;
150#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
152 dbgs() <<
"M68kISelAddressMode " <<
this;
153 dbgs() <<
"\nDisp: " << Disp;
154 dbgs() <<
", BaseReg: ";
155 if (BaseReg.getNode())
156 BaseReg.getNode()->dump();
159 dbgs() <<
", BaseFI: " << BaseFrameIndex;
160 dbgs() <<
", IndexReg: ";
165 dbgs() <<
", Scale: " << Scale;
177 M68kDAGToDAGISel() =
delete;
179 explicit M68kDAGToDAGISel(M68kTargetMachine &TM)
180 : SelectionDAGISel(
TM), Subtarget(nullptr) {}
182 bool runOnMachineFunction(MachineFunction &MF)
override;
183 bool IsProfitableToFold(
SDValue N, SDNode *U, SDNode *Root)
const override;
188 const M68kSubtarget *Subtarget;
191#include "M68kGenDAGISel.inc"
195 const M68kTargetMachine &getTargetMachine() {
196 return static_cast<const M68kTargetMachine &
>(
TM);
199 void Select(SDNode *
N)
override;
204 void initGlobalBaseReg(MachineFunction &MF);
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);
228 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
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,
291 inline SDValue getI8Imm(int64_t Imm,
const SDLoc &
DL) {
292 return CurDAG->getSignedTargetConstant(Imm,
DL, MVT::i8);
296 inline SDValue getI16Imm(int64_t Imm,
const SDLoc &
DL) {
297 return CurDAG->getSignedTargetConstant(Imm,
DL, MVT::i16);
301 inline SDValue getI32Imm(int64_t Imm,
const SDLoc &
DL) {
302 return CurDAG->getSignedTargetConstant(Imm,
DL, MVT::i32);
307 const M68kInstrInfo *getInstrInfo()
const {
308 return Subtarget->getInstrInfo();
314 SDNode *getGlobalBaseReg();
320 explicit M68kDAGToDAGISelLegacy(M68kTargetMachine &TM)
321 : SelectionDAGISelLegacy(ID, std::make_unique<M68kDAGToDAGISel>(
TM)) {}
324char M68kDAGToDAGISelLegacy::ID;
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();
390bool M68kDAGToDAGISel::foldOffsetIntoAddress(uint64_t
Offset,
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()) {
467 if (foldOffsetIntoAddress(Val, AM))
472 case M68kISD::Wrapper:
473 case M68kISD::WrapperPC:
474 if (matchWrapper(
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;
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,
538 HandleSDNode Handle(
N);
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();
565 N = Handle.getValue();
573bool M68kDAGToDAGISel::matchWrapper(
SDValue N, M68kISelAddressMode &AM) {
576 if (AM.hasSymbolicDisplacement())
581 if (
N.getOpcode() == M68kISD::WrapperPC) {
584 M68kISelAddressMode Backup = AM;
591 AM.GV =
G->getGlobal();
592 AM.SymbolFlags =
G->getTargetFlags();
593 if (!foldOffsetIntoAddress(
G->getOffset(), AM)) {
598 AM.CP =
CP->getConstVal();
599 AM.Alignment =
CP->getAlign();
600 AM.SymbolFlags =
CP->getTargetFlags();
601 if (!foldOffsetIntoAddress(
CP->getOffset(), AM)) {
606 AM.ES = S->getSymbol();
607 AM.SymbolFlags = S->getTargetFlags();
609 AM.MCSym = S->getMCSymbol();
611 AM.JT = J->getIndex();
612 AM.SymbolFlags = J->getTargetFlags();
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()) {
632 if (
N.getOpcode() == M68kISD::Wrapper) {
634 AM.GV =
G->getGlobal();
635 AM.Disp +=
G->getOffset();
636 AM.SymbolFlags =
G->getTargetFlags();
638 AM.CP =
CP->getConstVal();
639 AM.Alignment =
CP->getAlign();
640 AM.Disp +=
CP->getOffset();
641 AM.SymbolFlags =
CP->getTargetFlags();
643 AM.ES = S->getSymbol();
644 AM.SymbolFlags = S->getTargetFlags();
646 AM.MCSym = S->getMCSymbol();
648 AM.JT = J->getIndex();
649 AM.SymbolFlags = J->getTargetFlags();
651 AM.BlockAddr = BA->getBlockAddress();
652 AM.Disp += BA->getOffset();
653 AM.SymbolFlags = BA->getTargetFlags();
666void M68kDAGToDAGISel::Select(SDNode *Node) {
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);
691 case M68kISD::GLOBAL_BASE_REG:
692 ReplaceNode(Node, getGlobalBaseReg());
717 case ISD::ATOMIC_LOAD:
718 case ISD::ATOMIC_STORE:
725bool M68kDAGToDAGISel::SelectARID(SDNode *Parent,
SDValue N,
SDValue &Disp,
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()); });
781 case M68kISD::Wrapper:
782 case M68kISD::WrapperPC:
783 case M68kISD::GLOBAL_BASE_REG:
796 case ISD::ATOMIC_LOAD:
797 case ISD::ATOMIC_STORE:
798 case ISD::ATOMIC_CMP_SWAP:
805bool M68kDAGToDAGISel::SelectARII(SDNode *Parent,
SDValue N,
SDValue &Disp,
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));
855bool M68kDAGToDAGISel::SelectAL(SDNode *Parent,
SDValue N,
SDValue &Sym) {
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)) {
885 Sym = getI32Imm(AM.Disp, SDLoc(
N));
895bool M68kDAGToDAGISel::SelectPCD(SDNode *Parent,
SDValue N,
SDValue &Disp) {
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));
923bool M68kDAGToDAGISel::SelectPCI(SDNode *Parent,
SDValue N,
SDValue &Disp,
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: {
1029 OutOps.insert(OutOps.end(), {Operands[0], Operands[1]});
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});
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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)
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.
unsigned getTargetFlags() const
const GlobalValue * getGlobal() const
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.
Represents one node in the SelectionDAG.
LLVM_ABI 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
const SDValue & getOperand(unsigned i) const
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual bool runOnMachineFunction(MachineFunction &mf)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ ADDC
Carry-setting nodes for multiple precision addition and subtraction.
@ ADD
Simple integer binary arithmetic operators.
@ 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 ...
@ GlobalBaseReg
The result of the mflr at function entry, used for PIC code.
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto dyn_cast_or_null(const Y &Val)
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.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr 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.