LLVM 20.0.0git
LoongArchISelDAGToDAG.cpp
Go to the documentation of this file.
1//=- LoongArchISelDAGToDAG.cpp - A dag to dag inst selector for LoongArch -===//
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 LoongArch target.
10//
11//===----------------------------------------------------------------------===//
12
19
20using namespace llvm;
21
22#define DEBUG_TYPE "loongarch-isel"
23#define PASS_NAME "LoongArch DAG->DAG Pattern Instruction Selection"
24
26
29 : SelectionDAGISelLegacy(ID, std::make_unique<LoongArchDAGToDAGISel>(TM)) {}
30
32 false)
33
35 // If we have a custom node, we have already selected.
36 if (Node->isMachineOpcode()) {
37 LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n");
38 Node->setNodeId(-1);
39 return;
40 }
41
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();
46 SDLoc DL(Node);
47 MVT VT = Node->getSimpleValueType(0);
48
49 switch (Opcode) {
50 default:
51 break;
52 case ISD::Constant: {
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());
58 return;
59 }
60 SDNode *Result = nullptr;
61 SDValue SrcReg = CurDAG->getRegister(LoongArch::R0, GRLenVT);
62 // The instructions in the sequence are handled here.
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);
67 else
68 Result = CurDAG->getMachineNode(Inst.Opc, DL, GRLenVT, SrcReg, SDImm);
69 SrcReg = SDValue(Result, 0);
70 }
71
72 ReplaceNode(Node, Result);
73 return;
74 }
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);
79 unsigned ADDIOp =
80 Subtarget->is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
81 ReplaceNode(Node, CurDAG->getMachineNode(ADDIOp, DL, VT, TFI, Imm));
82 return;
83 }
84 case ISD::BITCAST: {
85 if (VT.is128BitVector() || VT.is256BitVector()) {
86 ReplaceUses(SDValue(Node, 0), Node->getOperand(0));
87 CurDAG->RemoveDeadNode(Node);
88 return;
89 }
90 break;
91 }
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;
98 bool HasAnyUndefs;
99 unsigned Op;
100 EVT ViaVecTy;
101 bool Is128Vec = BVN->getValueType(0).is128BitVector();
102 bool Is256Vec = BVN->getValueType(0).is256BitVector();
103
104 if (!Subtarget->hasExtLSX() || (!Is128Vec && !Is256Vec))
105 break;
106 if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
107 HasAnyUndefs, 8))
108 break;
109
110 switch (SplatBitSize) {
111 default:
112 break;
113 case 8:
114 Op = Is256Vec ? LoongArch::PseudoXVREPLI_B : LoongArch::PseudoVREPLI_B;
115 ViaVecTy = Is256Vec ? MVT::v32i8 : MVT::v16i8;
116 break;
117 case 16:
118 Op = Is256Vec ? LoongArch::PseudoXVREPLI_H : LoongArch::PseudoVREPLI_H;
119 ViaVecTy = Is256Vec ? MVT::v16i16 : MVT::v8i16;
120 break;
121 case 32:
122 Op = Is256Vec ? LoongArch::PseudoXVREPLI_W : LoongArch::PseudoVREPLI_W;
123 ViaVecTy = Is256Vec ? MVT::v8i32 : MVT::v4i32;
124 break;
125 case 64:
126 Op = Is256Vec ? LoongArch::PseudoXVREPLI_D : LoongArch::PseudoVREPLI_D;
127 ViaVecTy = Is256Vec ? MVT::v4i64 : MVT::v2i64;
128 break;
129 }
130
131 SDNode *Res;
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);
138 return;
139 }
140 break;
141 }
142 }
143
144 // Select the default instruction.
145 SelectCode(Node);
146}
147
149 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
150 std::vector<SDValue> &OutOps) {
151 SDValue Base = Op;
153 CurDAG->getTargetConstant(0, SDLoc(Op), Subtarget->getGRLenVT());
154 switch (ConstraintID) {
155 default:
156 llvm_unreachable("unexpected asm memory constraint");
157 // Reg+Reg addressing.
159 Base = Op.getOperand(0);
160 Offset = Op.getOperand(1);
161 break;
162 // Reg+simm12 addressing.
165 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op.getOperand(1));
166 if (isIntN(12, CN->getSExtValue())) {
167 Base = Op.getOperand(0);
169 Op.getValueType());
170 }
171 }
172 break;
173 // Reg+0 addressing.
175 break;
176 // Reg+(simm14<<2) addressing.
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);
184 Op.getValueType());
185 }
186 }
187 break;
188 }
189 OutOps.push_back(Base);
190 OutOps.push_back(Offset);
191 return false;
192}
193
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))
198 Base =
199 CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getGRLenVT());
200 else
201 Base = Addr;
202 return true;
203}
204
205// Fold constant addresses.
207 SDValue &Offset) {
208 SDLoc DL(Addr);
209 MVT VT = Addr.getSimpleValueType();
210
211 if (!isa<ConstantSDNode>(Addr))
212 return false;
213
214 // If the constant is a simm12, we can fold the whole constant and use R0 as
215 // the base.
216 int64_t CVal = cast<ConstantSDNode>(Addr)->getSExtValue();
217 if (!isInt<12>(CVal))
218 return false;
219 Base = CurDAG->getRegister(LoongArch::R0, VT);
220 Offset = CurDAG->getTargetConstant(SignExtend64<12>(CVal), DL, VT);
221 return true;
222}
223
225 // If this is FrameIndex, don't select it.
226 if (isa<FrameIndexSDNode>(Addr))
227 return false;
228 Base = Addr;
229 return true;
230}
231
233 SDValue &ShAmt) {
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);
239
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);
244
245 if (ShMask.isSubsetOf(AndMask)) {
246 ShAmt = N.getOperand(0);
247 return true;
248 }
249
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);
255 return true;
256 }
257 } else if (N.getOpcode() == LoongArchISD::BSTRPICK) {
258 // Similar to the above AND, if there is a BSTRPICK on the shift amount, we
259 // can bypass it.
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);
266 return true;
267 }
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) {
274 SDLoc DL(N);
275 EVT VT = N.getValueType();
276 SDValue Zero =
277 CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, LoongArch::R0, VT);
278 unsigned NegOpc = VT == MVT::i64 ? LoongArch::SUB_D : LoongArch::SUB_W;
279 MachineSDNode *Neg =
280 CurDAG->getMachineNode(NegOpc, DL, VT, Zero, N.getOperand(1));
281 ShAmt = SDValue(Neg, 0);
282 return true;
283 }
284 }
285
286 ShAmt = N;
287 return true;
288}
289
291 if (N.getOpcode() == ISD::SIGN_EXTEND_INREG &&
292 cast<VTSDNode>(N.getOperand(1))->getVT() == MVT::i32) {
293 Val = N.getOperand(0);
294 return true;
295 }
296 if (N.getOpcode() == LoongArchISD::BSTRPICK &&
297 N.getConstantOperandVal(1) < UINT64_C(0X1F) &&
298 N.getConstantOperandVal(2) == UINT64_C(0)) {
299 Val = N;
300 return true;
301 }
302 MVT VT = N.getSimpleValueType();
303 if (CurDAG->ComputeNumSignBits(N) > (VT.getSizeInBits() - 32)) {
304 Val = N;
305 return true;
306 }
307
308 return false;
309}
310
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);
316 return true;
317 }
318 }
319 MVT VT = N.getSimpleValueType();
321 if (CurDAG->MaskedValueIsZero(N, Mask)) {
322 Val = N;
323 return true;
324 }
325
326 return false;
327}
328
330 unsigned MinSizeInBits) const {
331 if (!Subtarget->hasExtLSX())
332 return false;
333
334 BuildVectorSDNode *Node = dyn_cast<BuildVectorSDNode>(N);
335
336 if (!Node)
337 return false;
338
339 APInt SplatValue, SplatUndef;
340 unsigned SplatBitSize;
341 bool HasAnyUndefs;
342
343 if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
344 MinSizeInBits, /*IsBigEndian=*/false))
345 return false;
346
347 Imm = SplatValue;
348
349 return true;
350}
351
352template <unsigned ImmBitSize, bool IsSigned>
354 APInt ImmValue;
355 EVT EltTy = N->getValueType(0).getVectorElementType();
356
357 if (N->getOpcode() == ISD::BITCAST)
358 N = N->getOperand(0);
359
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());
365 return true;
366 }
367 if (!IsSigned && ImmValue.isIntN(ImmBitSize)) {
368 SplatVal = CurDAG->getTargetConstant(ImmValue.getZExtValue(), SDLoc(N),
369 Subtarget->getGRLenVT());
370 return true;
371 }
372 }
373
374 return false;
375}
376
378 SDValue &SplatImm) const {
379 APInt ImmValue;
380 EVT EltTy = N->getValueType(0).getVectorElementType();
381
382 if (N->getOpcode() == ISD::BITCAST)
383 N = N->getOperand(0);
384
385 if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) &&
386 ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
387 int32_t Log2 = (~ImmValue).exactLogBase2();
388
389 if (Log2 != -1) {
390 SplatImm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy);
391 return true;
392 }
393 }
394
395 return false;
396}
397
399 SDValue &SplatImm) const {
400 APInt ImmValue;
401 EVT EltTy = N->getValueType(0).getVectorElementType();
402
403 if (N->getOpcode() == ISD::BITCAST)
404 N = N->getOperand(0);
405
406 if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) &&
407 ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
408 int32_t Log2 = ImmValue.exactLogBase2();
409
410 if (Log2 != -1) {
411 SplatImm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy);
412 return true;
413 }
414 }
415
416 return false;
417}
418
419// This pass converts a legalized DAG into a LoongArch-specific DAG, ready
420// for instruction scheduling.
422 return new LoongArchDAGToDAGISelLegacy(TM);
423}
amdgpu AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define LLVM_DEBUG(X)
Definition: Debug.h:101
uint64_t Addr
#define DEBUG_TYPE
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
#define PASS_NAME
DEMANGLE_DUMP_METHOD void dump() const
Class for arbitrary precision integers.
Definition: APInt.h:78
uint64_t getZExtValue() const
Get zero extended value.
Definition: APInt.h:1498
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition: APInt.h:1446
int32_t exactLogBase2() const
Definition: APInt.h:1739
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
Definition: APInt.h:413
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
Definition: APInt.h:1235
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
Definition: APInt.h:274
bool isIntN(unsigned N) const
Check if this APInt has an N-bits unsigned integer value.
Definition: APInt.h:410
int64_t getSExtValue() const
Get sign extended value.
Definition: APInt.h:1520
A "pseudo-class" with methods for operating on BUILD_VECTORs.
bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, unsigned &SplatBitSize, bool &HasAnyUndefs, unsigned MinSplatBits=0, bool isBigEndian=false) const
Check if this is a constant splat, and if so, find the smallest element size that splats the vector.
uint64_t getZExtValue() const
int64_t getSExtValue() const
This class represents an Operation in the Expression.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
LoongArchDAGToDAGISelLegacy(LoongArchTargetMachine &TM)
bool selectNonFIBaseAddr(SDValue Addr, SDValue &Base)
bool selectSExti32(SDValue N, SDValue &Val)
bool SelectInlineAsmMemoryOperand(const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, std::vector< SDValue > &OutOps) override
SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode,...
bool selectVSplatUimmPow2(SDValue N, SDValue &SplatImm) const
bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt)
bool selectZExti32(SDValue N, SDValue &Val)
bool SelectAddrConstant(SDValue Addr, SDValue &Base, SDValue &Offset)
bool selectVSplat(SDNode *N, APInt &Imm, unsigned MinSizeInBits) const
bool selectVSplatImm(SDValue N, SDValue &SplatVal)
bool selectVSplatUimmInvPow2(SDValue N, SDValue &SplatImm) const
bool SelectBaseAddr(SDValue Addr, SDValue &Base)
Machine Value Type.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool is256BitVector() const
Return true if this is a 256-bit vector type.
An SDNode that represents everything that will be needed to construct a MachineInstr.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
SDValue getTargetFrameIndex(int FI, EVT VT)
Definition: SelectionDAG.h:741
SDValue getRegister(unsigned Reg, EVT VT)
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
Definition: SelectionDAG.h:690
unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
bool isBaseWithConstantOffset(SDValue Op) const
Return true if the specified operand is an ISD::ADD with a ConstantSDNode on the right-hand side,...
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT)
Definition: SelectionDAG.h:813
KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
Definition: SelectionDAG.h:570
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
Definition: ISDOpcodes.h:953
@ FrameIndex
Definition: ISDOpcodes.h:80
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition: ISDOpcodes.h:848
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:708
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition: ISDOpcodes.h:529
InstSeq generateInstSeq(int64_t Val)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
Definition: Alignment.h:145
FunctionPass * createLoongArchISelDag(LoongArchTargetMachine &TM)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition: MathExtras.h:340
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition: MathExtras.h:291
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:260
DWARFExpression::Operation Op
unsigned Log2(Align A)
Returns the log2 of the alignment.
Definition: Alignment.h:208
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
Extended Value Type.
Definition: ValueTypes.h:35
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition: ValueTypes.h:359
bool is128BitVector() const
Return true if this is a 128-bit vector type.
Definition: ValueTypes.h:204
bool is256BitVector() const
Return true if this is a 256-bit vector type.
Definition: ValueTypes.h:209
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition: ValueTypes.h:319