22#define DEBUG_TYPE "loongarch-isel"
23#define PASS_NAME "LoongArch DAG->DAG Pattern Instruction Selection"
37 if (
Node->isMachineOpcode()) {
45 unsigned Opcode =
Node->getOpcode();
46 MVT GRLenVT = Subtarget->getGRLenVT();
48 MVT VT =
Node->getSimpleValueType(0);
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());
62 SDValue SrcReg = CurDAG->getRegister(LoongArch::R0, GRLenVT);
65 SDValue SDImm = CurDAG->getSignedTargetConstant(Inst.Imm,
DL, GRLenVT);
67 case LoongArch::LU12I_W:
68 Result = CurDAG->getMachineNode(Inst.Opc,
DL, GRLenVT, SDImm);
70 case LoongArch::ADDI_W:
72 case LoongArch::LU32I_D:
73 case LoongArch::LU52I_D:
74 Result = CurDAG->getMachineNode(Inst.Opc,
DL, GRLenVT, SrcReg, SDImm);
76 case LoongArch::BSTRINS_D:
77 Result = CurDAG->getMachineNode(
78 Inst.Opc,
DL, GRLenVT,
80 CurDAG->getSignedTargetConstant(Inst.Imm >> 32, DL, GRLenVT),
81 CurDAG->getTargetConstant(Inst.Imm & 0xFF, DL, GRLenVT)});
89 ReplaceNode(
Node, Result);
93 SDValue Imm = CurDAG->getTargetConstant(0,
DL, GRLenVT);
94 int FI = cast<FrameIndexSDNode>(
Node)->getIndex();
95 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
97 Subtarget->is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
98 ReplaceNode(
Node, CurDAG->getMachineNode(ADDIOp,
DL, VT, TFI, Imm));
104 CurDAG->RemoveDeadNode(
Node);
113 APInt SplatValue, SplatUndef;
114 unsigned SplatBitSize;
121 if (!Subtarget->hasExtLSX() || (!Is128Vec && !Is256Vec))
127 switch (SplatBitSize) {
131 Op = Is256Vec ? LoongArch::PseudoXVREPLI_B : LoongArch::PseudoVREPLI_B;
132 ViaVecTy = Is256Vec ? MVT::v32i8 : MVT::v16i8;
135 Op = Is256Vec ? LoongArch::PseudoXVREPLI_H : LoongArch::PseudoVREPLI_H;
136 ViaVecTy = Is256Vec ? MVT::v16i16 : MVT::v8i16;
139 Op = Is256Vec ? LoongArch::PseudoXVREPLI_W : LoongArch::PseudoVREPLI_W;
140 ViaVecTy = Is256Vec ? MVT::v8i32 : MVT::v4i32;
143 Op = Is256Vec ? LoongArch::PseudoXVREPLI_D : LoongArch::PseudoVREPLI_D;
144 ViaVecTy = Is256Vec ? MVT::v4i64 : MVT::v2i64;
151 SDValue Imm = CurDAG->getTargetConstant(SplatValue,
DL,
153 Res = CurDAG->getMachineNode(
Op,
DL, ViaVecTy, Imm);
154 ReplaceNode(
Node, Res);
167 std::vector<SDValue> &OutOps) {
171 switch (ConstraintID) {
206 OutOps.push_back(
Base);
214 if (
auto *FIN = dyn_cast<FrameIndexSDNode>(
Addr))
226 MVT VT =
Addr.getSimpleValueType();
228 if (!isa<ConstantSDNode>(
Addr))
233 int64_t CVal = cast<ConstantSDNode>(
Addr)->getSExtValue();
234 if (!isInt<12>(CVal))
243 if (isa<FrameIndexSDNode>(
Addr))
252 MVT VT =
Addr.getSimpleValueType();
256 int64_t Imm = cast<ConstantSDNode>(
Addr.getOperand(1))->getSExtValue();
257 if (isInt<12>(Imm)) {
276 if (
N.getOpcode() ==
ISD::AND && isa<ConstantSDNode>(
N.getOperand(1))) {
277 const APInt &AndMask =
N->getConstantOperandAPInt(1);
285 ShAmt =
N.getOperand(0);
293 ShAmt =
N.getOperand(0);
300 assert(isa<ConstantSDNode>(
N.getOperand(1)) &&
"Illegal msb operand!");
301 assert(isa<ConstantSDNode>(
N.getOperand(2)) &&
"Illegal lsb operand!");
302 uint64_t msb =
N.getConstantOperandVal(1), lsb =
N.getConstantOperandVal(2);
303 if (lsb == 0 &&
Log2_32(ShiftWidth) <= msb + 1) {
304 ShAmt =
N.getOperand(0);
308 isa<ConstantSDNode>(
N.getOperand(0))) {
309 uint64_t Imm =
N.getConstantOperandVal(0);
312 if (Imm != 0 && Imm % ShiftWidth == 0) {
314 EVT VT =
N.getValueType();
317 unsigned NegOpc = VT == MVT::i64 ? LoongArch::SUB_D : LoongArch::SUB_W;
331 cast<VTSDNode>(
N.getOperand(1))->getVT() == MVT::i32) {
332 Val =
N.getOperand(0);
336 N.getConstantOperandVal(1) < UINT64_C(0X1F) &&
337 N.getConstantOperandVal(2) == UINT64_C(0)) {
341 MVT VT =
N.getSimpleValueType();
352 auto *
C = dyn_cast<ConstantSDNode>(
N.getOperand(1));
353 if (
C &&
C->getZExtValue() == UINT64_C(0xFFFFFFFF)) {
354 Val =
N.getOperand(0);
358 MVT VT =
N.getSimpleValueType();
369 unsigned MinSizeInBits)
const {
370 if (!Subtarget->hasExtLSX())
378 APInt SplatValue, SplatUndef;
379 unsigned SplatBitSize;
382 if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
383 MinSizeInBits,
false))
391template <
unsigned ImmBitSize,
bool IsSigned>
394 EVT EltTy =
N->getValueType(0).getVectorElementType();
397 N =
N->getOperand(0);
406 if (!IsSigned && ImmValue.
isIntN(ImmBitSize)) {
419 EVT EltTy =
N->getValueType(0).getVectorElementType();
422 N =
N->getOperand(0);
426 int32_t
Log2 = (~ImmValue).exactLogBase2();
440 EVT EltTy =
N->getValueType(0).getVectorElementType();
443 N =
N->getOperand(0);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
DEMANGLE_DUMP_METHOD void dump() const
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
unsigned getBitWidth() const
Return the number of bits in the APInt.
int32_t exactLogBase2() const
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
bool isIntN(unsigned N) const
Check if this APInt has an N-bits unsigned integer value.
int64_t getSExtValue() const
Get sign extended value.
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
This class represents an Operation in the Expression.
FunctionPass class - This class is used to implement most global optimizations.
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)
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.
LLVM_ABI 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),...
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getTargetFrameIndex(int FI, EVT VT)
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI 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.
LLVM_ABI bool isBaseWithConstantOffset(SDValue Op) const
Return true if the specified operand is an ISD::ADD with a ConstantSDNode on the right-hand side,...
LLVM_ABI 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.
LLVM_ABI 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.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
InstSeq generateInstSeq(int64_t Val)
This is an optimization pass for GlobalISel generic memory operations.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
CodeGenOptLevel
Code generation optimization level.
FunctionPass * createLoongArchISelDag(LoongArchTargetMachine &TM, CodeGenOptLevel OptLevel)
DWARFExpression::Operation Op
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
unsigned Log2(Align A)
Returns the log2 of the alignment.
Implement std::hash so that hash_code can be used in STL containers.
This struct is a compact representation of a valid (non-zero power of two) alignment.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
bool is256BitVector() const
Return true if this is a 256-bit vector type.
EVT getVectorElementType() const
Given a vector type, return the type of each element.