1 //===- XtensaISelDAGToDAG.cpp - A dag to dag inst selector for Xtensa -----===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines an instruction selector for the Xtensa target.
11 //===----------------------------------------------------------------------===//
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"
25 #define DEBUG_TYPE "xtensa-isel"
29 class XtensaDAGToDAGISel
: public SelectionDAGISel
{
31 XtensaDAGToDAGISel(XtensaTargetMachine
&TM
, CodeGenOptLevel OptLevel
)
32 : SelectionDAGISel(TM
, OptLevel
) {}
34 void Select(SDNode
*Node
) override
;
36 // For load/store instructions generate (base+offset) pair from
37 // memory address. The offset must be a multiple of scale argument.
38 bool selectMemRegAddr(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
,
40 EVT ValTy
= Addr
.getValueType();
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
);
50 if (TM
.isPositionIndependent()) {
51 DiagnosticInfoUnsupported
Diag(CurDAG
->getMachineFunction().getFunction(),
52 "PIC relocations are not supported ",
54 CurDAG
->getContext()->diagnose(Diag
);
57 if ((Addr
.getOpcode() == ISD::TargetExternalSymbol
||
58 Addr
.getOpcode() == ISD::TargetGlobalAddress
))
61 // Addresses of the form FI+const
63 if (CurDAG
->isBaseWithConstantOffset(Addr
)) {
64 ConstantSDNode
*CN
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1));
65 int64_t OffsetVal
= CN
->getSExtValue();
67 Valid
= isValidAddrOffset(Scale
, OffsetVal
);
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
);
75 Base
= Addr
.getOperand(0);
78 CurDAG
->getTargetConstant(CN
->getZExtValue(), SDLoc(Addr
), ValTy
);
85 Offset
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), Addr
.getValueType());
89 bool selectMemRegAddrISH1(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
) {
90 return selectMemRegAddr(Addr
, Base
, Offset
, 1);
93 bool selectMemRegAddrISH2(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
) {
94 return selectMemRegAddr(Addr
, Base
, Offset
, 2);
97 bool selectMemRegAddrISH4(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
) {
98 return selectMemRegAddr(Addr
, Base
, Offset
, 4);
101 // Include the pieces autogenerated from the target description.
102 #include "XtensaGenDAGISel.inc"
105 class XtensaDAGToDAGISelLegacy
: public SelectionDAGISelLegacy
{
109 XtensaDAGToDAGISelLegacy(XtensaTargetMachine
&TM
, CodeGenOptLevel OptLevel
)
110 : SelectionDAGISelLegacy(
111 ID
, std::make_unique
<XtensaDAGToDAGISel
>(TM
, OptLevel
)) {}
113 StringRef
getPassName() const override
{
114 return "Xtensa DAG->DAG Pattern Instruction Selection";
117 } // end anonymous namespace
119 char XtensaDAGToDAGISelLegacy::ID
= 0;
121 FunctionPass
*llvm::createXtensaISelDag(XtensaTargetMachine
&TM
,
122 CodeGenOptLevel OptLevel
) {
123 return new XtensaDAGToDAGISelLegacy(TM
, OptLevel
);
126 void XtensaDAGToDAGISel::Select(SDNode
*Node
) {
129 // If we have a custom node, we already have selected!
130 if (Node
->isMachineOpcode()) {