LLVM 22.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
31
33 false)
34
36 // If we have a custom node, we have already selected.
37 if (Node->isMachineOpcode()) {
38 LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n");
39 Node->setNodeId(-1);
40 return;
41 }
42
43 // Instruction Selection not handled by the auto-generated tablegen selection
44 // should be handled here.
45 unsigned Opcode = Node->getOpcode();
46 MVT GRLenVT = Subtarget->getGRLenVT();
47 SDLoc DL(Node);
48 MVT VT = Node->getSimpleValueType(0);
49
50 switch (Opcode) {
51 default:
52 break;
53 case ISD::Constant: {
54 int64_t Imm = cast<ConstantSDNode>(Node)->getSExtValue();
55 if (Imm == 0 && VT == GRLenVT) {
56 SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL,
57 LoongArch::R0, GRLenVT);
58 ReplaceNode(Node, New.getNode());
59 return;
60 }
61 SDNode *Result = nullptr;
62 SDValue SrcReg = CurDAG->getRegister(LoongArch::R0, GRLenVT);
63 // The instructions in the sequence are handled here.
65 SDValue SDImm = CurDAG->getSignedTargetConstant(Inst.Imm, DL, GRLenVT);
66 switch (Inst.Opc) {
67 case LoongArch::LU12I_W:
68 Result = CurDAG->getMachineNode(Inst.Opc, DL, GRLenVT, SDImm);
69 break;
70 case LoongArch::ADDI_W:
71 case LoongArch::ORI:
72 case LoongArch::LU32I_D:
73 case LoongArch::LU52I_D:
74 Result = CurDAG->getMachineNode(Inst.Opc, DL, GRLenVT, SrcReg, SDImm);
75 break;
76 case LoongArch::BSTRINS_D:
77 Result = CurDAG->getMachineNode(
78 Inst.Opc, DL, GRLenVT,
79 {SrcReg, SrcReg,
80 CurDAG->getSignedTargetConstant(Inst.Imm >> 32, DL, GRLenVT),
81 CurDAG->getTargetConstant(Inst.Imm & 0xFF, DL, GRLenVT)});
82 break;
83 default:
84 llvm_unreachable("unexpected opcode generated by LoongArchMatInt");
85 }
86 SrcReg = SDValue(Result, 0);
87 }
88
89 ReplaceNode(Node, Result);
90 return;
91 }
92 case ISD::FrameIndex: {
93 SDValue Imm = CurDAG->getTargetConstant(0, DL, GRLenVT);
94 int FI = cast<FrameIndexSDNode>(Node)->getIndex();
95 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
96 unsigned ADDIOp =
97 Subtarget->is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
98 ReplaceNode(Node, CurDAG->getMachineNode(ADDIOp, DL, VT, TFI, Imm));
99 return;
100 }
101 case ISD::BITCAST: {
102 if (VT.is128BitVector() || VT.is256BitVector()) {
103 ReplaceUses(SDValue(Node, 0), Node->getOperand(0));
104 CurDAG->RemoveDeadNode(Node);
105 return;
106 }
107 break;
108 }
109 case ISD::BUILD_VECTOR: {
110 // Select appropriate [x]vrepli.[bhwd] instructions for constant splats of
111 // 128/256-bit when LSX/LASX is enabled.
113 APInt SplatValue, SplatUndef;
114 unsigned SplatBitSize;
115 bool HasAnyUndefs;
116 unsigned Op;
117 EVT ResTy = BVN->getValueType(0);
118 bool Is128Vec = BVN->getValueType(0).is128BitVector();
119 bool Is256Vec = BVN->getValueType(0).is256BitVector();
120
121 if (!Subtarget->hasExtLSX() || (!Is128Vec && !Is256Vec))
122 break;
123 if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
124 HasAnyUndefs, 8))
125 break;
126
127 switch (SplatBitSize) {
128 default:
129 break;
130 case 8:
131 Op = Is256Vec ? LoongArch::PseudoXVREPLI_B : LoongArch::PseudoVREPLI_B;
132 break;
133 case 16:
134 Op = Is256Vec ? LoongArch::PseudoXVREPLI_H : LoongArch::PseudoVREPLI_H;
135 break;
136 case 32:
137 Op = Is256Vec ? LoongArch::PseudoXVREPLI_W : LoongArch::PseudoVREPLI_W;
138 break;
139 case 64:
140 Op = Is256Vec ? LoongArch::PseudoXVREPLI_D : LoongArch::PseudoVREPLI_D;
141 break;
142 }
143
144 SDNode *Res;
145 // If we have a signed 10 bit integer, we can splat it directly.
146 if (SplatValue.isSignedIntN(10)) {
147 EVT EleType = ResTy.getVectorElementType();
148 APInt Val = SplatValue.sextOrTrunc(EleType.getSizeInBits());
149 SDValue Imm = CurDAG->getTargetConstant(Val, DL, EleType);
150 Res = CurDAG->getMachineNode(Op, DL, ResTy, Imm);
151 ReplaceNode(Node, Res);
152 return;
153 }
154 break;
155 }
156 }
157
158 // Select the default instruction.
159 SelectCode(Node);
160}
161
163 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
164 std::vector<SDValue> &OutOps) {
165 SDValue Base = Op;
167 CurDAG->getTargetConstant(0, SDLoc(Op), Subtarget->getGRLenVT());
168 switch (ConstraintID) {
169 default:
170 llvm_unreachable("unexpected asm memory constraint");
171 // Reg+Reg addressing.
173 Base = Op.getOperand(0);
174 Offset = Op.getOperand(1);
175 break;
176 // Reg+simm12 addressing.
178 if (CurDAG->isBaseWithConstantOffset(Op)) {
179 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op.getOperand(1));
180 if (isIntN(12, CN->getSExtValue())) {
181 Base = Op.getOperand(0);
182 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Op),
183 Op.getValueType());
184 }
185 }
186 break;
187 // Reg+0 addressing.
189 break;
190 // Reg+(simm14<<2) addressing.
192 if (CurDAG->isBaseWithConstantOffset(Op)) {
193 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op.getOperand(1));
194 if (isIntN(16, CN->getSExtValue()) &&
195 isAligned(Align(4ULL), CN->getZExtValue())) {
196 Base = Op.getOperand(0);
197 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Op),
198 Op.getValueType());
199 }
200 }
201 break;
202 }
203 OutOps.push_back(Base);
204 OutOps.push_back(Offset);
205 return false;
206}
207
209 // If this is FrameIndex, select it directly. Otherwise just let it get
210 // selected to a register independently.
211 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Addr))
212 Base =
213 CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getGRLenVT());
214 else
215 Base = Addr;
216 return true;
217}
218
219// Fold constant addresses.
221 SDValue &Offset) {
222 SDLoc DL(Addr);
223 MVT VT = Addr.getSimpleValueType();
224
225 if (!isa<ConstantSDNode>(Addr))
226 return false;
227
228 // If the constant is a simm12, we can fold the whole constant and use R0 as
229 // the base.
230 int64_t CVal = cast<ConstantSDNode>(Addr)->getSExtValue();
231 if (!isInt<12>(CVal))
232 return false;
233 Base = CurDAG->getRegister(LoongArch::R0, VT);
234 Offset = CurDAG->getSignedTargetConstant(SignExtend64<12>(CVal), DL, VT);
235 return true;
236}
237
239 // If this is FrameIndex, don't select it.
240 if (isa<FrameIndexSDNode>(Addr))
241 return false;
242 Base = Addr;
243 return true;
244}
245
247 SDValue &Offset) {
248 SDLoc DL(Addr);
249 MVT VT = Addr.getSimpleValueType();
250
251 // The address is the result of an ADD. Here we only consider reg+simm12.
252 if (CurDAG->isBaseWithConstantOffset(Addr)) {
253 int64_t Imm = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
254 if (isInt<12>(Imm)) {
255 Base = Addr.getOperand(0);
256 Offset = CurDAG->getSignedTargetConstant(SignExtend64<12>(Imm), DL, VT);
257 return true;
258 }
259 }
260
261 // Otherwise, we assume Addr as the base address and use constant 0 as the
262 // offset.
263 Base = Addr;
264 Offset = CurDAG->getTargetConstant(0, DL, VT);
265 return true;
266}
267
269 SDValue &ShAmt) {
270 // Shift instructions on LoongArch only read the lower 5 or 6 bits of the
271 // shift amount. If there is an AND on the shift amount, we can bypass it if
272 // it doesn't affect any of those bits.
273 if (N.getOpcode() == ISD::AND && isa<ConstantSDNode>(N.getOperand(1))) {
274 const APInt &AndMask = N->getConstantOperandAPInt(1);
275
276 // Since the max shift amount is a power of 2 we can subtract 1 to make a
277 // mask that covers the bits needed to represent all shift amounts.
278 assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!");
279 APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1);
280
281 if (ShMask.isSubsetOf(AndMask)) {
282 ShAmt = N.getOperand(0);
283 return true;
284 }
285
286 // SimplifyDemandedBits may have optimized the mask so try restoring any
287 // bits that are known zero.
288 KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0));
289 if (ShMask.isSubsetOf(AndMask | Known.Zero)) {
290 ShAmt = N.getOperand(0);
291 return true;
292 }
293 } else if (N.getOpcode() == LoongArchISD::BSTRPICK) {
294 // Similar to the above AND, if there is a BSTRPICK on the shift amount, we
295 // can bypass it.
296 assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!");
297 assert(isa<ConstantSDNode>(N.getOperand(1)) && "Illegal msb operand!");
298 assert(isa<ConstantSDNode>(N.getOperand(2)) && "Illegal lsb operand!");
299 uint64_t msb = N.getConstantOperandVal(1), lsb = N.getConstantOperandVal(2);
300 if (lsb == 0 && Log2_32(ShiftWidth) <= msb + 1) {
301 ShAmt = N.getOperand(0);
302 return true;
303 }
304 } else if (N.getOpcode() == ISD::SUB &&
305 isa<ConstantSDNode>(N.getOperand(0))) {
306 uint64_t Imm = N.getConstantOperandVal(0);
307 // If we are shifting by N-X where N == 0 mod Size, then just shift by -X to
308 // generate a NEG instead of a SUB of a constant.
309 if (Imm != 0 && Imm % ShiftWidth == 0) {
310 SDLoc DL(N);
311 EVT VT = N.getValueType();
312 SDValue Zero =
313 CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, LoongArch::R0, VT);
314 unsigned NegOpc = VT == MVT::i64 ? LoongArch::SUB_D : LoongArch::SUB_W;
315 MachineSDNode *Neg =
316 CurDAG->getMachineNode(NegOpc, DL, VT, Zero, N.getOperand(1));
317 ShAmt = SDValue(Neg, 0);
318 return true;
319 }
320 }
321
322 ShAmt = N;
323 return true;
324}
325
327 if (N.getOpcode() == ISD::SIGN_EXTEND_INREG &&
328 cast<VTSDNode>(N.getOperand(1))->getVT() == MVT::i32) {
329 Val = N.getOperand(0);
330 return true;
331 }
332 if (N.getOpcode() == LoongArchISD::BSTRPICK &&
333 N.getConstantOperandVal(1) < UINT64_C(0X1F) &&
334 N.getConstantOperandVal(2) == UINT64_C(0)) {
335 Val = N;
336 return true;
337 }
338 MVT VT = N.getSimpleValueType();
339 if (CurDAG->ComputeNumSignBits(N) > (VT.getSizeInBits() - 32)) {
340 Val = N;
341 return true;
342 }
343
344 return false;
345}
346
348 if (N.getOpcode() == ISD::AND) {
349 auto *C = dyn_cast<ConstantSDNode>(N.getOperand(1));
350 if (C && C->getZExtValue() == UINT64_C(0xFFFFFFFF)) {
351 Val = N.getOperand(0);
352 return true;
353 }
354 }
355 MVT VT = N.getSimpleValueType();
357 if (CurDAG->MaskedValueIsZero(N, Mask)) {
358 Val = N;
359 return true;
360 }
361
362 return false;
363}
364
366 unsigned MinSizeInBits) const {
367 if (!Subtarget->hasExtLSX())
368 return false;
369
371
372 if (!Node)
373 return false;
374
375 APInt SplatValue, SplatUndef;
376 unsigned SplatBitSize;
377 bool HasAnyUndefs;
378
379 if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
380 MinSizeInBits, /*IsBigEndian=*/false))
381 return false;
382
383 Imm = SplatValue;
384
385 return true;
386}
387
388template <unsigned ImmBitSize, bool IsSigned>
390 APInt ImmValue;
391 EVT EltTy = N->getValueType(0).getVectorElementType();
392
393 if (N->getOpcode() == ISD::BITCAST)
394 N = N->getOperand(0);
395
396 if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) &&
397 ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
398 if (IsSigned && ImmValue.isSignedIntN(ImmBitSize)) {
399 SplatVal = CurDAG->getSignedTargetConstant(
400 ImmValue.getSExtValue(), SDLoc(N), Subtarget->getGRLenVT());
401 return true;
402 }
403 if (!IsSigned && ImmValue.isIntN(ImmBitSize)) {
404 SplatVal = CurDAG->getTargetConstant(ImmValue.getZExtValue(), SDLoc(N),
405 Subtarget->getGRLenVT());
406 return true;
407 }
408 }
409
410 return false;
411}
412
414 SDValue &SplatImm) const {
415 APInt ImmValue;
416 EVT EltTy = N->getValueType(0).getVectorElementType();
417
418 if (N->getOpcode() == ISD::BITCAST)
419 N = N->getOperand(0);
420
421 if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) &&
422 ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
423 int32_t Log2 = (~ImmValue).exactLogBase2();
424
425 if (Log2 != -1) {
426 SplatImm = CurDAG->getSignedTargetConstant(Log2, SDLoc(N), EltTy);
427 return true;
428 }
429 }
430
431 return false;
432}
433
435 SDValue &SplatImm) const {
436 APInt ImmValue;
437 EVT EltTy = N->getValueType(0).getVectorElementType();
438
439 if (N->getOpcode() == ISD::BITCAST)
440 N = N->getOperand(0);
441
442 if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) &&
443 ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
444 int32_t Log2 = ImmValue.exactLogBase2();
445
446 if (Log2 != -1) {
447 SplatImm = CurDAG->getSignedTargetConstant(Log2, SDLoc(N), EltTy);
448 return true;
449 }
450 }
451
452 return false;
453}
454
455// This pass converts a legalized DAG into a LoongArch-specific DAG, ready
456// for instruction scheduling.
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define DEBUG_TYPE
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
#define PASS_NAME
Class for arbitrary precision integers.
Definition APInt.h:78
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1540
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1488
int32_t exactLogBase2() const
Definition APInt.h:1783
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
Definition APInt.h:435
LLVM_ABI APInt sextOrTrunc(unsigned width) const
Sign extend or truncate to width.
Definition APInt.cpp:1041
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
Definition APInt.h:1257
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
Definition APInt.h:296
bool isIntN(unsigned N) const
Check if this APInt has an N-bits unsigned integer value.
Definition APInt.h:432
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1562
A "pseudo-class" with methods for operating on BUILD_VECTORs.
LLVM_ABI 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
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
LoongArchDAGToDAGISelLegacy(LoongArchTargetMachine &TM, CodeGenOptLevel OptLevel)
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 SelectAddrRegImm12(SDValue Addr, SDValue &Base, SDValue &Offset)
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.
const SDValue & getOperand(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
SelectionDAGISelLegacy(char &ID, std::unique_ptr< SelectionDAGISel > S)
#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
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:870
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:730
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:543
InstSeq generateInstSeq(int64_t Val)
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:174
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:649
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
Definition Alignment.h:145
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:336
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:288
CodeGenOptLevel
Code generation optimization level.
Definition CodeGen.h:82
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:548
FunctionPass * createLoongArchISelDag(LoongArchTargetMachine &TM, CodeGenOptLevel OptLevel)
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:565
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition MathExtras.h:257
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:577
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:851
#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:368
bool is128BitVector() const
Return true if this is a 128-bit vector type.
Definition ValueTypes.h:207
bool is256BitVector() const
Return true if this is a 256-bit vector type.
Definition ValueTypes.h:212
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:323