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
23using namespace llvm;
24
25#define DEBUG_TYPE "xtensa-isel"
26
27namespace {
28
29class XtensaDAGToDAGISel : public SelectionDAGISel {
30public:
31 static char ID;
32
33 XtensaDAGToDAGISel(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel)
34 : SelectionDAGISel(ID, TM, OptLevel) {}
35
36 StringRef getPassName() const override {
37 return "Xtensa DAG->DAG Pattern Instruction Selection";
38 }
39
40 void Select(SDNode *Node) override;
41
42 // For load/store instructions generate (base+offset) pair from
43 // memory address. The offset must be a multiple of scale argument.
44 bool selectMemRegAddr(SDValue Addr, SDValue &Base, SDValue &Offset,
45 int Scale) {
46 EVT ValTy = Addr.getValueType();
47
48 // if Address is FI, get the TargetFrameIndex.
49 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
50 Base = CurDAG->getTargetFrameIndex(FI: FIN->getIndex(), VT: ValTy);
51 Offset = CurDAG->getTargetConstant(Val: 0, DL: SDLoc(Addr), VT: ValTy);
52
53 return true;
54 }
55
56 if (TM.isPositionIndependent()) {
57 DiagnosticInfoUnsupported Diag(CurDAG->getMachineFunction().getFunction(),
58 "PIC relocations are not supported ",
59 Addr.getDebugLoc());
60 CurDAG->getContext()->diagnose(DI: Diag);
61 }
62
63 if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
64 Addr.getOpcode() == ISD::TargetGlobalAddress))
65 return false;
66
67 // Addresses of the form FI+const
68 bool Valid = false;
69 if (CurDAG->isBaseWithConstantOffset(Op: Addr)) {
70 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(i: 1));
71 int64_t OffsetVal = CN->getSExtValue();
72
73 Valid = isValidAddrOffset(Scale, OffsetVal);
74
75 if (Valid) {
76 // If the first operand is a FI, get the TargetFI Node
77 if (FrameIndexSDNode *FIN =
78 dyn_cast<FrameIndexSDNode>(Addr.getOperand(i: 0)))
79 Base = CurDAG->getTargetFrameIndex(FI: FIN->getIndex(), VT: ValTy);
80 else
81 Base = Addr.getOperand(i: 0);
82
83 Offset =
84 CurDAG->getTargetConstant(Val: CN->getZExtValue(), DL: SDLoc(Addr), VT: ValTy);
85 return true;
86 }
87 }
88
89 // Last case
90 Base = Addr;
91 Offset = CurDAG->getTargetConstant(Val: 0, DL: SDLoc(Addr), VT: Addr.getValueType());
92 return true;
93 }
94
95 bool selectMemRegAddrISH1(SDValue Addr, SDValue &Base, SDValue &Offset) {
96 return selectMemRegAddr(Addr, Base, Offset, Scale: 1);
97 }
98
99 bool selectMemRegAddrISH2(SDValue Addr, SDValue &Base, SDValue &Offset) {
100 return selectMemRegAddr(Addr, Base, Offset, Scale: 2);
101 }
102
103 bool selectMemRegAddrISH4(SDValue Addr, SDValue &Base, SDValue &Offset) {
104 return selectMemRegAddr(Addr, Base, Offset, Scale: 4);
105 }
106
107// Include the pieces autogenerated from the target description.
108#include "XtensaGenDAGISel.inc"
109}; // namespace
110} // end anonymous namespace
111
112char XtensaDAGToDAGISel::ID = 0;
113
114FunctionPass *llvm::createXtensaISelDag(XtensaTargetMachine &TM,
115 CodeGenOptLevel OptLevel) {
116 return new XtensaDAGToDAGISel(TM, OptLevel);
117}
118
119void XtensaDAGToDAGISel::Select(SDNode *Node) {
120 SDLoc DL(Node);
121
122 // If we have a custom node, we already have selected!
123 if (Node->isMachineOpcode()) {
124 Node->setNodeId(-1);
125 return;
126 }
127
128 SelectCode(Node);
129}
130

source code of llvm/lib/Target/Xtensa/XtensaISelDAGToDAG.cpp