1 | //===-- MipsSEISelDAGToDAG.cpp - A Dag to Dag Inst Selector for MipsSE ----===// |
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 | // Subclass of MipsDAGToDAGISel specialized for mips32/64. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "MipsSEISelDAGToDAG.h" |
14 | #include "Mips.h" |
15 | #include "MipsAnalyzeImmediate.h" |
16 | #include "MipsMachineFunction.h" |
17 | #include "MipsRegisterInfo.h" |
18 | #include "llvm/CodeGen/MachineFrameInfo.h" |
19 | #include "llvm/CodeGen/MachineFunction.h" |
20 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
21 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
22 | #include "llvm/CodeGen/SelectionDAGNodes.h" |
23 | #include "llvm/IR/Dominators.h" |
24 | #include "llvm/IR/GlobalValue.h" |
25 | #include "llvm/IR/Instructions.h" |
26 | #include "llvm/IR/Intrinsics.h" |
27 | #include "llvm/IR/IntrinsicsMips.h" |
28 | #include "llvm/IR/Type.h" |
29 | #include "llvm/Support/ErrorHandling.h" |
30 | #include "llvm/Target/TargetMachine.h" |
31 | using namespace llvm; |
32 | |
33 | #define DEBUG_TYPE "mips-isel" |
34 | |
35 | bool MipsSEDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { |
36 | Subtarget = &MF.getSubtarget<MipsSubtarget>(); |
37 | if (Subtarget->inMips16Mode()) |
38 | return false; |
39 | return MipsDAGToDAGISel::runOnMachineFunction(MF); |
40 | } |
41 | |
42 | void MipsSEDAGToDAGISelLegacy::getAnalysisUsage(AnalysisUsage &AU) const { |
43 | AU.addRequired<DominatorTreeWrapperPass>(); |
44 | SelectionDAGISelLegacy::getAnalysisUsage(AU); |
45 | } |
46 | |
47 | void MipsSEDAGToDAGISel::addDSPCtrlRegOperands(bool IsDef, MachineInstr &MI, |
48 | MachineFunction &MF) { |
49 | MachineInstrBuilder MIB(MF, &MI); |
50 | unsigned Mask = MI.getOperand(i: 1).getImm(); |
51 | unsigned Flag = |
52 | IsDef ? RegState::ImplicitDefine : RegState::Implicit | RegState::Undef; |
53 | |
54 | if (Mask & 1) |
55 | MIB.addReg(RegNo: Mips::DSPPos, flags: Flag); |
56 | |
57 | if (Mask & 2) |
58 | MIB.addReg(RegNo: Mips::DSPSCount, flags: Flag); |
59 | |
60 | if (Mask & 4) |
61 | MIB.addReg(RegNo: Mips::DSPCarry, flags: Flag); |
62 | |
63 | if (Mask & 8) |
64 | MIB.addReg(RegNo: Mips::DSPOutFlag, flags: Flag); |
65 | |
66 | if (Mask & 16) |
67 | MIB.addReg(RegNo: Mips::DSPCCond, flags: Flag); |
68 | |
69 | if (Mask & 32) |
70 | MIB.addReg(RegNo: Mips::DSPEFI, flags: Flag); |
71 | } |
72 | |
73 | MCRegister MipsSEDAGToDAGISel::getMSACtrlReg(const SDValue RegIdx) const { |
74 | uint64_t RegNum = RegIdx->getAsZExtVal(); |
75 | return Mips::MSACtrlRegClass.getRegister(i: RegNum); |
76 | } |
77 | |
78 | bool MipsSEDAGToDAGISel::replaceUsesWithZeroReg(MachineRegisterInfo *MRI, |
79 | const MachineInstr& MI) { |
80 | unsigned DstReg = 0, ZeroReg = 0; |
81 | |
82 | // Check if MI is "addiu $dst, $zero, 0" or "daddiu $dst, $zero, 0". |
83 | if ((MI.getOpcode() == Mips::ADDiu) && |
84 | (MI.getOperand(i: 1).getReg() == Mips::ZERO) && |
85 | (MI.getOperand(i: 2).isImm()) && |
86 | (MI.getOperand(i: 2).getImm() == 0)) { |
87 | DstReg = MI.getOperand(i: 0).getReg(); |
88 | ZeroReg = Mips::ZERO; |
89 | } else if ((MI.getOpcode() == Mips::DADDiu) && |
90 | (MI.getOperand(i: 1).getReg() == Mips::ZERO_64) && |
91 | (MI.getOperand(i: 2).isImm()) && |
92 | (MI.getOperand(i: 2).getImm() == 0)) { |
93 | DstReg = MI.getOperand(i: 0).getReg(); |
94 | ZeroReg = Mips::ZERO_64; |
95 | } |
96 | |
97 | if (!DstReg) |
98 | return false; |
99 | |
100 | // Replace uses with ZeroReg. |
101 | for (MachineRegisterInfo::use_iterator U = MRI->use_begin(RegNo: DstReg), |
102 | E = MRI->use_end(); U != E;) { |
103 | MachineOperand &MO = *U; |
104 | unsigned OpNo = U.getOperandNo(); |
105 | MachineInstr *MI = MO.getParent(); |
106 | ++U; |
107 | |
108 | // Do not replace if it is a phi's operand or is tied to def operand. |
109 | if (MI->isPHI() || MI->isRegTiedToDefOperand(UseOpIdx: OpNo) || MI->isPseudo()) |
110 | continue; |
111 | |
112 | // Also, we have to check that the register class of the operand |
113 | // contains the zero register. |
114 | if (!MRI->getRegClass(Reg: MO.getReg())->contains(Reg: ZeroReg)) |
115 | continue; |
116 | |
117 | MO.setReg(ZeroReg); |
118 | } |
119 | |
120 | return true; |
121 | } |
122 | |
123 | void MipsSEDAGToDAGISel::emitMCountABI(MachineInstr &MI, MachineBasicBlock &MBB, |
124 | MachineFunction &MF) { |
125 | MachineInstrBuilder MIB(MF, &MI); |
126 | if (!Subtarget->isABI_O32()) { // N32, N64 |
127 | // Save current return address. |
128 | BuildMI(BB&: MBB, I: &MI, MIMD: MI.getDebugLoc(), MCID: TII->get(Opcode: Mips::OR64)) |
129 | .addDef(RegNo: Mips::AT_64) |
130 | .addUse(RegNo: Mips::RA_64, Flags: RegState::Undef) |
131 | .addUse(RegNo: Mips::ZERO_64); |
132 | // Stops instruction above from being removed later on. |
133 | MIB.addUse(RegNo: Mips::AT_64, Flags: RegState::Implicit); |
134 | } else { // O32 |
135 | // Save current return address. |
136 | BuildMI(BB&: MBB, I: &MI, MIMD: MI.getDebugLoc(), MCID: TII->get(Opcode: Mips::OR)) |
137 | .addDef(RegNo: Mips::AT) |
138 | .addUse(RegNo: Mips::RA, Flags: RegState::Undef) |
139 | .addUse(RegNo: Mips::ZERO); |
140 | // _mcount pops 2 words from stack. |
141 | BuildMI(BB&: MBB, I: &MI, MIMD: MI.getDebugLoc(), MCID: TII->get(Opcode: Mips::ADDiu)) |
142 | .addDef(RegNo: Mips::SP) |
143 | .addUse(RegNo: Mips::SP) |
144 | .addImm(Val: -8); |
145 | // Stops first instruction above from being removed later on. |
146 | MIB.addUse(RegNo: Mips::AT, Flags: RegState::Implicit); |
147 | } |
148 | } |
149 | |
150 | void MipsSEDAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) { |
151 | MF.getInfo<MipsFunctionInfo>()->initGlobalBaseReg(MF); |
152 | |
153 | MachineRegisterInfo *MRI = &MF.getRegInfo(); |
154 | |
155 | for (auto &MBB: MF) { |
156 | for (auto &MI: MBB) { |
157 | switch (MI.getOpcode()) { |
158 | case Mips::RDDSP: |
159 | addDSPCtrlRegOperands(IsDef: false, MI, MF); |
160 | break; |
161 | case Mips::WRDSP: |
162 | addDSPCtrlRegOperands(IsDef: true, MI, MF); |
163 | break; |
164 | case Mips::BuildPairF64_64: |
165 | case Mips::ExtractElementF64_64: |
166 | if (!Subtarget->useOddSPReg()) { |
167 | MI.addOperand(Op: MachineOperand::CreateReg(Reg: Mips::SP, isDef: false, isImp: true)); |
168 | break; |
169 | } |
170 | [[fallthrough]]; |
171 | case Mips::BuildPairF64: |
172 | case Mips::ExtractElementF64: |
173 | if (Subtarget->isABI_FPXX() && !Subtarget->hasMTHC1()) |
174 | MI.addOperand(Op: MachineOperand::CreateReg(Reg: Mips::SP, isDef: false, isImp: true)); |
175 | break; |
176 | case Mips::JAL: |
177 | case Mips::JAL_MM: |
178 | if (MI.getOperand(i: 0).isGlobal() && |
179 | MI.getOperand(i: 0).getGlobal()->hasExternalLinkage() && |
180 | MI.getOperand(i: 0).getGlobal()->getName() == "_mcount" ) |
181 | emitMCountABI(MI, MBB, MF); |
182 | break; |
183 | case Mips::JALRPseudo: |
184 | case Mips::JALR64Pseudo: |
185 | case Mips::JALR16_MM: |
186 | if (MI.getOperand(i: 2).isMCSymbol() && |
187 | MI.getOperand(i: 2).getMCSymbol()->getName() == "_mcount" ) |
188 | emitMCountABI(MI, MBB, MF); |
189 | break; |
190 | case Mips::JALR: |
191 | if (MI.getOperand(i: 3).isMCSymbol() && |
192 | MI.getOperand(i: 3).getMCSymbol()->getName() == "_mcount" ) |
193 | emitMCountABI(MI, MBB, MF); |
194 | break; |
195 | default: |
196 | replaceUsesWithZeroReg(MRI, MI); |
197 | } |
198 | } |
199 | } |
200 | } |
201 | |
202 | void MipsSEDAGToDAGISel::selectAddE(SDNode *Node, const SDLoc &DL) const { |
203 | SDValue InGlue = Node->getOperand(Num: 2); |
204 | unsigned Opc = InGlue.getOpcode(); |
205 | SDValue LHS = Node->getOperand(Num: 0), RHS = Node->getOperand(Num: 1); |
206 | EVT VT = LHS.getValueType(); |
207 | |
208 | // In the base case, we can rely on the carry bit from the addsc |
209 | // instruction. |
210 | if (Opc == ISD::ADDC) { |
211 | SDValue Ops[3] = {LHS, RHS, InGlue}; |
212 | CurDAG->SelectNodeTo(N: Node, MachineOpc: Mips::ADDWC, VT1: VT, VT2: MVT::Glue, Ops); |
213 | return; |
214 | } |
215 | |
216 | assert(Opc == ISD::ADDE && "ISD::ADDE not in a chain of ADDE nodes!" ); |
217 | |
218 | // The more complex case is when there is a chain of ISD::ADDE nodes like: |
219 | // (adde (adde (adde (addc a b) c) d) e). |
220 | // |
221 | // The addwc instruction does not write to the carry bit, instead it writes |
222 | // to bit 20 of the dsp control register. To match this series of nodes, each |
223 | // intermediate adde node must be expanded to write the carry bit before the |
224 | // addition. |
225 | |
226 | // Start by reading the overflow field for addsc and moving the value to the |
227 | // carry field. The usage of 1 here with MipsISD::RDDSP / Mips::WRDSP |
228 | // corresponds to reading/writing the entire control register to/from a GPR. |
229 | |
230 | SDValue CstOne = CurDAG->getTargetConstant(Val: 1, DL, VT: MVT::i32); |
231 | |
232 | SDValue OuFlag = CurDAG->getTargetConstant(Val: 20, DL, VT: MVT::i32); |
233 | |
234 | SDNode *DSPCtrlField = CurDAG->getMachineNode(Opcode: Mips::RDDSP, dl: DL, VT1: MVT::i32, |
235 | VT2: MVT::Glue, Op1: CstOne, Op2: InGlue); |
236 | |
237 | SDNode *Carry = CurDAG->getMachineNode( |
238 | Opcode: Mips::EXT, dl: DL, VT: MVT::i32, Op1: SDValue(DSPCtrlField, 0), Op2: OuFlag, Op3: CstOne); |
239 | |
240 | SDValue Ops[4] = {SDValue(DSPCtrlField, 0), |
241 | CurDAG->getTargetConstant(Val: 6, DL, VT: MVT::i32), CstOne, |
242 | SDValue(Carry, 0)}; |
243 | SDNode *DSPCFWithCarry = CurDAG->getMachineNode(Opcode: Mips::INS, dl: DL, VT: MVT::i32, Ops); |
244 | |
245 | // My reading of the MIPS DSP 3.01 specification isn't as clear as I |
246 | // would like about whether bit 20 always gets overwritten by addwc. |
247 | // Hence take an extremely conservative view and presume it's sticky. We |
248 | // therefore need to clear it. |
249 | |
250 | SDValue Zero = CurDAG->getRegister(Reg: Mips::ZERO, VT: MVT::i32); |
251 | |
252 | SDValue InsOps[4] = {Zero, OuFlag, CstOne, SDValue(DSPCFWithCarry, 0)}; |
253 | SDNode *DSPCtrlFinal = |
254 | CurDAG->getMachineNode(Opcode: Mips::INS, dl: DL, VT: MVT::i32, Ops: InsOps); |
255 | |
256 | SDNode *WrDSP = CurDAG->getMachineNode(Opcode: Mips::WRDSP, dl: DL, VT: MVT::Glue, |
257 | Op1: SDValue(DSPCtrlFinal, 0), Op2: CstOne); |
258 | |
259 | SDValue Operands[3] = {LHS, RHS, SDValue(WrDSP, 0)}; |
260 | CurDAG->SelectNodeTo(N: Node, MachineOpc: Mips::ADDWC, VT1: VT, VT2: MVT::Glue, Ops: Operands); |
261 | } |
262 | |
263 | /// Match frameindex |
264 | bool MipsSEDAGToDAGISel::selectAddrFrameIndex(SDValue Addr, SDValue &Base, |
265 | SDValue &Offset) const { |
266 | if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Val&: Addr)) { |
267 | EVT ValTy = Addr.getValueType(); |
268 | |
269 | Base = CurDAG->getTargetFrameIndex(FI: FIN->getIndex(), VT: ValTy); |
270 | Offset = CurDAG->getTargetConstant(Val: 0, DL: SDLoc(Addr), VT: ValTy); |
271 | return true; |
272 | } |
273 | return false; |
274 | } |
275 | |
276 | /// Match frameindex+offset and frameindex|offset |
277 | bool MipsSEDAGToDAGISel::selectAddrFrameIndexOffset( |
278 | SDValue Addr, SDValue &Base, SDValue &Offset, unsigned OffsetBits, |
279 | unsigned ShiftAmount = 0) const { |
280 | if (CurDAG->isBaseWithConstantOffset(Op: Addr)) { |
281 | auto *CN = cast<ConstantSDNode>(Val: Addr.getOperand(i: 1)); |
282 | if (isIntN(N: OffsetBits + ShiftAmount, x: CN->getSExtValue())) { |
283 | EVT ValTy = Addr.getValueType(); |
284 | |
285 | // If the first operand is a FI, get the TargetFI Node |
286 | if (FrameIndexSDNode *FIN = |
287 | dyn_cast<FrameIndexSDNode>(Val: Addr.getOperand(i: 0))) |
288 | Base = CurDAG->getTargetFrameIndex(FI: FIN->getIndex(), VT: ValTy); |
289 | else { |
290 | Base = Addr.getOperand(i: 0); |
291 | // If base is a FI, additional offset calculation is done in |
292 | // eliminateFrameIndex, otherwise we need to check the alignment |
293 | const Align Alignment(1ULL << ShiftAmount); |
294 | if (!isAligned(Lhs: Alignment, SizeInBytes: CN->getZExtValue())) |
295 | return false; |
296 | } |
297 | |
298 | Offset = CurDAG->getTargetConstant(Val: CN->getZExtValue(), DL: SDLoc(Addr), |
299 | VT: ValTy); |
300 | return true; |
301 | } |
302 | } |
303 | return false; |
304 | } |
305 | |
306 | /// ComplexPattern used on MipsInstrInfo |
307 | /// Used on Mips Load/Store instructions |
308 | bool MipsSEDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base, |
309 | SDValue &Offset) const { |
310 | // if Address is FI, get the TargetFrameIndex. |
311 | if (selectAddrFrameIndex(Addr, Base, Offset)) |
312 | return true; |
313 | |
314 | // on PIC code Load GA |
315 | if (Addr.getOpcode() == MipsISD::Wrapper) { |
316 | Base = Addr.getOperand(i: 0); |
317 | Offset = Addr.getOperand(i: 1); |
318 | return true; |
319 | } |
320 | |
321 | if (!TM.isPositionIndependent()) { |
322 | if ((Addr.getOpcode() == ISD::TargetExternalSymbol || |
323 | Addr.getOpcode() == ISD::TargetGlobalAddress)) |
324 | return false; |
325 | } |
326 | |
327 | // Addresses of the form FI+const or FI|const |
328 | if (selectAddrFrameIndexOffset(Addr, Base, Offset, OffsetBits: 16)) |
329 | return true; |
330 | |
331 | // Operand is a result from an ADD. |
332 | if (Addr.getOpcode() == ISD::ADD) { |
333 | // When loading from constant pools, load the lower address part in |
334 | // the instruction itself. Example, instead of: |
335 | // lui $2, %hi($CPI1_0) |
336 | // addiu $2, $2, %lo($CPI1_0) |
337 | // lwc1 $f0, 0($2) |
338 | // Generate: |
339 | // lui $2, %hi($CPI1_0) |
340 | // lwc1 $f0, %lo($CPI1_0)($2) |
341 | if (Addr.getOperand(i: 1).getOpcode() == MipsISD::Lo || |
342 | Addr.getOperand(i: 1).getOpcode() == MipsISD::GPRel) { |
343 | SDValue Opnd0 = Addr.getOperand(i: 1).getOperand(i: 0); |
344 | if (isa<ConstantPoolSDNode>(Val: Opnd0) || isa<GlobalAddressSDNode>(Val: Opnd0) || |
345 | isa<JumpTableSDNode>(Val: Opnd0)) { |
346 | Base = Addr.getOperand(i: 0); |
347 | Offset = Opnd0; |
348 | return true; |
349 | } |
350 | } |
351 | } |
352 | |
353 | return false; |
354 | } |
355 | |
356 | /// ComplexPattern used on MipsInstrInfo |
357 | /// Used on Mips Load/Store instructions |
358 | bool MipsSEDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base, |
359 | SDValue &Offset) const { |
360 | Base = Addr; |
361 | Offset = CurDAG->getTargetConstant(Val: 0, DL: SDLoc(Addr), VT: Addr.getValueType()); |
362 | return true; |
363 | } |
364 | |
365 | bool MipsSEDAGToDAGISel::selectIntAddr(SDValue Addr, SDValue &Base, |
366 | SDValue &Offset) const { |
367 | return selectAddrRegImm(Addr, Base, Offset) || |
368 | selectAddrDefault(Addr, Base, Offset); |
369 | } |
370 | |
371 | bool MipsSEDAGToDAGISel::selectAddrRegImm9(SDValue Addr, SDValue &Base, |
372 | SDValue &Offset) const { |
373 | if (selectAddrFrameIndex(Addr, Base, Offset)) |
374 | return true; |
375 | |
376 | if (selectAddrFrameIndexOffset(Addr, Base, Offset, OffsetBits: 9)) |
377 | return true; |
378 | |
379 | return false; |
380 | } |
381 | |
382 | /// Used on microMIPS LWC2, LDC2, SWC2 and SDC2 instructions (11-bit offset) |
383 | bool MipsSEDAGToDAGISel::selectAddrRegImm11(SDValue Addr, SDValue &Base, |
384 | SDValue &Offset) const { |
385 | if (selectAddrFrameIndex(Addr, Base, Offset)) |
386 | return true; |
387 | |
388 | if (selectAddrFrameIndexOffset(Addr, Base, Offset, OffsetBits: 11)) |
389 | return true; |
390 | |
391 | return false; |
392 | } |
393 | |
394 | /// Used on microMIPS Load/Store unaligned instructions (12-bit offset) |
395 | bool MipsSEDAGToDAGISel::selectAddrRegImm12(SDValue Addr, SDValue &Base, |
396 | SDValue &Offset) const { |
397 | if (selectAddrFrameIndex(Addr, Base, Offset)) |
398 | return true; |
399 | |
400 | if (selectAddrFrameIndexOffset(Addr, Base, Offset, OffsetBits: 12)) |
401 | return true; |
402 | |
403 | return false; |
404 | } |
405 | |
406 | bool MipsSEDAGToDAGISel::selectAddrRegImm16(SDValue Addr, SDValue &Base, |
407 | SDValue &Offset) const { |
408 | if (selectAddrFrameIndex(Addr, Base, Offset)) |
409 | return true; |
410 | |
411 | if (selectAddrFrameIndexOffset(Addr, Base, Offset, OffsetBits: 16)) |
412 | return true; |
413 | |
414 | return false; |
415 | } |
416 | |
417 | bool MipsSEDAGToDAGISel::selectIntAddr11MM(SDValue Addr, SDValue &Base, |
418 | SDValue &Offset) const { |
419 | return selectAddrRegImm11(Addr, Base, Offset) || |
420 | selectAddrDefault(Addr, Base, Offset); |
421 | } |
422 | |
423 | bool MipsSEDAGToDAGISel::selectIntAddr12MM(SDValue Addr, SDValue &Base, |
424 | SDValue &Offset) const { |
425 | return selectAddrRegImm12(Addr, Base, Offset) || |
426 | selectAddrDefault(Addr, Base, Offset); |
427 | } |
428 | |
429 | bool MipsSEDAGToDAGISel::selectIntAddr16MM(SDValue Addr, SDValue &Base, |
430 | SDValue &Offset) const { |
431 | return selectAddrRegImm16(Addr, Base, Offset) || |
432 | selectAddrDefault(Addr, Base, Offset); |
433 | } |
434 | |
435 | bool MipsSEDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, |
436 | SDValue &Offset) const { |
437 | if (selectAddrFrameIndexOffset(Addr, Base, Offset, OffsetBits: 7)) { |
438 | if (isa<FrameIndexSDNode>(Val: Base)) |
439 | return false; |
440 | |
441 | if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val&: Offset)) { |
442 | unsigned CnstOff = CN->getZExtValue(); |
443 | return (CnstOff == (CnstOff & 0x3c)); |
444 | } |
445 | |
446 | return false; |
447 | } |
448 | |
449 | // For all other cases where "lw" would be selected, don't select "lw16" |
450 | // because it would result in additional instructions to prepare operands. |
451 | if (selectAddrRegImm(Addr, Base, Offset)) |
452 | return false; |
453 | |
454 | return selectAddrDefault(Addr, Base, Offset); |
455 | } |
456 | |
457 | bool MipsSEDAGToDAGISel::selectIntAddrSImm10(SDValue Addr, SDValue &Base, |
458 | SDValue &Offset) const { |
459 | |
460 | if (selectAddrFrameIndex(Addr, Base, Offset)) |
461 | return true; |
462 | |
463 | if (selectAddrFrameIndexOffset(Addr, Base, Offset, OffsetBits: 10)) |
464 | return true; |
465 | |
466 | return selectAddrDefault(Addr, Base, Offset); |
467 | } |
468 | |
469 | bool MipsSEDAGToDAGISel::selectIntAddrSImm10Lsl1(SDValue Addr, SDValue &Base, |
470 | SDValue &Offset) const { |
471 | if (selectAddrFrameIndex(Addr, Base, Offset)) |
472 | return true; |
473 | |
474 | if (selectAddrFrameIndexOffset(Addr, Base, Offset, OffsetBits: 10, ShiftAmount: 1)) |
475 | return true; |
476 | |
477 | return selectAddrDefault(Addr, Base, Offset); |
478 | } |
479 | |
480 | bool MipsSEDAGToDAGISel::selectIntAddrSImm10Lsl2(SDValue Addr, SDValue &Base, |
481 | SDValue &Offset) const { |
482 | if (selectAddrFrameIndex(Addr, Base, Offset)) |
483 | return true; |
484 | |
485 | if (selectAddrFrameIndexOffset(Addr, Base, Offset, OffsetBits: 10, ShiftAmount: 2)) |
486 | return true; |
487 | |
488 | return selectAddrDefault(Addr, Base, Offset); |
489 | } |
490 | |
491 | bool MipsSEDAGToDAGISel::selectIntAddrSImm10Lsl3(SDValue Addr, SDValue &Base, |
492 | SDValue &Offset) const { |
493 | if (selectAddrFrameIndex(Addr, Base, Offset)) |
494 | return true; |
495 | |
496 | if (selectAddrFrameIndexOffset(Addr, Base, Offset, OffsetBits: 10, ShiftAmount: 3)) |
497 | return true; |
498 | |
499 | return selectAddrDefault(Addr, Base, Offset); |
500 | } |
501 | |
502 | // Select constant vector splats. |
503 | // |
504 | // Returns true and sets Imm if: |
505 | // * MSA is enabled |
506 | // * N is a ISD::BUILD_VECTOR representing a constant splat |
507 | bool MipsSEDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm, |
508 | unsigned MinSizeInBits) const { |
509 | if (!Subtarget->hasMSA()) |
510 | return false; |
511 | |
512 | BuildVectorSDNode *Node = dyn_cast<BuildVectorSDNode>(Val: N); |
513 | |
514 | if (!Node) |
515 | return false; |
516 | |
517 | APInt SplatValue, SplatUndef; |
518 | unsigned SplatBitSize; |
519 | bool HasAnyUndefs; |
520 | |
521 | if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, |
522 | MinSplatBits: MinSizeInBits, isBigEndian: !Subtarget->isLittle())) |
523 | return false; |
524 | |
525 | Imm = SplatValue; |
526 | |
527 | return true; |
528 | } |
529 | |
530 | // Select constant vector splats. |
531 | // |
532 | // In addition to the requirements of selectVSplat(), this function returns |
533 | // true and sets Imm if: |
534 | // * The splat value is the same width as the elements of the vector |
535 | // * The splat value fits in an integer with the specified signed-ness and |
536 | // width. |
537 | // |
538 | // This function looks through ISD::BITCAST nodes. |
539 | // TODO: This might not be appropriate for big-endian MSA since BITCAST is |
540 | // sometimes a shuffle in big-endian mode. |
541 | // |
542 | // It's worth noting that this function is not used as part of the selection |
543 | // of ldi.[bhwd] since it does not permit using the wrong-typed ldi.[bhwd] |
544 | // instruction to achieve the desired bit pattern. ldi.[bhwd] is selected in |
545 | // MipsSEDAGToDAGISel::selectNode. |
546 | bool MipsSEDAGToDAGISel:: |
547 | selectVSplatCommon(SDValue N, SDValue &Imm, bool Signed, |
548 | unsigned ImmBitSize) const { |
549 | APInt ImmValue; |
550 | EVT EltTy = N->getValueType(ResNo: 0).getVectorElementType(); |
551 | |
552 | if (N->getOpcode() == ISD::BITCAST) |
553 | N = N->getOperand(Num: 0); |
554 | |
555 | if (selectVSplat(N: N.getNode(), Imm&: ImmValue, MinSizeInBits: EltTy.getSizeInBits()) && |
556 | ImmValue.getBitWidth() == EltTy.getSizeInBits()) { |
557 | |
558 | if (( Signed && ImmValue.isSignedIntN(N: ImmBitSize)) || |
559 | (!Signed && ImmValue.isIntN(N: ImmBitSize))) { |
560 | Imm = CurDAG->getTargetConstant(Val: ImmValue, DL: SDLoc(N), VT: EltTy); |
561 | return true; |
562 | } |
563 | } |
564 | |
565 | return false; |
566 | } |
567 | |
568 | // Select constant vector splats whose value is a power of 2. |
569 | // |
570 | // In addition to the requirements of selectVSplat(), this function returns |
571 | // true and sets Imm if: |
572 | // * The splat value is the same width as the elements of the vector |
573 | // * The splat value is a power of two. |
574 | // |
575 | // This function looks through ISD::BITCAST nodes. |
576 | // TODO: This might not be appropriate for big-endian MSA since BITCAST is |
577 | // sometimes a shuffle in big-endian mode. |
578 | bool MipsSEDAGToDAGISel::selectVSplatUimmPow2(SDValue N, SDValue &Imm) const { |
579 | APInt ImmValue; |
580 | EVT EltTy = N->getValueType(ResNo: 0).getVectorElementType(); |
581 | |
582 | if (N->getOpcode() == ISD::BITCAST) |
583 | N = N->getOperand(Num: 0); |
584 | |
585 | if (selectVSplat(N: N.getNode(), Imm&: ImmValue, MinSizeInBits: EltTy.getSizeInBits()) && |
586 | ImmValue.getBitWidth() == EltTy.getSizeInBits()) { |
587 | int32_t Log2 = ImmValue.exactLogBase2(); |
588 | |
589 | if (Log2 != -1) { |
590 | Imm = CurDAG->getTargetConstant(Val: Log2, DL: SDLoc(N), VT: EltTy); |
591 | return true; |
592 | } |
593 | } |
594 | |
595 | return false; |
596 | } |
597 | |
598 | // Select constant vector splats whose value only has a consecutive sequence |
599 | // of left-most bits set (e.g. 0b11...1100...00). |
600 | // |
601 | // In addition to the requirements of selectVSplat(), this function returns |
602 | // true and sets Imm if: |
603 | // * The splat value is the same width as the elements of the vector |
604 | // * The splat value is a consecutive sequence of left-most bits. |
605 | // |
606 | // This function looks through ISD::BITCAST nodes. |
607 | // TODO: This might not be appropriate for big-endian MSA since BITCAST is |
608 | // sometimes a shuffle in big-endian mode. |
609 | bool MipsSEDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const { |
610 | APInt ImmValue; |
611 | EVT EltTy = N->getValueType(ResNo: 0).getVectorElementType(); |
612 | |
613 | if (N->getOpcode() == ISD::BITCAST) |
614 | N = N->getOperand(Num: 0); |
615 | |
616 | if (selectVSplat(N: N.getNode(), Imm&: ImmValue, MinSizeInBits: EltTy.getSizeInBits()) && |
617 | ImmValue.getBitWidth() == EltTy.getSizeInBits()) { |
618 | // Check if we have a leading one, then check if the whole value is a |
619 | // shifted mask. |
620 | if (ImmValue.isNegative() && ImmValue.isShiftedMask()) { |
621 | Imm = CurDAG->getTargetConstant(Val: ImmValue.popcount() - 1, DL: SDLoc(N), VT: EltTy); |
622 | return true; |
623 | } |
624 | } |
625 | |
626 | return false; |
627 | } |
628 | |
629 | // Select constant vector splats whose value only has a consecutive sequence |
630 | // of right-most bits set (e.g. 0b00...0011...11). |
631 | // |
632 | // In addition to the requirements of selectVSplat(), this function returns |
633 | // true and sets Imm if: |
634 | // * The splat value is the same width as the elements of the vector |
635 | // * The splat value is a consecutive sequence of right-most bits. |
636 | // |
637 | // This function looks through ISD::BITCAST nodes. |
638 | // TODO: This might not be appropriate for big-endian MSA since BITCAST is |
639 | // sometimes a shuffle in big-endian mode. |
640 | bool MipsSEDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const { |
641 | APInt ImmValue; |
642 | EVT EltTy = N->getValueType(ResNo: 0).getVectorElementType(); |
643 | |
644 | if (N->getOpcode() == ISD::BITCAST) |
645 | N = N->getOperand(Num: 0); |
646 | |
647 | if (selectVSplat(N: N.getNode(), Imm&: ImmValue, MinSizeInBits: EltTy.getSizeInBits()) && |
648 | ImmValue.getBitWidth() == EltTy.getSizeInBits()) { |
649 | if (ImmValue.isMask()) { |
650 | Imm = CurDAG->getTargetConstant(Val: ImmValue.popcount() - 1, DL: SDLoc(N), VT: EltTy); |
651 | return true; |
652 | } |
653 | } |
654 | |
655 | return false; |
656 | } |
657 | |
658 | bool MipsSEDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N, |
659 | SDValue &Imm) const { |
660 | APInt ImmValue; |
661 | EVT EltTy = N->getValueType(ResNo: 0).getVectorElementType(); |
662 | |
663 | if (N->getOpcode() == ISD::BITCAST) |
664 | N = N->getOperand(Num: 0); |
665 | |
666 | if (selectVSplat(N: N.getNode(), Imm&: ImmValue, MinSizeInBits: EltTy.getSizeInBits()) && |
667 | ImmValue.getBitWidth() == EltTy.getSizeInBits()) { |
668 | int32_t Log2 = (~ImmValue).exactLogBase2(); |
669 | |
670 | if (Log2 != -1) { |
671 | Imm = CurDAG->getTargetConstant(Val: Log2, DL: SDLoc(N), VT: EltTy); |
672 | return true; |
673 | } |
674 | } |
675 | |
676 | return false; |
677 | } |
678 | |
679 | // Select const vector splat of 1. |
680 | bool MipsSEDAGToDAGISel::selectVSplatImmEq1(SDValue N) const { |
681 | APInt ImmValue; |
682 | EVT EltTy = N->getValueType(ResNo: 0).getVectorElementType(); |
683 | |
684 | if (N->getOpcode() == ISD::BITCAST) |
685 | N = N->getOperand(Num: 0); |
686 | |
687 | return selectVSplat(N: N.getNode(), Imm&: ImmValue, MinSizeInBits: EltTy.getSizeInBits()) && |
688 | ImmValue.getBitWidth() == EltTy.getSizeInBits() && ImmValue == 1; |
689 | } |
690 | |
691 | bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) { |
692 | unsigned Opcode = Node->getOpcode(); |
693 | SDLoc DL(Node); |
694 | |
695 | /// |
696 | // Instruction Selection not handled by the auto-generated |
697 | // tablegen selection should be handled here. |
698 | /// |
699 | switch(Opcode) { |
700 | default: break; |
701 | |
702 | case MipsISD::DOUBLE_SELECT_I: |
703 | case MipsISD::DOUBLE_SELECT_I64: { |
704 | MVT VT = Subtarget->isGP64bit() ? MVT::i64 : MVT::i32; |
705 | SDValue cond = Node->getOperand(Num: 0); |
706 | SDValue Hi1 = Node->getOperand(Num: 1); |
707 | SDValue Lo1 = Node->getOperand(Num: 2); |
708 | SDValue Hi2 = Node->getOperand(Num: 3); |
709 | SDValue Lo2 = Node->getOperand(Num: 4); |
710 | |
711 | SDValue ops[] = {cond, Hi1, Lo1, Hi2, Lo2}; |
712 | EVT NodeTys[] = {VT, VT}; |
713 | ReplaceNode(F: Node, T: CurDAG->getMachineNode(Opcode: Subtarget->isGP64bit() |
714 | ? Mips::PseudoD_SELECT_I64 |
715 | : Mips::PseudoD_SELECT_I, |
716 | dl: DL, ResultTys: NodeTys, Ops: ops)); |
717 | return true; |
718 | } |
719 | |
720 | case ISD::ADDE: { |
721 | selectAddE(Node, DL); |
722 | return true; |
723 | } |
724 | |
725 | case ISD::ConstantFP: { |
726 | auto *CN = cast<ConstantFPSDNode>(Val: Node); |
727 | if (Node->getValueType(ResNo: 0) == MVT::f64 && CN->isExactlyValue(V: +0.0)) { |
728 | if (Subtarget->isGP64bit()) { |
729 | SDValue Zero = CurDAG->getCopyFromReg(Chain: CurDAG->getEntryNode(), dl: DL, |
730 | Reg: Mips::ZERO_64, VT: MVT::i64); |
731 | ReplaceNode(F: Node, |
732 | T: CurDAG->getMachineNode(Opcode: Mips::DMTC1, dl: DL, VT: MVT::f64, Op1: Zero)); |
733 | } else if (Subtarget->isFP64bit()) { |
734 | SDValue Zero = CurDAG->getCopyFromReg(Chain: CurDAG->getEntryNode(), dl: DL, |
735 | Reg: Mips::ZERO, VT: MVT::i32); |
736 | ReplaceNode(F: Node, T: CurDAG->getMachineNode(Opcode: Mips::BuildPairF64_64, dl: DL, |
737 | VT: MVT::f64, Op1: Zero, Op2: Zero)); |
738 | } else { |
739 | SDValue Zero = CurDAG->getCopyFromReg(Chain: CurDAG->getEntryNode(), dl: DL, |
740 | Reg: Mips::ZERO, VT: MVT::i32); |
741 | ReplaceNode(F: Node, T: CurDAG->getMachineNode(Opcode: Mips::BuildPairF64, dl: DL, |
742 | VT: MVT::f64, Op1: Zero, Op2: Zero)); |
743 | } |
744 | return true; |
745 | } |
746 | break; |
747 | } |
748 | |
749 | case ISD::Constant: { |
750 | auto *CN = cast<ConstantSDNode>(Val: Node); |
751 | int64_t Imm = CN->getSExtValue(); |
752 | unsigned Size = CN->getValueSizeInBits(ResNo: 0); |
753 | |
754 | if (isInt<32>(x: Imm)) |
755 | break; |
756 | |
757 | MipsAnalyzeImmediate AnalyzeImm; |
758 | |
759 | const MipsAnalyzeImmediate::InstSeq &Seq = |
760 | AnalyzeImm.Analyze(Imm, Size, LastInstrIsADDiu: false); |
761 | |
762 | MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin(); |
763 | SDLoc DL(CN); |
764 | SDNode *RegOpnd; |
765 | SDValue ImmOpnd = CurDAG->getTargetConstant(Val: SignExtend64<16>(x: Inst->ImmOpnd), |
766 | DL, VT: MVT::i64); |
767 | |
768 | // The first instruction can be a LUi which is different from other |
769 | // instructions (ADDiu, ORI and SLL) in that it does not have a register |
770 | // operand. |
771 | if (Inst->Opc == Mips::LUi64) |
772 | RegOpnd = CurDAG->getMachineNode(Opcode: Inst->Opc, dl: DL, VT: MVT::i64, Op1: ImmOpnd); |
773 | else |
774 | RegOpnd = |
775 | CurDAG->getMachineNode(Opcode: Inst->Opc, dl: DL, VT: MVT::i64, |
776 | Op1: CurDAG->getRegister(Reg: Mips::ZERO_64, VT: MVT::i64), |
777 | Op2: ImmOpnd); |
778 | |
779 | // The remaining instructions in the sequence are handled here. |
780 | for (++Inst; Inst != Seq.end(); ++Inst) { |
781 | ImmOpnd = CurDAG->getTargetConstant(Val: SignExtend64<16>(x: Inst->ImmOpnd), DL, |
782 | VT: MVT::i64); |
783 | RegOpnd = CurDAG->getMachineNode(Opcode: Inst->Opc, dl: DL, VT: MVT::i64, |
784 | Op1: SDValue(RegOpnd, 0), Op2: ImmOpnd); |
785 | } |
786 | |
787 | ReplaceNode(F: Node, T: RegOpnd); |
788 | return true; |
789 | } |
790 | |
791 | case ISD::INTRINSIC_W_CHAIN: { |
792 | const unsigned IntrinsicOpcode = Node->getConstantOperandVal(Num: 1); |
793 | switch (IntrinsicOpcode) { |
794 | default: |
795 | break; |
796 | |
797 | case Intrinsic::mips_cfcmsa: { |
798 | SDValue ChainIn = Node->getOperand(Num: 0); |
799 | SDValue RegIdx = Node->getOperand(Num: 2); |
800 | SDValue Reg = CurDAG->getCopyFromReg(Chain: ChainIn, dl: DL, |
801 | Reg: getMSACtrlReg(RegIdx), VT: MVT::i32); |
802 | ReplaceNode(F: Node, T: Reg.getNode()); |
803 | return true; |
804 | } |
805 | case Intrinsic::mips_ldr_d: |
806 | case Intrinsic::mips_ldr_w: { |
807 | unsigned Op = (IntrinsicOpcode == Intrinsic::mips_ldr_d) ? Mips::LDR_D |
808 | : Mips::LDR_W; |
809 | |
810 | SDLoc DL(Node); |
811 | assert(Node->getNumOperands() == 4 && "Unexpected number of operands." ); |
812 | const SDValue &Chain = Node->getOperand(Num: 0); |
813 | const SDValue &Intrinsic = Node->getOperand(Num: 1); |
814 | const SDValue &Pointer = Node->getOperand(Num: 2); |
815 | const SDValue &Constant = Node->getOperand(Num: 3); |
816 | |
817 | assert(Chain.getValueType() == MVT::Other); |
818 | (void)Intrinsic; |
819 | assert(Intrinsic.getOpcode() == ISD::TargetConstant && |
820 | Constant.getOpcode() == ISD::Constant && |
821 | "Invalid instruction operand." ); |
822 | |
823 | // Convert Constant to TargetConstant. |
824 | const ConstantInt *Val = |
825 | cast<ConstantSDNode>(Val: Constant)->getConstantIntValue(); |
826 | SDValue Imm = |
827 | CurDAG->getTargetConstant(Val: *Val, DL, VT: Constant.getValueType()); |
828 | |
829 | SmallVector<SDValue, 3> Ops{Pointer, Imm, Chain}; |
830 | |
831 | assert(Node->getNumValues() == 2); |
832 | assert(Node->getValueType(0).is128BitVector()); |
833 | assert(Node->getValueType(1) == MVT::Other); |
834 | SmallVector<EVT, 2> ResTys{Node->getValueType(ResNo: 0), Node->getValueType(ResNo: 1)}; |
835 | |
836 | ReplaceNode(F: Node, T: CurDAG->getMachineNode(Opcode: Op, dl: DL, ResultTys: ResTys, Ops)); |
837 | |
838 | return true; |
839 | } |
840 | } |
841 | break; |
842 | } |
843 | |
844 | case ISD::INTRINSIC_WO_CHAIN: { |
845 | switch (Node->getConstantOperandVal(Num: 0)) { |
846 | default: |
847 | break; |
848 | |
849 | case Intrinsic::mips_move_v: |
850 | // Like an assignment but will always produce a move.v even if |
851 | // unnecessary. |
852 | ReplaceNode(F: Node, T: CurDAG->getMachineNode(Opcode: Mips::MOVE_V, dl: DL, |
853 | VT: Node->getValueType(ResNo: 0), |
854 | Op1: Node->getOperand(Num: 1))); |
855 | return true; |
856 | } |
857 | break; |
858 | } |
859 | |
860 | case ISD::INTRINSIC_VOID: { |
861 | const unsigned IntrinsicOpcode = Node->getConstantOperandVal(Num: 1); |
862 | switch (IntrinsicOpcode) { |
863 | default: |
864 | break; |
865 | |
866 | case Intrinsic::mips_ctcmsa: { |
867 | SDValue ChainIn = Node->getOperand(Num: 0); |
868 | SDValue RegIdx = Node->getOperand(Num: 2); |
869 | SDValue Value = Node->getOperand(Num: 3); |
870 | SDValue ChainOut = CurDAG->getCopyToReg(Chain: ChainIn, dl: DL, |
871 | Reg: getMSACtrlReg(RegIdx), N: Value); |
872 | ReplaceNode(F: Node, T: ChainOut.getNode()); |
873 | return true; |
874 | } |
875 | case Intrinsic::mips_str_d: |
876 | case Intrinsic::mips_str_w: { |
877 | unsigned Op = (IntrinsicOpcode == Intrinsic::mips_str_d) ? Mips::STR_D |
878 | : Mips::STR_W; |
879 | |
880 | SDLoc DL(Node); |
881 | assert(Node->getNumOperands() == 5 && "Unexpected number of operands." ); |
882 | const SDValue &Chain = Node->getOperand(Num: 0); |
883 | const SDValue &Intrinsic = Node->getOperand(Num: 1); |
884 | const SDValue &Vec = Node->getOperand(Num: 2); |
885 | const SDValue &Pointer = Node->getOperand(Num: 3); |
886 | const SDValue &Constant = Node->getOperand(Num: 4); |
887 | |
888 | assert(Chain.getValueType() == MVT::Other); |
889 | (void)Intrinsic; |
890 | assert(Intrinsic.getOpcode() == ISD::TargetConstant && |
891 | Constant.getOpcode() == ISD::Constant && |
892 | "Invalid instruction operand." ); |
893 | |
894 | // Convert Constant to TargetConstant. |
895 | const ConstantInt *Val = |
896 | cast<ConstantSDNode>(Val: Constant)->getConstantIntValue(); |
897 | SDValue Imm = |
898 | CurDAG->getTargetConstant(Val: *Val, DL, VT: Constant.getValueType()); |
899 | |
900 | SmallVector<SDValue, 4> Ops{Vec, Pointer, Imm, Chain}; |
901 | |
902 | assert(Node->getNumValues() == 1); |
903 | assert(Node->getValueType(0) == MVT::Other); |
904 | SmallVector<EVT, 1> ResTys{Node->getValueType(ResNo: 0)}; |
905 | |
906 | ReplaceNode(F: Node, T: CurDAG->getMachineNode(Opcode: Op, dl: DL, ResultTys: ResTys, Ops)); |
907 | return true; |
908 | } |
909 | } |
910 | break; |
911 | } |
912 | |
913 | case MipsISD::FAbs: { |
914 | MVT ResTy = Node->getSimpleValueType(ResNo: 0); |
915 | assert((ResTy == MVT::f64 || ResTy == MVT::f32) && |
916 | "Unsupported float type!" ); |
917 | unsigned Opc = 0; |
918 | if (ResTy == MVT::f64) |
919 | Opc = (Subtarget->isFP64bit() ? Mips::FABS_D64 : Mips::FABS_D32); |
920 | else |
921 | Opc = Mips::FABS_S; |
922 | |
923 | if (Subtarget->inMicroMipsMode()) { |
924 | switch (Opc) { |
925 | case Mips::FABS_D64: |
926 | Opc = Mips::FABS_D64_MM; |
927 | break; |
928 | case Mips::FABS_D32: |
929 | Opc = Mips::FABS_D32_MM; |
930 | break; |
931 | case Mips::FABS_S: |
932 | Opc = Mips::FABS_S_MM; |
933 | break; |
934 | default: |
935 | llvm_unreachable("Unknown opcode for MIPS floating point abs!" ); |
936 | } |
937 | } |
938 | |
939 | ReplaceNode(F: Node, |
940 | T: CurDAG->getMachineNode(Opcode: Opc, dl: DL, VT: ResTy, Op1: Node->getOperand(Num: 0))); |
941 | |
942 | return true; |
943 | } |
944 | |
945 | // Manually match MipsISD::Ins nodes to get the correct instruction. It has |
946 | // to be done in this fashion so that we respect the differences between |
947 | // dins and dinsm, as the difference is that the size operand has the range |
948 | // 0 < size <= 32 for dins while dinsm has the range 2 <= size <= 64 which |
949 | // means SelectionDAGISel would have to test all the operands at once to |
950 | // match the instruction. |
951 | case MipsISD::Ins: { |
952 | |
953 | // Validating the node operands. |
954 | if (Node->getValueType(ResNo: 0) != MVT::i32 && Node->getValueType(ResNo: 0) != MVT::i64) |
955 | return false; |
956 | |
957 | if (Node->getNumOperands() != 4) |
958 | return false; |
959 | |
960 | if (Node->getOperand(Num: 1)->getOpcode() != ISD::Constant || |
961 | Node->getOperand(Num: 2)->getOpcode() != ISD::Constant) |
962 | return false; |
963 | |
964 | MVT ResTy = Node->getSimpleValueType(ResNo: 0); |
965 | uint64_t Pos = Node->getConstantOperandVal(Num: 1); |
966 | uint64_t Size = Node->getConstantOperandVal(Num: 2); |
967 | |
968 | // Size has to be >0 for 'ins', 'dins' and 'dinsu'. |
969 | if (!Size) |
970 | return false; |
971 | |
972 | if (Pos + Size > 64) |
973 | return false; |
974 | |
975 | if (ResTy != MVT::i32 && ResTy != MVT::i64) |
976 | return false; |
977 | |
978 | unsigned Opcode = 0; |
979 | if (ResTy == MVT::i32) { |
980 | if (Pos + Size <= 32) |
981 | Opcode = Mips::INS; |
982 | } else { |
983 | if (Pos + Size <= 32) |
984 | Opcode = Mips::DINS; |
985 | else if (Pos < 32 && 1 < Size) |
986 | Opcode = Mips::DINSM; |
987 | else |
988 | Opcode = Mips::DINSU; |
989 | } |
990 | |
991 | if (Opcode) { |
992 | SDValue Ops[4] = { |
993 | Node->getOperand(Num: 0), CurDAG->getTargetConstant(Val: Pos, DL, VT: MVT::i32), |
994 | CurDAG->getTargetConstant(Val: Size, DL, VT: MVT::i32), Node->getOperand(Num: 3)}; |
995 | |
996 | ReplaceNode(F: Node, T: CurDAG->getMachineNode(Opcode, dl: DL, VT: ResTy, Ops)); |
997 | return true; |
998 | } |
999 | |
1000 | return false; |
1001 | } |
1002 | |
1003 | case MipsISD::ThreadPointer: { |
1004 | EVT PtrVT = getTargetLowering()->getPointerTy(DL: CurDAG->getDataLayout()); |
1005 | unsigned RdhwrOpc, DestReg; |
1006 | |
1007 | if (PtrVT == MVT::i32) { |
1008 | RdhwrOpc = Mips::RDHWR; |
1009 | DestReg = Mips::V1; |
1010 | } else { |
1011 | RdhwrOpc = Mips::RDHWR64; |
1012 | DestReg = Mips::V1_64; |
1013 | } |
1014 | |
1015 | SDNode *Rdhwr = |
1016 | CurDAG->getMachineNode(Opcode: RdhwrOpc, dl: DL, VT1: Node->getValueType(ResNo: 0), VT2: MVT::Glue, |
1017 | Op1: CurDAG->getRegister(Reg: Mips::HWR29, VT: MVT::i32), |
1018 | Op2: CurDAG->getTargetConstant(Val: 0, DL, VT: MVT::i32)); |
1019 | SDValue Chain = CurDAG->getCopyToReg(Chain: CurDAG->getEntryNode(), dl: DL, Reg: DestReg, |
1020 | N: SDValue(Rdhwr, 0), Glue: SDValue(Rdhwr, 1)); |
1021 | SDValue ResNode = CurDAG->getCopyFromReg(Chain, dl: DL, Reg: DestReg, VT: PtrVT, |
1022 | Glue: Chain.getValue(R: 1)); |
1023 | ReplaceNode(F: Node, T: ResNode.getNode()); |
1024 | return true; |
1025 | } |
1026 | |
1027 | case ISD::BUILD_VECTOR: { |
1028 | // Select appropriate ldi.[bhwd] instructions for constant splats of |
1029 | // 128-bit when MSA is enabled. Fixup any register class mismatches that |
1030 | // occur as a result. |
1031 | // |
1032 | // This allows the compiler to use a wider range of immediates than would |
1033 | // otherwise be allowed. If, for example, v4i32 could only use ldi.h then |
1034 | // it would not be possible to load { 0x01010101, 0x01010101, 0x01010101, |
1035 | // 0x01010101 } without using a constant pool. This would be sub-optimal |
1036 | // when // 'ldi.b wd, 1' is capable of producing that bit-pattern in the |
1037 | // same set/ of registers. Similarly, ldi.h isn't capable of producing { |
1038 | // 0x00000000, 0x00000001, 0x00000000, 0x00000001 } but 'ldi.d wd, 1' can. |
1039 | |
1040 | const MipsABIInfo &ABI = |
1041 | static_cast<const MipsTargetMachine &>(TM).getABI(); |
1042 | |
1043 | BuildVectorSDNode *BVN = cast<BuildVectorSDNode>(Val: Node); |
1044 | APInt SplatValue, SplatUndef; |
1045 | unsigned SplatBitSize; |
1046 | bool HasAnyUndefs; |
1047 | unsigned LdiOp; |
1048 | EVT ResVecTy = BVN->getValueType(ResNo: 0); |
1049 | EVT ViaVecTy; |
1050 | |
1051 | if (!Subtarget->hasMSA() || !BVN->getValueType(ResNo: 0).is128BitVector()) |
1052 | return false; |
1053 | |
1054 | if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, |
1055 | HasAnyUndefs, MinSplatBits: 8, |
1056 | isBigEndian: !Subtarget->isLittle())) |
1057 | return false; |
1058 | |
1059 | switch (SplatBitSize) { |
1060 | default: |
1061 | return false; |
1062 | case 8: |
1063 | LdiOp = Mips::LDI_B; |
1064 | ViaVecTy = MVT::v16i8; |
1065 | break; |
1066 | case 16: |
1067 | LdiOp = Mips::LDI_H; |
1068 | ViaVecTy = MVT::v8i16; |
1069 | break; |
1070 | case 32: |
1071 | LdiOp = Mips::LDI_W; |
1072 | ViaVecTy = MVT::v4i32; |
1073 | break; |
1074 | case 64: |
1075 | LdiOp = Mips::LDI_D; |
1076 | ViaVecTy = MVT::v2i64; |
1077 | break; |
1078 | } |
1079 | |
1080 | SDNode *Res = nullptr; |
1081 | |
1082 | // If we have a signed 10 bit integer, we can splat it directly. |
1083 | // |
1084 | // If we have something bigger we can synthesize the value into a GPR and |
1085 | // splat from there. |
1086 | if (SplatValue.isSignedIntN(N: 10)) { |
1087 | SDValue Imm = CurDAG->getTargetConstant(Val: SplatValue, DL, |
1088 | VT: ViaVecTy.getVectorElementType()); |
1089 | |
1090 | Res = CurDAG->getMachineNode(Opcode: LdiOp, dl: DL, VT: ViaVecTy, Op1: Imm); |
1091 | } else if (SplatValue.isSignedIntN(N: 16) && |
1092 | ((ABI.IsO32() && SplatBitSize < 64) || |
1093 | (ABI.IsN32() || ABI.IsN64()))) { |
1094 | // Only handle signed 16 bit values when the element size is GPR width. |
1095 | // MIPS64 can handle all the cases but MIPS32 would need to handle |
1096 | // negative cases specifically here. Instead, handle those cases as |
1097 | // 64bit values. |
1098 | |
1099 | bool Is32BitSplat = ABI.IsO32() || SplatBitSize < 64; |
1100 | const unsigned ADDiuOp = Is32BitSplat ? Mips::ADDiu : Mips::DADDiu; |
1101 | const MVT SplatMVT = Is32BitSplat ? MVT::i32 : MVT::i64; |
1102 | SDValue ZeroVal = CurDAG->getRegister( |
1103 | Reg: Is32BitSplat ? Mips::ZERO : Mips::ZERO_64, VT: SplatMVT); |
1104 | |
1105 | const unsigned FILLOp = |
1106 | SplatBitSize == 16 |
1107 | ? Mips::FILL_H |
1108 | : (SplatBitSize == 32 ? Mips::FILL_W |
1109 | : (SplatBitSize == 64 ? Mips::FILL_D : 0)); |
1110 | |
1111 | assert(FILLOp != 0 && "Unknown FILL Op for splat synthesis!" ); |
1112 | assert((!ABI.IsO32() || (FILLOp != Mips::FILL_D)) && |
1113 | "Attempting to use fill.d on MIPS32!" ); |
1114 | |
1115 | const unsigned Lo = SplatValue.getLoBits(numBits: 16).getZExtValue(); |
1116 | SDValue LoVal = CurDAG->getTargetConstant(Val: Lo, DL, VT: SplatMVT); |
1117 | |
1118 | Res = CurDAG->getMachineNode(Opcode: ADDiuOp, dl: DL, VT: SplatMVT, Op1: ZeroVal, Op2: LoVal); |
1119 | Res = CurDAG->getMachineNode(Opcode: FILLOp, dl: DL, VT: ViaVecTy, Op1: SDValue(Res, 0)); |
1120 | |
1121 | } else if (SplatValue.isSignedIntN(N: 32) && SplatBitSize == 32) { |
1122 | // Only handle the cases where the splat size agrees with the size |
1123 | // of the SplatValue here. |
1124 | const unsigned Lo = SplatValue.getLoBits(numBits: 16).getZExtValue(); |
1125 | const unsigned Hi = SplatValue.lshr(shiftAmt: 16).getLoBits(numBits: 16).getZExtValue(); |
1126 | SDValue ZeroVal = CurDAG->getRegister(Reg: Mips::ZERO, VT: MVT::i32); |
1127 | |
1128 | SDValue LoVal = CurDAG->getTargetConstant(Val: Lo, DL, VT: MVT::i32); |
1129 | SDValue HiVal = CurDAG->getTargetConstant(Val: Hi, DL, VT: MVT::i32); |
1130 | |
1131 | if (Hi) |
1132 | Res = CurDAG->getMachineNode(Opcode: Mips::LUi, dl: DL, VT: MVT::i32, Op1: HiVal); |
1133 | |
1134 | if (Lo) |
1135 | Res = CurDAG->getMachineNode(Opcode: Mips::ORi, dl: DL, VT: MVT::i32, |
1136 | Op1: Hi ? SDValue(Res, 0) : ZeroVal, Op2: LoVal); |
1137 | |
1138 | assert((Hi || Lo) && "Zero case reached 32 bit case splat synthesis!" ); |
1139 | Res = |
1140 | CurDAG->getMachineNode(Opcode: Mips::FILL_W, dl: DL, VT: MVT::v4i32, Op1: SDValue(Res, 0)); |
1141 | |
1142 | } else if (SplatValue.isSignedIntN(N: 32) && SplatBitSize == 64 && |
1143 | (ABI.IsN32() || ABI.IsN64())) { |
1144 | // N32 and N64 can perform some tricks that O32 can't for signed 32 bit |
1145 | // integers due to having 64bit registers. lui will cause the necessary |
1146 | // zero/sign extension. |
1147 | const unsigned Lo = SplatValue.getLoBits(numBits: 16).getZExtValue(); |
1148 | const unsigned Hi = SplatValue.lshr(shiftAmt: 16).getLoBits(numBits: 16).getZExtValue(); |
1149 | SDValue ZeroVal = CurDAG->getRegister(Reg: Mips::ZERO, VT: MVT::i32); |
1150 | |
1151 | SDValue LoVal = CurDAG->getTargetConstant(Val: Lo, DL, VT: MVT::i32); |
1152 | SDValue HiVal = CurDAG->getTargetConstant(Val: Hi, DL, VT: MVT::i32); |
1153 | |
1154 | if (Hi) |
1155 | Res = CurDAG->getMachineNode(Opcode: Mips::LUi, dl: DL, VT: MVT::i32, Op1: HiVal); |
1156 | |
1157 | if (Lo) |
1158 | Res = CurDAG->getMachineNode(Opcode: Mips::ORi, dl: DL, VT: MVT::i32, |
1159 | Op1: Hi ? SDValue(Res, 0) : ZeroVal, Op2: LoVal); |
1160 | |
1161 | Res = CurDAG->getMachineNode( |
1162 | Opcode: Mips::SUBREG_TO_REG, dl: DL, VT: MVT::i64, |
1163 | Op1: CurDAG->getTargetConstant(Val: ((Hi >> 15) & 0x1), DL, VT: MVT::i64), |
1164 | Op2: SDValue(Res, 0), |
1165 | Op3: CurDAG->getTargetConstant(Val: Mips::sub_32, DL, VT: MVT::i64)); |
1166 | |
1167 | Res = |
1168 | CurDAG->getMachineNode(Opcode: Mips::FILL_D, dl: DL, VT: MVT::v2i64, Op1: SDValue(Res, 0)); |
1169 | |
1170 | } else if (SplatValue.isSignedIntN(N: 64)) { |
1171 | // If we have a 64 bit Splat value, we perform a similar sequence to the |
1172 | // above: |
1173 | // |
1174 | // MIPS32: MIPS64: |
1175 | // lui $res, %highest(val) lui $res, %highest(val) |
1176 | // ori $res, $res, %higher(val) ori $res, $res, %higher(val) |
1177 | // lui $res2, %hi(val) lui $res2, %hi(val) |
1178 | // ori $res2, %res2, %lo(val) ori $res2, %res2, %lo(val) |
1179 | // $res3 = fill $res2 dinsu $res, $res2, 0, 32 |
1180 | // $res4 = insert.w $res3[1], $res fill.d $res |
1181 | // splat.d $res4, 0 |
1182 | // |
1183 | // The ability to use dinsu is guaranteed as MSA requires MIPSR5. |
1184 | // This saves having to materialize the value by shifts and ors. |
1185 | // |
1186 | // FIXME: Implement the preferred sequence for MIPS64R6: |
1187 | // |
1188 | // MIPS64R6: |
1189 | // ori $res, $zero, %lo(val) |
1190 | // daui $res, $res, %hi(val) |
1191 | // dahi $res, $res, %higher(val) |
1192 | // dati $res, $res, %highest(cal) |
1193 | // fill.d $res |
1194 | // |
1195 | |
1196 | const unsigned Lo = SplatValue.getLoBits(numBits: 16).getZExtValue(); |
1197 | const unsigned Hi = SplatValue.lshr(shiftAmt: 16).getLoBits(numBits: 16).getZExtValue(); |
1198 | const unsigned Higher = SplatValue.lshr(shiftAmt: 32).getLoBits(numBits: 16).getZExtValue(); |
1199 | const unsigned Highest = SplatValue.lshr(shiftAmt: 48).getLoBits(numBits: 16).getZExtValue(); |
1200 | |
1201 | SDValue LoVal = CurDAG->getTargetConstant(Val: Lo, DL, VT: MVT::i32); |
1202 | SDValue HiVal = CurDAG->getTargetConstant(Val: Hi, DL, VT: MVT::i32); |
1203 | SDValue HigherVal = CurDAG->getTargetConstant(Val: Higher, DL, VT: MVT::i32); |
1204 | SDValue HighestVal = CurDAG->getTargetConstant(Val: Highest, DL, VT: MVT::i32); |
1205 | SDValue ZeroVal = CurDAG->getRegister(Reg: Mips::ZERO, VT: MVT::i32); |
1206 | |
1207 | // Independent of whether we're targeting MIPS64 or not, the basic |
1208 | // operations are the same. Also, directly use the $zero register if |
1209 | // the 16 bit chunk is zero. |
1210 | // |
1211 | // For optimization purposes we always synthesize the splat value as |
1212 | // an i32 value, then if we're targetting MIPS64, use SUBREG_TO_REG |
1213 | // just before combining the values with dinsu to produce an i64. This |
1214 | // enables SelectionDAG to aggressively share components of splat values |
1215 | // where possible. |
1216 | // |
1217 | // FIXME: This is the general constant synthesis problem. This code |
1218 | // should be factored out into a class shared between all the |
1219 | // classes that need it. Specifically, for a splat size of 64 |
1220 | // bits that's a negative number we can do better than LUi/ORi |
1221 | // for the upper 32bits. |
1222 | |
1223 | if (Hi) |
1224 | Res = CurDAG->getMachineNode(Opcode: Mips::LUi, dl: DL, VT: MVT::i32, Op1: HiVal); |
1225 | |
1226 | if (Lo) |
1227 | Res = CurDAG->getMachineNode(Opcode: Mips::ORi, dl: DL, VT: MVT::i32, |
1228 | Op1: Hi ? SDValue(Res, 0) : ZeroVal, Op2: LoVal); |
1229 | |
1230 | SDNode *HiRes; |
1231 | if (Highest) |
1232 | HiRes = CurDAG->getMachineNode(Opcode: Mips::LUi, dl: DL, VT: MVT::i32, Op1: HighestVal); |
1233 | |
1234 | if (Higher) |
1235 | HiRes = CurDAG->getMachineNode(Opcode: Mips::ORi, dl: DL, VT: MVT::i32, |
1236 | Op1: Highest ? SDValue(HiRes, 0) : ZeroVal, |
1237 | Op2: HigherVal); |
1238 | |
1239 | |
1240 | if (ABI.IsO32()) { |
1241 | Res = CurDAG->getMachineNode(Opcode: Mips::FILL_W, dl: DL, VT: MVT::v4i32, |
1242 | Op1: (Hi || Lo) ? SDValue(Res, 0) : ZeroVal); |
1243 | |
1244 | Res = CurDAG->getMachineNode( |
1245 | Opcode: Mips::INSERT_W, dl: DL, VT: MVT::v4i32, Op1: SDValue(Res, 0), |
1246 | Op2: (Highest || Higher) ? SDValue(HiRes, 0) : ZeroVal, |
1247 | Op3: CurDAG->getTargetConstant(Val: 1, DL, VT: MVT::i32)); |
1248 | |
1249 | const TargetLowering *TLI = getTargetLowering(); |
1250 | const TargetRegisterClass *RC = |
1251 | TLI->getRegClassFor(VT: ViaVecTy.getSimpleVT()); |
1252 | |
1253 | Res = CurDAG->getMachineNode( |
1254 | Opcode: Mips::COPY_TO_REGCLASS, dl: DL, VT: ViaVecTy, Op1: SDValue(Res, 0), |
1255 | Op2: CurDAG->getTargetConstant(Val: RC->getID(), DL, VT: MVT::i32)); |
1256 | |
1257 | Res = CurDAG->getMachineNode( |
1258 | Opcode: Mips::SPLATI_D, dl: DL, VT: MVT::v2i64, Op1: SDValue(Res, 0), |
1259 | Op2: CurDAG->getTargetConstant(Val: 0, DL, VT: MVT::i32)); |
1260 | } else if (ABI.IsN64() || ABI.IsN32()) { |
1261 | |
1262 | SDValue Zero64Val = CurDAG->getRegister(Reg: Mips::ZERO_64, VT: MVT::i64); |
1263 | const bool HiResNonZero = Highest || Higher; |
1264 | const bool ResNonZero = Hi || Lo; |
1265 | |
1266 | if (HiResNonZero) |
1267 | HiRes = CurDAG->getMachineNode( |
1268 | Opcode: Mips::SUBREG_TO_REG, dl: DL, VT: MVT::i64, |
1269 | Op1: CurDAG->getTargetConstant(Val: ((Highest >> 15) & 0x1), DL, VT: MVT::i64), |
1270 | Op2: SDValue(HiRes, 0), |
1271 | Op3: CurDAG->getTargetConstant(Val: Mips::sub_32, DL, VT: MVT::i64)); |
1272 | |
1273 | if (ResNonZero) |
1274 | Res = CurDAG->getMachineNode( |
1275 | Opcode: Mips::SUBREG_TO_REG, dl: DL, VT: MVT::i64, |
1276 | Op1: CurDAG->getTargetConstant(Val: ((Hi >> 15) & 0x1), DL, VT: MVT::i64), |
1277 | Op2: SDValue(Res, 0), |
1278 | Op3: CurDAG->getTargetConstant(Val: Mips::sub_32, DL, VT: MVT::i64)); |
1279 | |
1280 | // We have 3 cases: |
1281 | // The HiRes is nonzero but Res is $zero => dsll32 HiRes, 0 |
1282 | // The Res is nonzero but HiRes is $zero => dinsu Res, $zero, 32, 32 |
1283 | // Both are non zero => dinsu Res, HiRes, 32, 32 |
1284 | // |
1285 | // The obvious "missing" case is when both are zero, but that case is |
1286 | // handled by the ldi case. |
1287 | if (ResNonZero) { |
1288 | IntegerType *Int32Ty = |
1289 | IntegerType::get(C&: MF->getFunction().getContext(), NumBits: 32); |
1290 | const ConstantInt *Const32 = ConstantInt::get(Ty: Int32Ty, V: 32); |
1291 | SDValue Ops[4] = {HiResNonZero ? SDValue(HiRes, 0) : Zero64Val, |
1292 | CurDAG->getConstant(Val: *Const32, DL, VT: MVT::i32), |
1293 | CurDAG->getConstant(Val: *Const32, DL, VT: MVT::i32), |
1294 | SDValue(Res, 0)}; |
1295 | |
1296 | Res = CurDAG->getMachineNode(Opcode: Mips::DINSU, dl: DL, VT: MVT::i64, Ops); |
1297 | } else if (HiResNonZero) { |
1298 | Res = CurDAG->getMachineNode( |
1299 | Opcode: Mips::DSLL32, dl: DL, VT: MVT::i64, Op1: SDValue(HiRes, 0), |
1300 | Op2: CurDAG->getTargetConstant(Val: 0, DL, VT: MVT::i32)); |
1301 | } else |
1302 | llvm_unreachable( |
1303 | "Zero splat value handled by non-zero 64bit splat synthesis!" ); |
1304 | |
1305 | Res = CurDAG->getMachineNode(Opcode: Mips::FILL_D, dl: DL, VT: MVT::v2i64, |
1306 | Op1: SDValue(Res, 0)); |
1307 | } else |
1308 | llvm_unreachable("Unknown ABI in MipsISelDAGToDAG!" ); |
1309 | |
1310 | } else |
1311 | return false; |
1312 | |
1313 | if (ResVecTy != ViaVecTy) { |
1314 | // If LdiOp is writing to a different register class to ResVecTy, then |
1315 | // fix it up here. This COPY_TO_REGCLASS should never cause a move.v |
1316 | // since the source and destination register sets contain the same |
1317 | // registers. |
1318 | const TargetLowering *TLI = getTargetLowering(); |
1319 | MVT ResVecTySimple = ResVecTy.getSimpleVT(); |
1320 | const TargetRegisterClass *RC = TLI->getRegClassFor(VT: ResVecTySimple); |
1321 | Res = CurDAG->getMachineNode(Opcode: Mips::COPY_TO_REGCLASS, dl: DL, |
1322 | VT: ResVecTy, Op1: SDValue(Res, 0), |
1323 | Op2: CurDAG->getTargetConstant(Val: RC->getID(), DL, |
1324 | VT: MVT::i32)); |
1325 | } |
1326 | |
1327 | ReplaceNode(F: Node, T: Res); |
1328 | return true; |
1329 | } |
1330 | |
1331 | } |
1332 | |
1333 | return false; |
1334 | } |
1335 | |
1336 | bool MipsSEDAGToDAGISel::SelectInlineAsmMemoryOperand( |
1337 | const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, |
1338 | std::vector<SDValue> &OutOps) { |
1339 | SDValue Base, Offset; |
1340 | |
1341 | switch(ConstraintID) { |
1342 | default: |
1343 | llvm_unreachable("Unexpected asm memory constraint" ); |
1344 | // All memory constraints can at least accept raw pointers. |
1345 | case InlineAsm::ConstraintCode::m: |
1346 | case InlineAsm::ConstraintCode::o: |
1347 | if (selectAddrRegImm16(Addr: Op, Base, Offset)) { |
1348 | OutOps.push_back(x: Base); |
1349 | OutOps.push_back(x: Offset); |
1350 | return false; |
1351 | } |
1352 | OutOps.push_back(x: Op); |
1353 | OutOps.push_back(x: CurDAG->getTargetConstant(Val: 0, DL: SDLoc(Op), VT: MVT::i32)); |
1354 | return false; |
1355 | case InlineAsm::ConstraintCode::R: |
1356 | // The 'R' constraint is supposed to be much more complicated than this. |
1357 | // However, it's becoming less useful due to architectural changes and |
1358 | // ought to be replaced by other constraints such as 'ZC'. |
1359 | // For now, support 9-bit signed offsets which is supportable by all |
1360 | // subtargets for all instructions. |
1361 | if (selectAddrRegImm9(Addr: Op, Base, Offset)) { |
1362 | OutOps.push_back(x: Base); |
1363 | OutOps.push_back(x: Offset); |
1364 | return false; |
1365 | } |
1366 | OutOps.push_back(x: Op); |
1367 | OutOps.push_back(x: CurDAG->getTargetConstant(Val: 0, DL: SDLoc(Op), VT: MVT::i32)); |
1368 | return false; |
1369 | case InlineAsm::ConstraintCode::ZC: |
1370 | // ZC matches whatever the pref, ll, and sc instructions can handle for the |
1371 | // given subtarget. |
1372 | if (Subtarget->inMicroMipsMode()) { |
1373 | // On microMIPS, they can handle 12-bit offsets. |
1374 | if (selectAddrRegImm12(Addr: Op, Base, Offset)) { |
1375 | OutOps.push_back(x: Base); |
1376 | OutOps.push_back(x: Offset); |
1377 | return false; |
1378 | } |
1379 | } else if (Subtarget->hasMips32r6()) { |
1380 | // On MIPS32r6/MIPS64r6, they can only handle 9-bit offsets. |
1381 | if (selectAddrRegImm9(Addr: Op, Base, Offset)) { |
1382 | OutOps.push_back(x: Base); |
1383 | OutOps.push_back(x: Offset); |
1384 | return false; |
1385 | } |
1386 | } else if (selectAddrRegImm16(Addr: Op, Base, Offset)) { |
1387 | // Prior to MIPS32r6/MIPS64r6, they can handle 16-bit offsets. |
1388 | OutOps.push_back(x: Base); |
1389 | OutOps.push_back(x: Offset); |
1390 | return false; |
1391 | } |
1392 | // In all cases, 0-bit offsets are acceptable. |
1393 | OutOps.push_back(x: Op); |
1394 | OutOps.push_back(x: CurDAG->getTargetConstant(Val: 0, DL: SDLoc(Op), VT: MVT::i32)); |
1395 | return false; |
1396 | } |
1397 | return true; |
1398 | } |
1399 | |
1400 | MipsSEDAGToDAGISelLegacy::MipsSEDAGToDAGISelLegacy(MipsTargetMachine &TM, |
1401 | CodeGenOptLevel OL) |
1402 | : MipsDAGToDAGISelLegacy(std::make_unique<MipsSEDAGToDAGISel>(args&: TM, args&: OL)) {} |
1403 | |
1404 | FunctionPass *llvm::createMipsSEISelDag(MipsTargetMachine &TM, |
1405 | CodeGenOptLevel OptLevel) { |
1406 | return new MipsSEDAGToDAGISelLegacy(TM, OptLevel); |
1407 | } |
1408 | |