1 //=- LoongArchISelDAGToDAG.cpp - A dag to dag inst selector for LoongArch -===//
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 LoongArch target.
11 //===----------------------------------------------------------------------===//
13 #include "LoongArchISelDAGToDAG.h"
14 #include "LoongArchISelLowering.h"
15 #include "MCTargetDesc/LoongArchMCTargetDesc.h"
16 #include "MCTargetDesc/LoongArchMatInt.h"
17 #include "llvm/Support/KnownBits.h"
18 #include "llvm/Support/raw_ostream.h"
22 #define DEBUG_TYPE "loongarch-isel"
23 #define PASS_NAME "LoongArch DAG->DAG Pattern Instruction Selection"
25 char LoongArchDAGToDAGISelLegacy::ID
;
27 LoongArchDAGToDAGISelLegacy::LoongArchDAGToDAGISelLegacy(
28 LoongArchTargetMachine
&TM
)
29 : SelectionDAGISelLegacy(ID
, std::make_unique
<LoongArchDAGToDAGISel
>(TM
)) {}
31 INITIALIZE_PASS(LoongArchDAGToDAGISelLegacy
, DEBUG_TYPE
, PASS_NAME
, false,
34 void LoongArchDAGToDAGISel::Select(SDNode
*Node
) {
35 // If we have a custom node, we have already selected.
36 if (Node
->isMachineOpcode()) {
37 LLVM_DEBUG(dbgs() << "== "; Node
->dump(CurDAG
); dbgs() << "\n");
42 // Instruction Selection not handled by the auto-generated tablegen selection
43 // should be handled here.
44 unsigned Opcode
= Node
->getOpcode();
45 MVT GRLenVT
= Subtarget
->getGRLenVT();
47 MVT VT
= Node
->getSimpleValueType(0);
53 int64_t Imm
= cast
<ConstantSDNode
>(Node
)->getSExtValue();
54 if (Imm
== 0 && VT
== GRLenVT
) {
55 SDValue New
= CurDAG
->getCopyFromReg(CurDAG
->getEntryNode(), DL
,
56 LoongArch::R0
, GRLenVT
);
57 ReplaceNode(Node
, New
.getNode());
60 SDNode
*Result
= nullptr;
61 SDValue SrcReg
= CurDAG
->getRegister(LoongArch::R0
, GRLenVT
);
62 // The instructions in the sequence are handled here.
63 for (LoongArchMatInt::Inst
&Inst
: LoongArchMatInt::generateInstSeq(Imm
)) {
64 SDValue SDImm
= CurDAG
->getTargetConstant(Inst
.Imm
, DL
, GRLenVT
);
65 if (Inst
.Opc
== LoongArch::LU12I_W
)
66 Result
= CurDAG
->getMachineNode(LoongArch::LU12I_W
, DL
, GRLenVT
, SDImm
);
68 Result
= CurDAG
->getMachineNode(Inst
.Opc
, DL
, GRLenVT
, SrcReg
, SDImm
);
69 SrcReg
= SDValue(Result
, 0);
72 ReplaceNode(Node
, Result
);
75 case ISD::FrameIndex
: {
76 SDValue Imm
= CurDAG
->getTargetConstant(0, DL
, GRLenVT
);
77 int FI
= cast
<FrameIndexSDNode
>(Node
)->getIndex();
78 SDValue TFI
= CurDAG
->getTargetFrameIndex(FI
, VT
);
80 Subtarget
->is64Bit() ? LoongArch::ADDI_D
: LoongArch::ADDI_W
;
81 ReplaceNode(Node
, CurDAG
->getMachineNode(ADDIOp
, DL
, VT
, TFI
, Imm
));
85 if (VT
.is128BitVector() || VT
.is256BitVector()) {
86 ReplaceUses(SDValue(Node
, 0), Node
->getOperand(0));
87 CurDAG
->RemoveDeadNode(Node
);
92 case ISD::BUILD_VECTOR
: {
93 // Select appropriate [x]vrepli.[bhwd] instructions for constant splats of
94 // 128/256-bit when LSX/LASX is enabled.
95 BuildVectorSDNode
*BVN
= cast
<BuildVectorSDNode
>(Node
);
96 APInt SplatValue
, SplatUndef
;
97 unsigned SplatBitSize
;
101 bool Is128Vec
= BVN
->getValueType(0).is128BitVector();
102 bool Is256Vec
= BVN
->getValueType(0).is256BitVector();
104 if (!Subtarget
->hasExtLSX() || (!Is128Vec
&& !Is256Vec
))
106 if (!BVN
->isConstantSplat(SplatValue
, SplatUndef
, SplatBitSize
,
110 switch (SplatBitSize
) {
114 Op
= Is256Vec
? LoongArch::PseudoXVREPLI_B
: LoongArch::PseudoVREPLI_B
;
115 ViaVecTy
= Is256Vec
? MVT::v32i8
: MVT::v16i8
;
118 Op
= Is256Vec
? LoongArch::PseudoXVREPLI_H
: LoongArch::PseudoVREPLI_H
;
119 ViaVecTy
= Is256Vec
? MVT::v16i16
: MVT::v8i16
;
122 Op
= Is256Vec
? LoongArch::PseudoXVREPLI_W
: LoongArch::PseudoVREPLI_W
;
123 ViaVecTy
= Is256Vec
? MVT::v8i32
: MVT::v4i32
;
126 Op
= Is256Vec
? LoongArch::PseudoXVREPLI_D
: LoongArch::PseudoVREPLI_D
;
127 ViaVecTy
= Is256Vec
? MVT::v4i64
: MVT::v2i64
;
132 // If we have a signed 10 bit integer, we can splat it directly.
133 if (SplatValue
.isSignedIntN(10)) {
134 SDValue Imm
= CurDAG
->getTargetConstant(SplatValue
, DL
,
135 ViaVecTy
.getVectorElementType());
136 Res
= CurDAG
->getMachineNode(Op
, DL
, ViaVecTy
, Imm
);
137 ReplaceNode(Node
, Res
);
144 // Select the default instruction.
148 bool LoongArchDAGToDAGISel::SelectInlineAsmMemoryOperand(
149 const SDValue
&Op
, InlineAsm::ConstraintCode ConstraintID
,
150 std::vector
<SDValue
> &OutOps
) {
153 CurDAG
->getTargetConstant(0, SDLoc(Op
), Subtarget
->getGRLenVT());
154 switch (ConstraintID
) {
156 llvm_unreachable("unexpected asm memory constraint");
157 // Reg+Reg addressing.
158 case InlineAsm::ConstraintCode::k
:
159 Base
= Op
.getOperand(0);
160 Offset
= Op
.getOperand(1);
162 // Reg+simm12 addressing.
163 case InlineAsm::ConstraintCode::m
:
164 if (CurDAG
->isBaseWithConstantOffset(Op
)) {
165 ConstantSDNode
*CN
= dyn_cast
<ConstantSDNode
>(Op
.getOperand(1));
166 if (isIntN(12, CN
->getSExtValue())) {
167 Base
= Op
.getOperand(0);
168 Offset
= CurDAG
->getTargetConstant(CN
->getZExtValue(), SDLoc(Op
),
174 case InlineAsm::ConstraintCode::ZB
:
176 // Reg+(simm14<<2) addressing.
177 case InlineAsm::ConstraintCode::ZC
:
178 if (CurDAG
->isBaseWithConstantOffset(Op
)) {
179 ConstantSDNode
*CN
= dyn_cast
<ConstantSDNode
>(Op
.getOperand(1));
180 if (isIntN(16, CN
->getSExtValue()) &&
181 isAligned(Align(4ULL), CN
->getZExtValue())) {
182 Base
= Op
.getOperand(0);
183 Offset
= CurDAG
->getTargetConstant(CN
->getZExtValue(), SDLoc(Op
),
189 OutOps
.push_back(Base
);
190 OutOps
.push_back(Offset
);
194 bool LoongArchDAGToDAGISel::SelectBaseAddr(SDValue Addr
, SDValue
&Base
) {
195 // If this is FrameIndex, select it directly. Otherwise just let it get
196 // selected to a register independently.
197 if (auto *FIN
= dyn_cast
<FrameIndexSDNode
>(Addr
))
199 CurDAG
->getTargetFrameIndex(FIN
->getIndex(), Subtarget
->getGRLenVT());
205 // Fold constant addresses.
206 bool LoongArchDAGToDAGISel::SelectAddrConstant(SDValue Addr
, SDValue
&Base
,
209 MVT VT
= Addr
.getSimpleValueType();
211 if (!isa
<ConstantSDNode
>(Addr
))
214 // If the constant is a simm12, we can fold the whole constant and use R0 as
216 int64_t CVal
= cast
<ConstantSDNode
>(Addr
)->getSExtValue();
217 if (!isInt
<12>(CVal
))
219 Base
= CurDAG
->getRegister(LoongArch::R0
, VT
);
220 Offset
= CurDAG
->getTargetConstant(SignExtend64
<12>(CVal
), DL
, VT
);
224 bool LoongArchDAGToDAGISel::selectNonFIBaseAddr(SDValue Addr
, SDValue
&Base
) {
225 // If this is FrameIndex, don't select it.
226 if (isa
<FrameIndexSDNode
>(Addr
))
232 bool LoongArchDAGToDAGISel::selectShiftMask(SDValue N
, unsigned ShiftWidth
,
234 // Shift instructions on LoongArch only read the lower 5 or 6 bits of the
235 // shift amount. If there is an AND on the shift amount, we can bypass it if
236 // it doesn't affect any of those bits.
237 if (N
.getOpcode() == ISD::AND
&& isa
<ConstantSDNode
>(N
.getOperand(1))) {
238 const APInt
&AndMask
= N
->getConstantOperandAPInt(1);
240 // Since the max shift amount is a power of 2 we can subtract 1 to make a
241 // mask that covers the bits needed to represent all shift amounts.
242 assert(isPowerOf2_32(ShiftWidth
) && "Unexpected max shift amount!");
243 APInt
ShMask(AndMask
.getBitWidth(), ShiftWidth
- 1);
245 if (ShMask
.isSubsetOf(AndMask
)) {
246 ShAmt
= N
.getOperand(0);
250 // SimplifyDemandedBits may have optimized the mask so try restoring any
251 // bits that are known zero.
252 KnownBits Known
= CurDAG
->computeKnownBits(N
->getOperand(0));
253 if (ShMask
.isSubsetOf(AndMask
| Known
.Zero
)) {
254 ShAmt
= N
.getOperand(0);
257 } else if (N
.getOpcode() == LoongArchISD::BSTRPICK
) {
258 // Similar to the above AND, if there is a BSTRPICK on the shift amount, we
260 assert(isPowerOf2_32(ShiftWidth
) && "Unexpected max shift amount!");
261 assert(isa
<ConstantSDNode
>(N
.getOperand(1)) && "Illegal msb operand!");
262 assert(isa
<ConstantSDNode
>(N
.getOperand(2)) && "Illegal lsb operand!");
263 uint64_t msb
= N
.getConstantOperandVal(1), lsb
= N
.getConstantOperandVal(2);
264 if (lsb
== 0 && Log2_32(ShiftWidth
) <= msb
+ 1) {
265 ShAmt
= N
.getOperand(0);
268 } else if (N
.getOpcode() == ISD::SUB
&&
269 isa
<ConstantSDNode
>(N
.getOperand(0))) {
270 uint64_t Imm
= N
.getConstantOperandVal(0);
271 // If we are shifting by N-X where N == 0 mod Size, then just shift by -X to
272 // generate a NEG instead of a SUB of a constant.
273 if (Imm
!= 0 && Imm
% ShiftWidth
== 0) {
275 EVT VT
= N
.getValueType();
277 CurDAG
->getCopyFromReg(CurDAG
->getEntryNode(), DL
, LoongArch::R0
, VT
);
278 unsigned NegOpc
= VT
== MVT::i64
? LoongArch::SUB_D
: LoongArch::SUB_W
;
280 CurDAG
->getMachineNode(NegOpc
, DL
, VT
, Zero
, N
.getOperand(1));
281 ShAmt
= SDValue(Neg
, 0);
290 bool LoongArchDAGToDAGISel::selectSExti32(SDValue N
, SDValue
&Val
) {
291 if (N
.getOpcode() == ISD::SIGN_EXTEND_INREG
&&
292 cast
<VTSDNode
>(N
.getOperand(1))->getVT() == MVT::i32
) {
293 Val
= N
.getOperand(0);
296 if (N
.getOpcode() == LoongArchISD::BSTRPICK
&&
297 N
.getConstantOperandVal(1) < UINT64_C(0X1F) &&
298 N
.getConstantOperandVal(2) == UINT64_C(0)) {
302 MVT VT
= N
.getSimpleValueType();
303 if (CurDAG
->ComputeNumSignBits(N
) > (VT
.getSizeInBits() - 32)) {
311 bool LoongArchDAGToDAGISel::selectZExti32(SDValue N
, SDValue
&Val
) {
312 if (N
.getOpcode() == ISD::AND
) {
313 auto *C
= dyn_cast
<ConstantSDNode
>(N
.getOperand(1));
314 if (C
&& C
->getZExtValue() == UINT64_C(0xFFFFFFFF)) {
315 Val
= N
.getOperand(0);
319 MVT VT
= N
.getSimpleValueType();
320 APInt Mask
= APInt::getHighBitsSet(VT
.getSizeInBits(), 32);
321 if (CurDAG
->MaskedValueIsZero(N
, Mask
)) {
329 bool LoongArchDAGToDAGISel::selectVSplat(SDNode
*N
, APInt
&Imm
,
330 unsigned MinSizeInBits
) const {
331 if (!Subtarget
->hasExtLSX())
334 BuildVectorSDNode
*Node
= dyn_cast
<BuildVectorSDNode
>(N
);
339 APInt SplatValue
, SplatUndef
;
340 unsigned SplatBitSize
;
343 if (!Node
->isConstantSplat(SplatValue
, SplatUndef
, SplatBitSize
, HasAnyUndefs
,
344 MinSizeInBits
, /*IsBigEndian=*/false))
352 template <unsigned ImmBitSize
, bool IsSigned
>
353 bool LoongArchDAGToDAGISel::selectVSplatImm(SDValue N
, SDValue
&SplatVal
) {
355 EVT EltTy
= N
->getValueType(0).getVectorElementType();
357 if (N
->getOpcode() == ISD::BITCAST
)
358 N
= N
->getOperand(0);
360 if (selectVSplat(N
.getNode(), ImmValue
, EltTy
.getSizeInBits()) &&
361 ImmValue
.getBitWidth() == EltTy
.getSizeInBits()) {
362 if (IsSigned
&& ImmValue
.isSignedIntN(ImmBitSize
)) {
363 SplatVal
= CurDAG
->getTargetConstant(ImmValue
.getSExtValue(), SDLoc(N
),
364 Subtarget
->getGRLenVT());
367 if (!IsSigned
&& ImmValue
.isIntN(ImmBitSize
)) {
368 SplatVal
= CurDAG
->getTargetConstant(ImmValue
.getZExtValue(), SDLoc(N
),
369 Subtarget
->getGRLenVT());
377 bool LoongArchDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N
,
378 SDValue
&SplatImm
) const {
380 EVT EltTy
= N
->getValueType(0).getVectorElementType();
382 if (N
->getOpcode() == ISD::BITCAST
)
383 N
= N
->getOperand(0);
385 if (selectVSplat(N
.getNode(), ImmValue
, EltTy
.getSizeInBits()) &&
386 ImmValue
.getBitWidth() == EltTy
.getSizeInBits()) {
387 int32_t Log2
= (~ImmValue
).exactLogBase2();
390 SplatImm
= CurDAG
->getTargetConstant(Log2
, SDLoc(N
), EltTy
);
398 bool LoongArchDAGToDAGISel::selectVSplatUimmPow2(SDValue N
,
399 SDValue
&SplatImm
) const {
401 EVT EltTy
= N
->getValueType(0).getVectorElementType();
403 if (N
->getOpcode() == ISD::BITCAST
)
404 N
= N
->getOperand(0);
406 if (selectVSplat(N
.getNode(), ImmValue
, EltTy
.getSizeInBits()) &&
407 ImmValue
.getBitWidth() == EltTy
.getSizeInBits()) {
408 int32_t Log2
= ImmValue
.exactLogBase2();
411 SplatImm
= CurDAG
->getTargetConstant(Log2
, SDLoc(N
), EltTy
);
419 // This pass converts a legalized DAG into a LoongArch-specific DAG, ready
420 // for instruction scheduling.
421 FunctionPass
*llvm::createLoongArchISelDag(LoongArchTargetMachine
&TM
) {
422 return new LoongArchDAGToDAGISelLegacy(TM
);