LLVM 19.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
28
30 // If we have a custom node, we have already selected.
31 if (Node->isMachineOpcode()) {
32 LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n");
33 Node->setNodeId(-1);
34 return;
35 }
36
37 // Instruction Selection not handled by the auto-generated tablegen selection
38 // should be handled here.
39 unsigned Opcode = Node->getOpcode();
40 MVT GRLenVT = Subtarget->getGRLenVT();
41 SDLoc DL(Node);
42 MVT VT = Node->getSimpleValueType(0);
43
44 switch (Opcode) {
45 default:
46 break;
47 case ISD::Constant: {
48 int64_t Imm = cast<ConstantSDNode>(Node)->getSExtValue();
49 if (Imm == 0 && VT == GRLenVT) {
50 SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL,
51 LoongArch::R0, GRLenVT);
52 ReplaceNode(Node, New.getNode());
53 return;
54 }
55 SDNode *Result = nullptr;
56 SDValue SrcReg = CurDAG->getRegister(LoongArch::R0, GRLenVT);
57 // The instructions in the sequence are handled here.
59 SDValue SDImm = CurDAG->getTargetConstant(Inst.Imm, DL, GRLenVT);
60 if (Inst.Opc == LoongArch::LU12I_W)
61 Result = CurDAG->getMachineNode(LoongArch::LU12I_W, DL, GRLenVT, SDImm);
62 else
63 Result = CurDAG->getMachineNode(Inst.Opc, DL, GRLenVT, SrcReg, SDImm);
64 SrcReg = SDValue(Result, 0);
65 }
66
67 ReplaceNode(Node, Result);
68 return;
69 }
70 case ISD::FrameIndex: {
71 SDValue Imm = CurDAG->getTargetConstant(0, DL, GRLenVT);
72 int FI = cast<FrameIndexSDNode>(Node)->getIndex();
73 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
74 unsigned ADDIOp =
75 Subtarget->is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
76 ReplaceNode(Node, CurDAG->getMachineNode(ADDIOp, DL, VT, TFI, Imm));
77 return;
78 }
79 case ISD::BITCAST: {
80 if (VT.is128BitVector() || VT.is256BitVector()) {
81 ReplaceUses(SDValue(Node, 0), Node->getOperand(0));
82 CurDAG->RemoveDeadNode(Node);
83 return;
84 }
85 break;
86 }
87 case ISD::BUILD_VECTOR: {
88 // Select appropriate [x]vrepli.[bhwd] instructions for constant splats of
89 // 128/256-bit when LSX/LASX is enabled.
90 BuildVectorSDNode *BVN = cast<BuildVectorSDNode>(Node);
91 APInt SplatValue, SplatUndef;
92 unsigned SplatBitSize;
93 bool HasAnyUndefs;
94 unsigned Op;
95 EVT ViaVecTy;
96 bool Is128Vec = BVN->getValueType(0).is128BitVector();
97 bool Is256Vec = BVN->getValueType(0).is256BitVector();
98
99 if (!Subtarget->hasExtLSX() || (!Is128Vec && !Is256Vec))
100 break;
101 if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
102 HasAnyUndefs, 8))
103 break;
104
105 switch (SplatBitSize) {
106 default:
107 break;
108 case 8:
109 Op = Is256Vec ? LoongArch::PseudoXVREPLI_B : LoongArch::PseudoVREPLI_B;
110 ViaVecTy = Is256Vec ? MVT::v32i8 : MVT::v16i8;
111 break;
112 case 16:
113 Op = Is256Vec ? LoongArch::PseudoXVREPLI_H : LoongArch::PseudoVREPLI_H;
114 ViaVecTy = Is256Vec ? MVT::v16i16 : MVT::v8i16;
115 break;
116 case 32:
117 Op = Is256Vec ? LoongArch::PseudoXVREPLI_W : LoongArch::PseudoVREPLI_W;
118 ViaVecTy = Is256Vec ? MVT::v8i32 : MVT::v4i32;
119 break;
120 case 64:
121 Op = Is256Vec ? LoongArch::PseudoXVREPLI_D : LoongArch::PseudoVREPLI_D;
122 ViaVecTy = Is256Vec ? MVT::v4i64 : MVT::v2i64;
123 break;
124 }
125
126 SDNode *Res;
127 // If we have a signed 10 bit integer, we can splat it directly.
128 if (SplatValue.isSignedIntN(10)) {
129 SDValue Imm = CurDAG->getTargetConstant(SplatValue, DL,
130 ViaVecTy.getVectorElementType());
131 Res = CurDAG->getMachineNode(Op, DL, ViaVecTy, Imm);
132 ReplaceNode(Node, Res);
133 return;
134 }
135 break;
136 }
137 }
138
139 // Select the default instruction.
140 SelectCode(Node);
141}
142
144 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
145 std::vector<SDValue> &OutOps) {
146 SDValue Base = Op;
148 CurDAG->getTargetConstant(0, SDLoc(Op), Subtarget->getGRLenVT());
149 switch (ConstraintID) {
150 default:
151 llvm_unreachable("unexpected asm memory constraint");
152 // Reg+Reg addressing.
154 Base = Op.getOperand(0);
155 Offset = Op.getOperand(1);
156 break;
157 // Reg+simm12 addressing.
160 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op.getOperand(1));
161 if (isIntN(12, CN->getSExtValue())) {
162 Base = Op.getOperand(0);
164 Op.getValueType());
165 }
166 }
167 break;
168 // Reg+0 addressing.
170 break;
171 // Reg+(simm14<<2) addressing.
174 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op.getOperand(1));
175 if (isIntN(16, CN->getSExtValue()) &&
176 isAligned(Align(4ULL), CN->getZExtValue())) {
177 Base = Op.getOperand(0);
179 Op.getValueType());
180 }
181 }
182 break;
183 }
184 OutOps.push_back(Base);
185 OutOps.push_back(Offset);
186 return false;
187}
188
190 // If this is FrameIndex, select it directly. Otherwise just let it get
191 // selected to a register independently.
192 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Addr))
193 Base =
194 CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getGRLenVT());
195 else
196 Base = Addr;
197 return true;
198}
199
200// Fold constant addresses.
202 SDValue &Offset) {
203 SDLoc DL(Addr);
204 MVT VT = Addr.getSimpleValueType();
205
206 if (!isa<ConstantSDNode>(Addr))
207 return false;
208
209 // If the constant is a simm12, we can fold the whole constant and use R0 as
210 // the base.
211 int64_t CVal = cast<ConstantSDNode>(Addr)->getSExtValue();
212 if (!isInt<12>(CVal))
213 return false;
214 Base = CurDAG->getRegister(LoongArch::R0, VT);
215 Offset = CurDAG->getTargetConstant(SignExtend64<12>(CVal), DL, VT);
216 return true;
217}
218
220 // If this is FrameIndex, don't select it.
221 if (isa<FrameIndexSDNode>(Addr))
222 return false;
223 Base = Addr;
224 return true;
225}
226
228 SDValue &ShAmt) {
229 // Shift instructions on LoongArch only read the lower 5 or 6 bits of the
230 // shift amount. If there is an AND on the shift amount, we can bypass it if
231 // it doesn't affect any of those bits.
232 if (N.getOpcode() == ISD::AND && isa<ConstantSDNode>(N.getOperand(1))) {
233 const APInt &AndMask = N->getConstantOperandAPInt(1);
234
235 // Since the max shift amount is a power of 2 we can subtract 1 to make a
236 // mask that covers the bits needed to represent all shift amounts.
237 assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!");
238 APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1);
239
240 if (ShMask.isSubsetOf(AndMask)) {
241 ShAmt = N.getOperand(0);
242 return true;
243 }
244
245 // SimplifyDemandedBits may have optimized the mask so try restoring any
246 // bits that are known zero.
247 KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0));
248 if (ShMask.isSubsetOf(AndMask | Known.Zero)) {
249 ShAmt = N.getOperand(0);
250 return true;
251 }
252 } else if (N.getOpcode() == LoongArchISD::BSTRPICK) {
253 // Similar to the above AND, if there is a BSTRPICK on the shift amount, we
254 // can bypass it.
255 assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!");
256 assert(isa<ConstantSDNode>(N.getOperand(1)) && "Illegal msb operand!");
257 assert(isa<ConstantSDNode>(N.getOperand(2)) && "Illegal lsb operand!");
258 uint64_t msb = N.getConstantOperandVal(1), lsb = N.getConstantOperandVal(2);
259 if (lsb == 0 && Log2_32(ShiftWidth) <= msb + 1) {
260 ShAmt = N.getOperand(0);
261 return true;
262 }
263 } else if (N.getOpcode() == ISD::SUB &&
264 isa<ConstantSDNode>(N.getOperand(0))) {
265 uint64_t Imm = N.getConstantOperandVal(0);
266 // If we are shifting by N-X where N == 0 mod Size, then just shift by -X to
267 // generate a NEG instead of a SUB of a constant.
268 if (Imm != 0 && Imm % ShiftWidth == 0) {
269 SDLoc DL(N);
270 EVT VT = N.getValueType();
271 SDValue Zero =
272 CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, LoongArch::R0, VT);
273 unsigned NegOpc = VT == MVT::i64 ? LoongArch::SUB_D : LoongArch::SUB_W;
274 MachineSDNode *Neg =
275 CurDAG->getMachineNode(NegOpc, DL, VT, Zero, N.getOperand(1));
276 ShAmt = SDValue(Neg, 0);
277 return true;
278 }
279 }
280
281 ShAmt = N;
282 return true;
283}
284
286 if (N.getOpcode() == ISD::SIGN_EXTEND_INREG &&
287 cast<VTSDNode>(N.getOperand(1))->getVT() == MVT::i32) {
288 Val = N.getOperand(0);
289 return true;
290 }
291 if (N.getOpcode() == LoongArchISD::BSTRPICK &&
292 N.getConstantOperandVal(1) < UINT64_C(0X1F) &&
293 N.getConstantOperandVal(2) == UINT64_C(0)) {
294 Val = N;
295 return true;
296 }
297 MVT VT = N.getSimpleValueType();
298 if (CurDAG->ComputeNumSignBits(N) > (VT.getSizeInBits() - 32)) {
299 Val = N;
300 return true;
301 }
302
303 return false;
304}
305
307 if (N.getOpcode() == ISD::AND) {
308 auto *C = dyn_cast<ConstantSDNode>(N.getOperand(1));
309 if (C && C->getZExtValue() == UINT64_C(0xFFFFFFFF)) {
310 Val = N.getOperand(0);
311 return true;
312 }
313 }
314 MVT VT = N.getSimpleValueType();
316 if (CurDAG->MaskedValueIsZero(N, Mask)) {
317 Val = N;
318 return true;
319 }
320
321 return false;
322}
323
325 unsigned MinSizeInBits) const {
326 if (!Subtarget->hasExtLSX())
327 return false;
328
329 BuildVectorSDNode *Node = dyn_cast<BuildVectorSDNode>(N);
330
331 if (!Node)
332 return false;
333
334 APInt SplatValue, SplatUndef;
335 unsigned SplatBitSize;
336 bool HasAnyUndefs;
337
338 if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
339 MinSizeInBits, /*IsBigEndian=*/false))
340 return false;
341
342 Imm = SplatValue;
343
344 return true;
345}
346
347template <unsigned ImmBitSize, bool IsSigned>
349 APInt ImmValue;
350 EVT EltTy = N->getValueType(0).getVectorElementType();
351
352 if (N->getOpcode() == ISD::BITCAST)
353 N = N->getOperand(0);
354
355 if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) &&
356 ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
357 if (IsSigned && ImmValue.isSignedIntN(ImmBitSize)) {
358 SplatVal = CurDAG->getTargetConstant(ImmValue.getSExtValue(), SDLoc(N),
359 Subtarget->getGRLenVT());
360 return true;
361 }
362 if (!IsSigned && ImmValue.isIntN(ImmBitSize)) {
363 SplatVal = CurDAG->getTargetConstant(ImmValue.getZExtValue(), SDLoc(N),
364 Subtarget->getGRLenVT());
365 return true;
366 }
367 }
368
369 return false;
370}
371
373 SDValue &SplatImm) const {
374 APInt ImmValue;
375 EVT EltTy = N->getValueType(0).getVectorElementType();
376
377 if (N->getOpcode() == ISD::BITCAST)
378 N = N->getOperand(0);
379
380 if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) &&
381 ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
382 int32_t Log2 = (~ImmValue).exactLogBase2();
383
384 if (Log2 != -1) {
385 SplatImm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy);
386 return true;
387 }
388 }
389
390 return false;
391}
392
394 SDValue &SplatImm) const {
395 APInt ImmValue;
396 EVT EltTy = N->getValueType(0).getVectorElementType();
397
398 if (N->getOpcode() == ISD::BITCAST)
399 N = N->getOperand(0);
400
401 if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) &&
402 ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
403 int32_t Log2 = ImmValue.exactLogBase2();
404
405 if (Log2 != -1) {
406 SplatImm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy);
407 return true;
408 }
409 }
410
411 return false;
412}
413
414// This pass converts a legalized DAG into a LoongArch-specific DAG, ready
415// for instruction scheduling.
417 return new LoongArchDAGToDAGISel(TM);
418}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu AMDGPU Register Bank Select
#define LLVM_DEBUG(X)
Definition: Debug.h:101
uint64_t Addr
#define PASS_NAME
#define DEBUG_TYPE
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Class for arbitrary precision integers.
Definition: APInt.h:76
uint64_t getZExtValue() const
Get zero extended value.
Definition: APInt.h:1491
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition: APInt.h:1439
int32_t exactLogBase2() const
Definition: APInt.h:1725
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:1513
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:311
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:727
SDValue getRegister(unsigned Reg, EVT VT)
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
Definition: SelectionDAG.h:676
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:799
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:554
#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:903
@ 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:798
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:680
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition: ISDOpcodes.h:515
InstSeq generateInstSeq(int64_t Val)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:456
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:324
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition: MathExtras.h:275
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:244
DWARFExpression::Operation Op
unsigned Log2(Align A)
Returns the log2 of the alignment.
Definition: Alignment.h:208
#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:34
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition: ValueTypes.h:358
bool is128BitVector() const
Return true if this is a 128-bit vector type.
Definition: ValueTypes.h:203
bool is256BitVector() const
Return true if this is a 256-bit vector type.
Definition: ValueTypes.h:208
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition: ValueTypes.h:318