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"
38 //===----------------------------------------------------------------------===//
39 // Instruction Selector Implementation
40 //===----------------------------------------------------------------------===//
42 //===----------------------------------------------------------------------===//
43 // LanaiDAGToDAGISel - Lanai specific code to select Lanai machine
44 // instructions for SelectionDAG operations.
45 //===----------------------------------------------------------------------===//
48 class LanaiDAGToDAGISel
: public SelectionDAGISel
{
50 explicit LanaiDAGToDAGISel(LanaiTargetMachine
&TargetMachine
)
51 : SelectionDAGISel(TargetMachine
) {}
53 bool runOnMachineFunction(MachineFunction
&MF
) override
{
54 return SelectionDAGISel::runOnMachineFunction(MF
);
58 StringRef
getPassName() const override
{
59 return "Lanai DAG->DAG Pattern Instruction Selection";
62 bool SelectInlineAsmMemoryOperand(const SDValue
&Op
, unsigned ConstraintCode
,
63 std::vector
<SDValue
> &OutOps
) override
;
66 // Include the pieces autogenerated from the target description.
67 #include "LanaiGenDAGISel.inc"
69 // Instruction Selection not handled by the auto-generated tablgen
70 void Select(SDNode
*N
) override
;
72 // Support functions for the opcodes of Instruction Selection
73 // not handled by the auto-generated tablgen
74 void selectFrameIndex(SDNode
*N
);
76 // Complex Pattern for address selection.
77 bool selectAddrRi(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
,
79 bool selectAddrRr(SDValue Addr
, SDValue
&R1
, SDValue
&R2
, SDValue
&AluOp
);
80 bool selectAddrSls(SDValue Addr
, SDValue
&Offset
);
81 bool selectAddrSpls(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
,
84 // getI32Imm - Return a target constant with the specified value, of type i32.
85 inline SDValue
getI32Imm(unsigned Imm
, const SDLoc
&DL
) {
86 return CurDAG
->getTargetConstant(Imm
, DL
, MVT::i32
);
90 bool selectAddrRiSpls(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
,
91 SDValue
&AluOp
, bool RiMode
);
94 bool canBeRepresentedAsSls(const ConstantSDNode
&CN
) {
95 // Fits in 21-bit signed immediate and two low-order bits are zero.
96 return isInt
<21>(CN
.getSExtValue()) && ((CN
.getSExtValue() & 0x3) == 0);
101 // Helper functions for ComplexPattern used on LanaiInstrInfo
102 // Used on Lanai Load/Store instructions.
103 bool LanaiDAGToDAGISel::selectAddrSls(SDValue Addr
, SDValue
&Offset
) {
104 if (ConstantSDNode
*CN
= dyn_cast
<ConstantSDNode
>(Addr
)) {
106 // Loading from a constant address.
107 if (canBeRepresentedAsSls(*CN
)) {
108 int32_t Imm
= CN
->getSExtValue();
109 Offset
= CurDAG
->getTargetConstant(Imm
, DL
, CN
->getValueType(0));
113 if (Addr
.getOpcode() == ISD::OR
&&
114 Addr
.getOperand(1).getOpcode() == LanaiISD::SMALL
) {
115 Offset
= Addr
.getOperand(1).getOperand(0);
121 bool LanaiDAGToDAGISel::selectAddrRiSpls(SDValue Addr
, SDValue
&Base
,
122 SDValue
&Offset
, SDValue
&AluOp
,
126 if (ConstantSDNode
*CN
= dyn_cast
<ConstantSDNode
>(Addr
)) {
128 // Fits in 16-bit signed immediate.
129 if (isInt
<16>(CN
->getSExtValue())) {
130 int16_t Imm
= CN
->getSExtValue();
131 Offset
= CurDAG
->getTargetConstant(Imm
, DL
, CN
->getValueType(0));
132 Base
= CurDAG
->getRegister(Lanai::R0
, CN
->getValueType(0));
133 AluOp
= CurDAG
->getTargetConstant(LPAC::ADD
, DL
, MVT::i32
);
136 // Allow SLS to match if the constant doesn't fit in 16 bits but can be
137 // represented as an SLS.
138 if (canBeRepresentedAsSls(*CN
))
141 // Fits in 10-bit signed immediate.
142 if (isInt
<10>(CN
->getSExtValue())) {
143 int16_t Imm
= CN
->getSExtValue();
144 Offset
= CurDAG
->getTargetConstant(Imm
, DL
, CN
->getValueType(0));
145 Base
= CurDAG
->getRegister(Lanai::R0
, CN
->getValueType(0));
146 AluOp
= CurDAG
->getTargetConstant(LPAC::ADD
, DL
, MVT::i32
);
152 // if Address is FI, get the TargetFrameIndex.
153 if (FrameIndexSDNode
*FIN
= dyn_cast
<FrameIndexSDNode
>(Addr
)) {
154 Base
= CurDAG
->getTargetFrameIndex(
156 getTargetLowering()->getPointerTy(CurDAG
->getDataLayout()));
157 Offset
= CurDAG
->getTargetConstant(0, DL
, MVT::i32
);
158 AluOp
= CurDAG
->getTargetConstant(LPAC::ADD
, DL
, MVT::i32
);
163 if ((Addr
.getOpcode() == ISD::TargetExternalSymbol
||
164 Addr
.getOpcode() == ISD::TargetGlobalAddress
))
167 // Address of the form imm + reg
168 ISD::NodeType AluOperator
= static_cast<ISD::NodeType
>(Addr
.getOpcode());
169 if (AluOperator
== ISD::ADD
) {
170 AluOp
= CurDAG
->getTargetConstant(LPAC::ADD
, DL
, MVT::i32
);
171 // Addresses of the form FI+const
172 if (ConstantSDNode
*CN
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1)))
173 if ((RiMode
&& isInt
<16>(CN
->getSExtValue())) ||
174 (!RiMode
&& isInt
<10>(CN
->getSExtValue()))) {
175 // If the first operand is a FI, get the TargetFI Node
176 if (FrameIndexSDNode
*FIN
=
177 dyn_cast
<FrameIndexSDNode
>(Addr
.getOperand(0))) {
178 Base
= CurDAG
->getTargetFrameIndex(
180 getTargetLowering()->getPointerTy(CurDAG
->getDataLayout()));
182 Base
= Addr
.getOperand(0);
185 Offset
= CurDAG
->getTargetConstant(CN
->getSExtValue(), DL
, MVT::i32
);
190 // Let SLS match SMALL instead of RI.
191 if (AluOperator
== ISD::OR
&& RiMode
&&
192 Addr
.getOperand(1).getOpcode() == LanaiISD::SMALL
)
196 Offset
= CurDAG
->getTargetConstant(0, DL
, MVT::i32
);
197 AluOp
= CurDAG
->getTargetConstant(LPAC::ADD
, DL
, MVT::i32
);
201 bool LanaiDAGToDAGISel::selectAddrRi(SDValue Addr
, SDValue
&Base
,
202 SDValue
&Offset
, SDValue
&AluOp
) {
203 return selectAddrRiSpls(Addr
, Base
, Offset
, AluOp
, /*RiMode=*/true);
206 bool LanaiDAGToDAGISel::selectAddrSpls(SDValue Addr
, SDValue
&Base
,
207 SDValue
&Offset
, SDValue
&AluOp
) {
208 return selectAddrRiSpls(Addr
, Base
, Offset
, AluOp
, /*RiMode=*/false);
211 bool LanaiDAGToDAGISel::selectAddrRr(SDValue Addr
, SDValue
&R1
, SDValue
&R2
,
213 // if Address is FI, get the TargetFrameIndex.
214 if (Addr
.getOpcode() == ISD::FrameIndex
)
218 if ((Addr
.getOpcode() == ISD::TargetExternalSymbol
||
219 Addr
.getOpcode() == ISD::TargetGlobalAddress
))
222 // Address of the form OP + OP
223 ISD::NodeType AluOperator
= static_cast<ISD::NodeType
>(Addr
.getOpcode());
224 LPAC::AluCode AluCode
= LPAC::isdToLanaiAluCode(AluOperator
);
225 if (AluCode
!= LPAC::UNKNOWN
) {
226 // Skip addresses of the form FI OP const
227 if (ConstantSDNode
*CN
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1)))
228 if (isInt
<16>(CN
->getSExtValue()))
231 // Skip addresses with hi/lo operands
232 if (Addr
.getOperand(0).getOpcode() == LanaiISD::HI
||
233 Addr
.getOperand(0).getOpcode() == LanaiISD::LO
||
234 Addr
.getOperand(0).getOpcode() == LanaiISD::SMALL
||
235 Addr
.getOperand(1).getOpcode() == LanaiISD::HI
||
236 Addr
.getOperand(1).getOpcode() == LanaiISD::LO
||
237 Addr
.getOperand(1).getOpcode() == LanaiISD::SMALL
)
240 // Addresses of the form register OP register
241 R1
= Addr
.getOperand(0);
242 R2
= Addr
.getOperand(1);
243 AluOp
= CurDAG
->getTargetConstant(AluCode
, SDLoc(Addr
), MVT::i32
);
247 // Skip addresses with zero offset
251 bool LanaiDAGToDAGISel::SelectInlineAsmMemoryOperand(
252 const SDValue
&Op
, unsigned ConstraintCode
, std::vector
<SDValue
> &OutOps
) {
253 SDValue Op0
, Op1
, AluOp
;
254 switch (ConstraintCode
) {
257 case InlineAsm::Constraint_m
: // memory
258 if (!selectAddrRr(Op
, Op0
, Op1
, AluOp
) &&
259 !selectAddrRi(Op
, Op0
, Op1
, AluOp
))
264 OutOps
.push_back(Op0
);
265 OutOps
.push_back(Op1
);
266 OutOps
.push_back(AluOp
);
270 // Select instructions not customized! Used for
271 // expanded, promoted and normal instructions
272 void LanaiDAGToDAGISel::Select(SDNode
*Node
) {
273 unsigned Opcode
= Node
->getOpcode();
275 // If we have a custom node, we already have selected!
276 if (Node
->isMachineOpcode()) {
277 LLVM_DEBUG(errs() << "== "; Node
->dump(CurDAG
); errs() << "\n");
281 // Instruction Selection not handled by the auto-generated tablegen selection
282 // should be handled here.
283 EVT VT
= Node
->getValueType(0);
286 if (VT
== MVT::i32
) {
287 ConstantSDNode
*ConstNode
= cast
<ConstantSDNode
>(Node
);
288 // Materialize zero constants as copies from R0. This allows the coalescer
289 // to propagate these into other instructions.
290 if (ConstNode
->isNullValue()) {
291 SDValue New
= CurDAG
->getCopyFromReg(CurDAG
->getEntryNode(),
292 SDLoc(Node
), Lanai::R0
, MVT::i32
);
293 return ReplaceNode(Node
, New
.getNode());
295 // Materialize all ones constants as copies from R1. This allows the
296 // coalescer to propagate these into other instructions.
297 if (ConstNode
->isAllOnesValue()) {
298 SDValue New
= CurDAG
->getCopyFromReg(CurDAG
->getEntryNode(),
299 SDLoc(Node
), Lanai::R1
, MVT::i32
);
300 return ReplaceNode(Node
, New
.getNode());
304 case ISD::FrameIndex
:
305 selectFrameIndex(Node
);
311 // Select the default instruction
315 void LanaiDAGToDAGISel::selectFrameIndex(SDNode
*Node
) {
317 SDValue Imm
= CurDAG
->getTargetConstant(0, DL
, MVT::i32
);
318 int FI
= cast
<FrameIndexSDNode
>(Node
)->getIndex();
319 EVT VT
= Node
->getValueType(0);
320 SDValue TFI
= CurDAG
->getTargetFrameIndex(FI
, VT
);
321 unsigned Opc
= Lanai::ADD_I_LO
;
322 if (Node
->hasOneUse()) {
323 CurDAG
->SelectNodeTo(Node
, Opc
, VT
, TFI
, Imm
);
326 ReplaceNode(Node
, CurDAG
->getMachineNode(Opc
, DL
, VT
, TFI
, Imm
));
329 // createLanaiISelDag - This pass converts a legalized DAG into a
330 // Lanai-specific DAG, ready for instruction scheduling.
331 FunctionPass
*llvm::createLanaiISelDag(LanaiTargetMachine
&TM
) {
332 return new LanaiDAGToDAGISel(TM
);