LLVM 17.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
18
19using namespace llvm;
20
21#define DEBUG_TYPE "loongarch-isel"
22#define PASS_NAME "LoongArch DAG->DAG Pattern Instruction Selection"
23
25
27
29 // If we have a custom node, we have already selected.
30 if (Node->isMachineOpcode()) {
31 LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n");
32 Node->setNodeId(-1);
33 return;
34 }
35
36 // Instruction Selection not handled by the auto-generated tablegen selection
37 // should be handled here.
38 unsigned Opcode = Node->getOpcode();
39 MVT GRLenVT = Subtarget->getGRLenVT();
40 SDLoc DL(Node);
41 MVT VT = Node->getSimpleValueType(0);
42
43 switch (Opcode) {
44 default:
45 break;
46 case ISD::Constant: {
47 int64_t Imm = cast<ConstantSDNode>(Node)->getSExtValue();
48 if (Imm == 0 && VT == GRLenVT) {
49 SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL,
50 LoongArch::R0, GRLenVT);
51 ReplaceNode(Node, New.getNode());
52 return;
53 }
54 SDNode *Result = nullptr;
55 SDValue SrcReg = CurDAG->getRegister(LoongArch::R0, GRLenVT);
56 // The instructions in the sequence are handled here.
58 SDValue SDImm = CurDAG->getTargetConstant(Inst.Imm, DL, GRLenVT);
59 if (Inst.Opc == LoongArch::LU12I_W)
60 Result = CurDAG->getMachineNode(LoongArch::LU12I_W, DL, GRLenVT, SDImm);
61 else
62 Result = CurDAG->getMachineNode(Inst.Opc, DL, GRLenVT, SrcReg, SDImm);
63 SrcReg = SDValue(Result, 0);
64 }
65
66 ReplaceNode(Node, Result);
67 return;
68 }
69 case ISD::FrameIndex: {
70 SDValue Imm = CurDAG->getTargetConstant(0, DL, GRLenVT);
71 int FI = cast<FrameIndexSDNode>(Node)->getIndex();
72 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
73 unsigned ADDIOp =
74 Subtarget->is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
75 ReplaceNode(Node, CurDAG->getMachineNode(ADDIOp, DL, VT, TFI, Imm));
76 return;
77 }
78 // TODO: Add selection nodes needed later.
79 }
80
81 // Select the default instruction.
82 SelectCode(Node);
83}
84
86 const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) {
87 SDValue Base = Op;
89 CurDAG->getTargetConstant(0, SDLoc(Op), Subtarget->getGRLenVT());
90 switch (ConstraintID) {
91 default:
92 llvm_unreachable("unexpected asm memory constraint");
93 // Reg+Reg addressing.
95 Base = Op.getOperand(0);
96 Offset = Op.getOperand(1);
97 break;
98 // Reg+simm12 addressing.
101 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op.getOperand(1));
102 if (isIntN(12, CN->getSExtValue())) {
103 Base = Op.getOperand(0);
105 Op.getValueType());
106 }
107 }
108 break;
109 // Reg+0 addressing.
111 break;
112 // Reg+(simm14<<2) addressing.
115 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op.getOperand(1));
116 if (isIntN(16, CN->getSExtValue()) &&
117 isAligned(Align(4ULL), CN->getZExtValue())) {
118 Base = Op.getOperand(0);
120 Op.getValueType());
121 }
122 }
123 break;
124 }
125 OutOps.push_back(Base);
126 OutOps.push_back(Offset);
127 return false;
128}
129
131 // If this is FrameIndex, select it directly. Otherwise just let it get
132 // selected to a register independently.
133 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Addr))
134 Base =
135 CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getGRLenVT());
136 else
137 Base = Addr;
138 return true;
139}
140
141// Fold constant addresses.
143 SDValue &Offset) {
144 SDLoc DL(Addr);
145 MVT VT = Addr.getSimpleValueType();
146
147 if (!isa<ConstantSDNode>(Addr))
148 return false;
149
150 // If the constant is a simm12, we can fold the whole constant and use R0 as
151 // the base.
152 int64_t CVal = cast<ConstantSDNode>(Addr)->getSExtValue();
153 if (!isInt<12>(CVal))
154 return false;
155 Base = CurDAG->getRegister(LoongArch::R0, VT);
156 Offset = CurDAG->getTargetConstant(SignExtend64<12>(CVal), DL, VT);
157 return true;
158}
159
161 // If this is FrameIndex, don't select it.
162 if (isa<FrameIndexSDNode>(Addr))
163 return false;
164 Base = Addr;
165 return true;
166}
167
169 SDValue &ShAmt) {
170 // Shift instructions on LoongArch only read the lower 5 or 6 bits of the
171 // shift amount. If there is an AND on the shift amount, we can bypass it if
172 // it doesn't affect any of those bits.
173 if (N.getOpcode() == ISD::AND && isa<ConstantSDNode>(N.getOperand(1))) {
174 const APInt &AndMask = N->getConstantOperandAPInt(1);
175
176 // Since the max shift amount is a power of 2 we can subtract 1 to make a
177 // mask that covers the bits needed to represent all shift amounts.
178 assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!");
179 APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1);
180
181 if (ShMask.isSubsetOf(AndMask)) {
182 ShAmt = N.getOperand(0);
183 return true;
184 }
185
186 // SimplifyDemandedBits may have optimized the mask so try restoring any
187 // bits that are known zero.
188 KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0));
189 if (ShMask.isSubsetOf(AndMask | Known.Zero)) {
190 ShAmt = N.getOperand(0);
191 return true;
192 }
193 } else if (N.getOpcode() == LoongArchISD::BSTRPICK) {
194 // Similar to the above AND, if there is a BSTRPICK on the shift amount, we
195 // can bypass it.
196 assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!");
197 assert(isa<ConstantSDNode>(N.getOperand(1)) && "Illegal msb operand!");
198 assert(isa<ConstantSDNode>(N.getOperand(2)) && "Illegal lsb operand!");
199 uint64_t msb = N.getConstantOperandVal(1), lsb = N.getConstantOperandVal(2);
200 if (lsb == 0 && Log2_32(ShiftWidth) <= msb + 1) {
201 ShAmt = N.getOperand(0);
202 return true;
203 }
204 } else if (N.getOpcode() == ISD::SUB &&
205 isa<ConstantSDNode>(N.getOperand(0))) {
206 uint64_t Imm = N.getConstantOperandVal(0);
207 // If we are shifting by N-X where N == 0 mod Size, then just shift by -X to
208 // generate a NEG instead of a SUB of a constant.
209 if (Imm != 0 && Imm % ShiftWidth == 0) {
210 SDLoc DL(N);
211 EVT VT = N.getValueType();
212 SDValue Zero =
213 CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, LoongArch::R0, VT);
214 unsigned NegOpc = VT == MVT::i64 ? LoongArch::SUB_D : LoongArch::SUB_W;
215 MachineSDNode *Neg =
216 CurDAG->getMachineNode(NegOpc, DL, VT, Zero, N.getOperand(1));
217 ShAmt = SDValue(Neg, 0);
218 return true;
219 }
220 }
221
222 ShAmt = N;
223 return true;
224}
225
227 if (N.getOpcode() == ISD::SIGN_EXTEND_INREG &&
228 cast<VTSDNode>(N.getOperand(1))->getVT() == MVT::i32) {
229 Val = N.getOperand(0);
230 return true;
231 }
232 if (N.getOpcode() == LoongArchISD::BSTRPICK &&
233 N.getConstantOperandVal(1) < UINT64_C(0X1F) &&
234 N.getConstantOperandVal(2) == UINT64_C(0)) {
235 Val = N;
236 return true;
237 }
238 MVT VT = N.getSimpleValueType();
239 if (CurDAG->ComputeNumSignBits(N) > (VT.getSizeInBits() - 32)) {
240 Val = N;
241 return true;
242 }
243
244 return false;
245}
246
248 if (N.getOpcode() == ISD::AND) {
249 auto *C = dyn_cast<ConstantSDNode>(N.getOperand(1));
250 if (C && C->getZExtValue() == UINT64_C(0xFFFFFFFF)) {
251 Val = N.getOperand(0);
252 return true;
253 }
254 }
255 MVT VT = N.getSimpleValueType();
257 if (CurDAG->MaskedValueIsZero(N, Mask)) {
258 Val = N;
259 return true;
260 }
261
262 return false;
263}
264
265// This pass converts a legalized DAG into a LoongArch-specific DAG, ready
266// for instruction scheduling.
268 return new LoongArchDAGToDAGISel(TM);
269}
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:75
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition: APInt.h:1439
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:279
uint64_t getZExtValue() const
int64_t getSExtValue() const
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:308
bool selectNonFIBaseAddr(SDValue Addr, SDValue &Base)
bool selectSExti32(SDValue N, SDValue &Val)
bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, std::vector< SDValue > &OutOps) override
SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode,...
bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt)
bool selectZExti32(SDValue N, SDValue &Val)
bool SelectAddrConstant(SDValue Addr, SDValue &Base, SDValue &Offset)
bool SelectBaseAddr(SDValue Addr, SDValue &Base)
Machine Value 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:726
SDValue getRegister(unsigned Reg, EVT VT)
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
Definition: SelectionDAG.h:675
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
@ 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:794
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:679
InstSeq generateInstSeq(int64_t Val)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:406
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:382
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition: MathExtras.h:292
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:261
#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