1 //===- XtensaISelDAGToDAG.cpp - A dag to dag inst selector for Xtensa -----===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines an instruction selector for the Xtensa target.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "Xtensa.h"
14 #include "XtensaTargetMachine.h"
15 #include "XtensaUtils.h"
16 #include "llvm/CodeGen/MachineFunction.h"
17 #include "llvm/CodeGen/MachineRegisterInfo.h"
18 #include "llvm/CodeGen/SelectionDAGISel.h"
19 #include "llvm/IR/DiagnosticInfo.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/raw_ostream.h"
22
23 using namespace llvm;
24
25 #define DEBUG_TYPE "xtensa-isel"
26
27 namespace {
28
29 class XtensaDAGToDAGISel : public SelectionDAGISel {
30 public:
XtensaDAGToDAGISel(XtensaTargetMachine & TM,CodeGenOptLevel OptLevel)31 XtensaDAGToDAGISel(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel)
32 : SelectionDAGISel(TM, OptLevel) {}
33
34 void Select(SDNode *Node) override;
35
36 // For load/store instructions generate (base+offset) pair from
37 // memory address. The offset must be a multiple of scale argument.
selectMemRegAddr(SDValue Addr,SDValue & Base,SDValue & Offset,int Scale)38 bool selectMemRegAddr(SDValue Addr, SDValue &Base, SDValue &Offset,
39 int Scale) {
40 EVT ValTy = Addr.getValueType();
41
42 // if Address is FI, get the TargetFrameIndex.
43 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
44 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
45 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), ValTy);
46
47 return true;
48 }
49
50 if (TM.isPositionIndependent()) {
51 DiagnosticInfoUnsupported Diag(CurDAG->getMachineFunction().getFunction(),
52 "PIC relocations are not supported ",
53 Addr.getDebugLoc());
54 CurDAG->getContext()->diagnose(Diag);
55 }
56
57 if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
58 Addr.getOpcode() == ISD::TargetGlobalAddress))
59 return false;
60
61 // Addresses of the form FI+const
62 bool Valid = false;
63 if (CurDAG->isBaseWithConstantOffset(Addr)) {
64 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
65 int64_t OffsetVal = CN->getSExtValue();
66
67 Valid = isValidAddrOffset(Scale, OffsetVal);
68
69 if (Valid) {
70 // If the first operand is a FI, get the TargetFI Node
71 if (FrameIndexSDNode *FIN =
72 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
73 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
74 else
75 Base = Addr.getOperand(0);
76
77 Offset =
78 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), ValTy);
79 return true;
80 }
81 }
82
83 // Last case
84 Base = Addr;
85 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), Addr.getValueType());
86 return true;
87 }
88
selectMemRegAddrISH1(SDValue Addr,SDValue & Base,SDValue & Offset)89 bool selectMemRegAddrISH1(SDValue Addr, SDValue &Base, SDValue &Offset) {
90 return selectMemRegAddr(Addr, Base, Offset, 1);
91 }
92
selectMemRegAddrISH2(SDValue Addr,SDValue & Base,SDValue & Offset)93 bool selectMemRegAddrISH2(SDValue Addr, SDValue &Base, SDValue &Offset) {
94 return selectMemRegAddr(Addr, Base, Offset, 2);
95 }
96
selectMemRegAddrISH4(SDValue Addr,SDValue & Base,SDValue & Offset)97 bool selectMemRegAddrISH4(SDValue Addr, SDValue &Base, SDValue &Offset) {
98 return selectMemRegAddr(Addr, Base, Offset, 4);
99 }
100
101 // Include the pieces autogenerated from the target description.
102 #include "XtensaGenDAGISel.inc"
103 }; // namespace
104
105 class XtensaDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
106 public:
107 static char ID;
108
XtensaDAGToDAGISelLegacy(XtensaTargetMachine & TM,CodeGenOptLevel OptLevel)109 XtensaDAGToDAGISelLegacy(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel)
110 : SelectionDAGISelLegacy(
111 ID, std::make_unique<XtensaDAGToDAGISel>(TM, OptLevel)) {}
112
getPassName() const113 StringRef getPassName() const override {
114 return "Xtensa DAG->DAG Pattern Instruction Selection";
115 }
116 };
117 } // end anonymous namespace
118
119 char XtensaDAGToDAGISelLegacy::ID = 0;
120
createXtensaISelDag(XtensaTargetMachine & TM,CodeGenOptLevel OptLevel)121 FunctionPass *llvm::createXtensaISelDag(XtensaTargetMachine &TM,
122 CodeGenOptLevel OptLevel) {
123 return new XtensaDAGToDAGISelLegacy(TM, OptLevel);
124 }
125
Select(SDNode * Node)126 void XtensaDAGToDAGISel::Select(SDNode *Node) {
127 SDLoc DL(Node);
128
129 // If we have a custom node, we already have selected!
130 if (Node->isMachineOpcode()) {
131 Node->setNodeId(-1);
132 return;
133 }
134
135 SelectCode(Node);
136 }
137