1 //===-- LanaiISelDAGToDAG.cpp - A dag to dag inst selector for Lanai ------===//
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 Lanai target.
11 //===----------------------------------------------------------------------===//
13 #include "LanaiAluCode.h"
14 #include "LanaiMachineFunctionInfo.h"
15 #include "LanaiRegisterInfo.h"
16 #include "LanaiSubtarget.h"
17 #include "LanaiTargetMachine.h"
18 #include "llvm/CodeGen/MachineConstantPool.h"
19 #include "llvm/CodeGen/MachineFrameInfo.h"
20 #include "llvm/CodeGen/MachineFunction.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 #include "llvm/CodeGen/MachineRegisterInfo.h"
23 #include "llvm/CodeGen/SelectionDAGISel.h"
24 #include "llvm/IR/CFG.h"
25 #include "llvm/IR/GlobalValue.h"
26 #include "llvm/IR/Instructions.h"
27 #include "llvm/IR/Intrinsics.h"
28 #include "llvm/IR/Type.h"
29 #include "llvm/Support/Debug.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/raw_ostream.h"
32 #include "llvm/Target/TargetMachine.h"
36 #define DEBUG_TYPE "lanai-isel"
37 #define PASS_NAME "Lanai DAG->DAG Pattern Instruction Selection"
39 //===----------------------------------------------------------------------===//
40 // Instruction Selector Implementation
41 //===----------------------------------------------------------------------===//
43 //===----------------------------------------------------------------------===//
44 // LanaiDAGToDAGISel - Lanai specific code to select Lanai machine
45 // instructions for SelectionDAG operations.
46 //===----------------------------------------------------------------------===//
49 class LanaiDAGToDAGISel
: public SelectionDAGISel
{
51 LanaiDAGToDAGISel() = delete;
53 explicit LanaiDAGToDAGISel(LanaiTargetMachine
&TargetMachine
)
54 : SelectionDAGISel(TargetMachine
) {}
56 bool SelectInlineAsmMemoryOperand(const SDValue
&Op
,
57 InlineAsm::ConstraintCode ConstraintCode
,
58 std::vector
<SDValue
> &OutOps
) override
;
61 // Include the pieces autogenerated from the target description.
62 #include "LanaiGenDAGISel.inc"
64 // Instruction Selection not handled by the auto-generated tablgen
65 void Select(SDNode
*N
) override
;
67 // Support functions for the opcodes of Instruction Selection
68 // not handled by the auto-generated tablgen
69 void selectFrameIndex(SDNode
*N
);
71 // Complex Pattern for address selection.
72 bool selectAddrRi(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
,
74 bool selectAddrRr(SDValue Addr
, SDValue
&R1
, SDValue
&R2
, SDValue
&AluOp
);
75 bool selectAddrSls(SDValue Addr
, SDValue
&Offset
);
76 bool selectAddrSpls(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
,
79 // getI32Imm - Return a target constant with the specified value, of type i32.
80 inline SDValue
getI32Imm(unsigned Imm
, const SDLoc
&DL
) {
81 return CurDAG
->getTargetConstant(Imm
, DL
, MVT::i32
);
85 bool selectAddrRiSpls(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
,
86 SDValue
&AluOp
, bool RiMode
);
89 bool canBeRepresentedAsSls(const ConstantSDNode
&CN
) {
90 // Fits in 21-bit signed immediate and two low-order bits are zero.
91 return isInt
<21>(CN
.getSExtValue()) && ((CN
.getSExtValue() & 0x3) == 0);
94 class LanaiDAGToDAGISelLegacy
: public SelectionDAGISelLegacy
{
97 explicit LanaiDAGToDAGISelLegacy(LanaiTargetMachine
&TM
)
98 : SelectionDAGISelLegacy(ID
, std::make_unique
<LanaiDAGToDAGISel
>(TM
)) {}
103 char LanaiDAGToDAGISelLegacy::ID
= 0;
105 INITIALIZE_PASS(LanaiDAGToDAGISelLegacy
, DEBUG_TYPE
, PASS_NAME
, false, false)
107 // Helper functions for ComplexPattern used on LanaiInstrInfo
108 // Used on Lanai Load/Store instructions.
109 bool LanaiDAGToDAGISel::selectAddrSls(SDValue Addr
, SDValue
&Offset
) {
110 if (ConstantSDNode
*CN
= dyn_cast
<ConstantSDNode
>(Addr
)) {
112 // Loading from a constant address.
113 if (canBeRepresentedAsSls(*CN
)) {
114 int32_t Imm
= CN
->getSExtValue();
115 Offset
= CurDAG
->getTargetConstant(Imm
, DL
, CN
->getValueType(0));
119 if (Addr
.getOpcode() == ISD::OR
&&
120 Addr
.getOperand(1).getOpcode() == LanaiISD::SMALL
) {
121 Offset
= Addr
.getOperand(1).getOperand(0);
127 bool LanaiDAGToDAGISel::selectAddrRiSpls(SDValue Addr
, SDValue
&Base
,
128 SDValue
&Offset
, SDValue
&AluOp
,
132 if (ConstantSDNode
*CN
= dyn_cast
<ConstantSDNode
>(Addr
)) {
134 // Fits in 16-bit signed immediate.
135 if (isInt
<16>(CN
->getSExtValue())) {
136 int16_t Imm
= CN
->getSExtValue();
137 Offset
= CurDAG
->getTargetConstant(Imm
, DL
, CN
->getValueType(0));
138 Base
= CurDAG
->getRegister(Lanai::R0
, CN
->getValueType(0));
139 AluOp
= CurDAG
->getTargetConstant(LPAC::ADD
, DL
, MVT::i32
);
142 // Allow SLS to match if the constant doesn't fit in 16 bits but can be
143 // represented as an SLS.
144 if (canBeRepresentedAsSls(*CN
))
147 // Fits in 10-bit signed immediate.
148 if (isInt
<10>(CN
->getSExtValue())) {
149 int16_t Imm
= CN
->getSExtValue();
150 Offset
= CurDAG
->getTargetConstant(Imm
, DL
, CN
->getValueType(0));
151 Base
= CurDAG
->getRegister(Lanai::R0
, CN
->getValueType(0));
152 AluOp
= CurDAG
->getTargetConstant(LPAC::ADD
, DL
, MVT::i32
);
158 // if Address is FI, get the TargetFrameIndex.
159 if (FrameIndexSDNode
*FIN
= dyn_cast
<FrameIndexSDNode
>(Addr
)) {
160 Base
= CurDAG
->getTargetFrameIndex(
162 getTargetLowering()->getPointerTy(CurDAG
->getDataLayout()));
163 Offset
= CurDAG
->getTargetConstant(0, DL
, MVT::i32
);
164 AluOp
= CurDAG
->getTargetConstant(LPAC::ADD
, DL
, MVT::i32
);
169 if ((Addr
.getOpcode() == ISD::TargetExternalSymbol
||
170 Addr
.getOpcode() == ISD::TargetGlobalAddress
))
173 // Address of the form imm + reg
174 ISD::NodeType AluOperator
= static_cast<ISD::NodeType
>(Addr
.getOpcode());
175 if (AluOperator
== ISD::ADD
) {
176 AluOp
= CurDAG
->getTargetConstant(LPAC::ADD
, DL
, MVT::i32
);
177 // Addresses of the form FI+const
178 if (ConstantSDNode
*CN
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1)))
179 if ((RiMode
&& isInt
<16>(CN
->getSExtValue())) ||
180 (!RiMode
&& isInt
<10>(CN
->getSExtValue()))) {
181 // If the first operand is a FI, get the TargetFI Node
182 if (FrameIndexSDNode
*FIN
=
183 dyn_cast
<FrameIndexSDNode
>(Addr
.getOperand(0))) {
184 Base
= CurDAG
->getTargetFrameIndex(
186 getTargetLowering()->getPointerTy(CurDAG
->getDataLayout()));
188 Base
= Addr
.getOperand(0);
191 Offset
= CurDAG
->getTargetConstant(CN
->getSExtValue(), DL
, MVT::i32
);
196 // Let SLS match SMALL instead of RI.
197 if (AluOperator
== ISD::OR
&& RiMode
&&
198 Addr
.getOperand(1).getOpcode() == LanaiISD::SMALL
)
202 Offset
= CurDAG
->getTargetConstant(0, DL
, MVT::i32
);
203 AluOp
= CurDAG
->getTargetConstant(LPAC::ADD
, DL
, MVT::i32
);
207 bool LanaiDAGToDAGISel::selectAddrRi(SDValue Addr
, SDValue
&Base
,
208 SDValue
&Offset
, SDValue
&AluOp
) {
209 return selectAddrRiSpls(Addr
, Base
, Offset
, AluOp
, /*RiMode=*/true);
212 bool LanaiDAGToDAGISel::selectAddrSpls(SDValue Addr
, SDValue
&Base
,
213 SDValue
&Offset
, SDValue
&AluOp
) {
214 return selectAddrRiSpls(Addr
, Base
, Offset
, AluOp
, /*RiMode=*/false);
219 static AluCode
isdToLanaiAluCode(ISD::NodeType Node_type
) {
224 return AluCode::ADDC
;
228 return AluCode::SUBB
;
242 return AluCode::UNKNOWN
;
248 bool LanaiDAGToDAGISel::selectAddrRr(SDValue Addr
, SDValue
&R1
, SDValue
&R2
,
250 // if Address is FI, get the TargetFrameIndex.
251 if (Addr
.getOpcode() == ISD::FrameIndex
)
255 if ((Addr
.getOpcode() == ISD::TargetExternalSymbol
||
256 Addr
.getOpcode() == ISD::TargetGlobalAddress
))
259 // Address of the form OP + OP
260 ISD::NodeType AluOperator
= static_cast<ISD::NodeType
>(Addr
.getOpcode());
261 LPAC::AluCode AluCode
= LPAC::isdToLanaiAluCode(AluOperator
);
262 if (AluCode
!= LPAC::UNKNOWN
) {
263 // Skip addresses of the form FI OP const
264 if (ConstantSDNode
*CN
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1)))
265 if (isInt
<16>(CN
->getSExtValue()))
268 // Skip addresses with hi/lo operands
269 if (Addr
.getOperand(0).getOpcode() == LanaiISD::HI
||
270 Addr
.getOperand(0).getOpcode() == LanaiISD::LO
||
271 Addr
.getOperand(0).getOpcode() == LanaiISD::SMALL
||
272 Addr
.getOperand(1).getOpcode() == LanaiISD::HI
||
273 Addr
.getOperand(1).getOpcode() == LanaiISD::LO
||
274 Addr
.getOperand(1).getOpcode() == LanaiISD::SMALL
)
277 // Addresses of the form register OP register
278 R1
= Addr
.getOperand(0);
279 R2
= Addr
.getOperand(1);
280 AluOp
= CurDAG
->getTargetConstant(AluCode
, SDLoc(Addr
), MVT::i32
);
284 // Skip addresses with zero offset
288 bool LanaiDAGToDAGISel::SelectInlineAsmMemoryOperand(
289 const SDValue
&Op
, InlineAsm::ConstraintCode ConstraintCode
,
290 std::vector
<SDValue
> &OutOps
) {
291 SDValue Op0
, Op1
, AluOp
;
292 switch (ConstraintCode
) {
295 case InlineAsm::ConstraintCode::m
: // memory
296 if (!selectAddrRr(Op
, Op0
, Op1
, AluOp
) &&
297 !selectAddrRi(Op
, Op0
, Op1
, AluOp
))
302 OutOps
.push_back(Op0
);
303 OutOps
.push_back(Op1
);
304 OutOps
.push_back(AluOp
);
308 // Select instructions not customized! Used for
309 // expanded, promoted and normal instructions
310 void LanaiDAGToDAGISel::Select(SDNode
*Node
) {
311 unsigned Opcode
= Node
->getOpcode();
313 // If we have a custom node, we already have selected!
314 if (Node
->isMachineOpcode()) {
315 LLVM_DEBUG(errs() << "== "; Node
->dump(CurDAG
); errs() << "\n");
319 // Instruction Selection not handled by the auto-generated tablegen selection
320 // should be handled here.
321 EVT VT
= Node
->getValueType(0);
324 if (VT
== MVT::i32
) {
325 ConstantSDNode
*ConstNode
= cast
<ConstantSDNode
>(Node
);
326 // Materialize zero constants as copies from R0. This allows the coalescer
327 // to propagate these into other instructions.
328 if (ConstNode
->isZero()) {
329 SDValue New
= CurDAG
->getCopyFromReg(CurDAG
->getEntryNode(),
330 SDLoc(Node
), Lanai::R0
, MVT::i32
);
331 return ReplaceNode(Node
, New
.getNode());
333 // Materialize all ones constants as copies from R1. This allows the
334 // coalescer to propagate these into other instructions.
335 if (ConstNode
->isAllOnes()) {
336 SDValue New
= CurDAG
->getCopyFromReg(CurDAG
->getEntryNode(),
337 SDLoc(Node
), Lanai::R1
, MVT::i32
);
338 return ReplaceNode(Node
, New
.getNode());
342 case ISD::FrameIndex
:
343 selectFrameIndex(Node
);
349 // Select the default instruction
353 void LanaiDAGToDAGISel::selectFrameIndex(SDNode
*Node
) {
355 SDValue Imm
= CurDAG
->getTargetConstant(0, DL
, MVT::i32
);
356 int FI
= cast
<FrameIndexSDNode
>(Node
)->getIndex();
357 EVT VT
= Node
->getValueType(0);
358 SDValue TFI
= CurDAG
->getTargetFrameIndex(FI
, VT
);
359 unsigned Opc
= Lanai::ADD_I_LO
;
360 if (Node
->hasOneUse()) {
361 CurDAG
->SelectNodeTo(Node
, Opc
, VT
, TFI
, Imm
);
364 ReplaceNode(Node
, CurDAG
->getMachineNode(Opc
, DL
, VT
, TFI
, Imm
));
367 // createLanaiISelDag - This pass converts a legalized DAG into a
368 // Lanai-specific DAG, ready for instruction scheduling.
369 FunctionPass
*llvm::createLanaiISelDag(LanaiTargetMachine
&TM
) {
370 return new LanaiDAGToDAGISelLegacy(TM
);