LLVM 18.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.is512BitVector()) {
81 ReplaceUses(SDValue(Node, 0), Node->getOperand(0));
82 CurDAG->RemoveDeadNode(Node);
83 return;
84 }
85 break;
86 }
87 }
88
89 // Select the default instruction.
90 SelectCode(Node);
91}
92
94 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
95 std::vector<SDValue> &OutOps) {
96 SDValue Base = Op;
98 CurDAG->getTargetConstant(0, SDLoc(Op), Subtarget->getGRLenVT());
99 switch (ConstraintID) {
100 default:
101 llvm_unreachable("unexpected asm memory constraint");
102 // Reg+Reg addressing.
104 Base = Op.getOperand(0);
105 Offset = Op.getOperand(1);
106 break;
107 // Reg+simm12 addressing.
110 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op.getOperand(1));
111 if (isIntN(12, CN->getSExtValue())) {
112 Base = Op.getOperand(0);
114 Op.getValueType());
115 }
116 }
117 break;
118 // Reg+0 addressing.
120 break;
121 // Reg+(simm14<<2) addressing.
124 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op.getOperand(1));
125 if (isIntN(16, CN->getSExtValue()) &&
126 isAligned(Align(4ULL), CN->getZExtValue())) {
127 Base = Op.getOperand(0);
129 Op.getValueType());
130 }
131 }
132 break;
133 }
134 OutOps.push_back(Base);
135 OutOps.push_back(Offset);
136 return false;
137}
138
140 // If this is FrameIndex, select it directly. Otherwise just let it get
141 // selected to a register independently.
142 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Addr))
143 Base =
144 CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getGRLenVT());
145 else
146 Base = Addr;
147 return true;
148}
149
150// Fold constant addresses.
152 SDValue &Offset) {
153 SDLoc DL(Addr);
154 MVT VT = Addr.getSimpleValueType();
155
156 if (!isa<ConstantSDNode>(Addr))
157 return false;
158
159 // If the constant is a simm12, we can fold the whole constant and use R0 as
160 // the base.
161 int64_t CVal = cast<ConstantSDNode>(Addr)->getSExtValue();
162 if (!isInt<12>(CVal))
163 return false;
164 Base = CurDAG->getRegister(LoongArch::R0, VT);
165 Offset = CurDAG->getTargetConstant(SignExtend64<12>(CVal), DL, VT);
166 return true;
167}
168
170 // If this is FrameIndex, don't select it.
171 if (isa<FrameIndexSDNode>(Addr))
172 return false;
173 Base = Addr;
174 return true;
175}
176
178 SDValue &ShAmt) {
179 // Shift instructions on LoongArch only read the lower 5 or 6 bits of the
180 // shift amount. If there is an AND on the shift amount, we can bypass it if
181 // it doesn't affect any of those bits.
182 if (N.getOpcode() == ISD::AND && isa<ConstantSDNode>(N.getOperand(1))) {
183 const APInt &AndMask = N->getConstantOperandAPInt(1);
184
185 // Since the max shift amount is a power of 2 we can subtract 1 to make a
186 // mask that covers the bits needed to represent all shift amounts.
187 assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!");
188 APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1);
189
190 if (ShMask.isSubsetOf(AndMask)) {
191 ShAmt = N.getOperand(0);
192 return true;
193 }
194
195 // SimplifyDemandedBits may have optimized the mask so try restoring any
196 // bits that are known zero.
197 KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0));
198 if (ShMask.isSubsetOf(AndMask | Known.Zero)) {
199 ShAmt = N.getOperand(0);
200 return true;
201 }
202 } else if (N.getOpcode() == LoongArchISD::BSTRPICK) {
203 // Similar to the above AND, if there is a BSTRPICK on the shift amount, we
204 // can bypass it.
205 assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!");
206 assert(isa<ConstantSDNode>(N.getOperand(1)) && "Illegal msb operand!");
207 assert(isa<ConstantSDNode>(N.getOperand(2)) && "Illegal lsb operand!");
208 uint64_t msb = N.getConstantOperandVal(1), lsb = N.getConstantOperandVal(2);
209 if (lsb == 0 && Log2_32(ShiftWidth) <= msb + 1) {
210 ShAmt = N.getOperand(0);
211 return true;
212 }
213 } else if (N.getOpcode() == ISD::SUB &&
214 isa<ConstantSDNode>(N.getOperand(0))) {
215 uint64_t Imm = N.getConstantOperandVal(0);
216 // If we are shifting by N-X where N == 0 mod Size, then just shift by -X to
217 // generate a NEG instead of a SUB of a constant.
218 if (Imm != 0 && Imm % ShiftWidth == 0) {
219 SDLoc DL(N);
220 EVT VT = N.getValueType();
221 SDValue Zero =
222 CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, LoongArch::R0, VT);
223 unsigned NegOpc = VT == MVT::i64 ? LoongArch::SUB_D : LoongArch::SUB_W;
224 MachineSDNode *Neg =
225 CurDAG->getMachineNode(NegOpc, DL, VT, Zero, N.getOperand(1));
226 ShAmt = SDValue(Neg, 0);
227 return true;
228 }
229 }
230
231 ShAmt = N;
232 return true;
233}
234
236 if (N.getOpcode() == ISD::SIGN_EXTEND_INREG &&
237 cast<VTSDNode>(N.getOperand(1))->getVT() == MVT::i32) {
238 Val = N.getOperand(0);
239 return true;
240 }
241 if (N.getOpcode() == LoongArchISD::BSTRPICK &&
242 N.getConstantOperandVal(1) < UINT64_C(0X1F) &&
243 N.getConstantOperandVal(2) == UINT64_C(0)) {
244 Val = N;
245 return true;
246 }
247 MVT VT = N.getSimpleValueType();
248 if (CurDAG->ComputeNumSignBits(N) > (VT.getSizeInBits() - 32)) {
249 Val = N;
250 return true;
251 }
252
253 return false;
254}
255
257 if (N.getOpcode() == ISD::AND) {
258 auto *C = dyn_cast<ConstantSDNode>(N.getOperand(1));
259 if (C && C->getZExtValue() == UINT64_C(0xFFFFFFFF)) {
260 Val = N.getOperand(0);
261 return true;
262 }
263 }
264 MVT VT = N.getSimpleValueType();
266 if (CurDAG->MaskedValueIsZero(N, Mask)) {
267 Val = N;
268 return true;
269 }
270
271 return false;
272}
273
275 unsigned MinSizeInBits) const {
276 if (!Subtarget->hasExtLSX())
277 return false;
278
279 BuildVectorSDNode *Node = dyn_cast<BuildVectorSDNode>(N);
280
281 if (!Node)
282 return false;
283
284 APInt SplatValue, SplatUndef;
285 unsigned SplatBitSize;
286 bool HasAnyUndefs;
287
288 if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
289 MinSizeInBits, /*IsBigEndian=*/false))
290 return false;
291
292 Imm = SplatValue;
293
294 return true;
295}
296
297template <unsigned ImmBitSize, bool IsSigned>
299 APInt ImmValue;
300 EVT EltTy = N->getValueType(0).getVectorElementType();
301
302 if (N->getOpcode() == ISD::BITCAST)
303 N = N->getOperand(0);
304
305 if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) &&
306 ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
307 if (IsSigned && ImmValue.isSignedIntN(ImmBitSize)) {
308 SplatVal = CurDAG->getTargetConstant(ImmValue.getSExtValue(), SDLoc(N),
309 Subtarget->getGRLenVT());
310 return true;
311 }
312 if (!IsSigned && ImmValue.isIntN(ImmBitSize)) {
313 SplatVal = CurDAG->getTargetConstant(ImmValue.getZExtValue(), SDLoc(N),
314 Subtarget->getGRLenVT());
315 return true;
316 }
317 }
318
319 return false;
320}
321
323 SDValue &SplatImm) const {
324 APInt ImmValue;
325 EVT EltTy = N->getValueType(0).getVectorElementType();
326
327 if (N->getOpcode() == ISD::BITCAST)
328 N = N->getOperand(0);
329
330 if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) &&
331 ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
332 int32_t Log2 = (~ImmValue).exactLogBase2();
333
334 if (Log2 != -1) {
335 SplatImm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy);
336 return true;
337 }
338 }
339
340 return false;
341}
342
344 SDValue &SplatImm) const {
345 APInt ImmValue;
346 EVT EltTy = N->getValueType(0).getVectorElementType();
347
348 if (N->getOpcode() == ISD::BITCAST)
349 N = N->getOperand(0);
350
351 if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) &&
352 ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
353 int32_t Log2 = ImmValue.exactLogBase2();
354
355 if (Log2 != -1) {
356 SplatImm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy);
357 return true;
358 }
359 }
360
361 return false;
362}
363
364// This pass converts a legalized DAG into a LoongArch-specific DAG, ready
365// for instruction scheduling.
367 return new LoongArchDAGToDAGISel(TM);
368}
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:1485
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition: APInt.h:1433
int32_t exactLogBase2() const
Definition: APInt.h:1718
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:1229
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:1507
A "pseudo-class" with methods for operating on BUILD_VECTORs.
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.
bool is512BitVector() const
Return true if this is a 512-bit vector type.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
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.
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:725
SDValue getRegister(unsigned Reg, EVT VT)
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
Definition: SelectionDAG.h:674
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:797
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:900
@ 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:795
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:680
InstSeq generateInstSeq(int64_t Val)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:440
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:313
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition: MathExtras.h:264
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:233
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:351