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