1//===-- MipsISelDAGToDAG.cpp - A Dag to Dag Inst Selector for Mips --------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines an instruction selector for the MIPS target.
10//
11//===----------------------------------------------------------------------===//
12
13#include "MipsISelDAGToDAG.h"
14#include "MCTargetDesc/MipsBaseInfo.h"
15#include "Mips.h"
16#include "Mips16ISelDAGToDAG.h"
17#include "MipsMachineFunction.h"
18#include "MipsRegisterInfo.h"
19#include "MipsSEISelDAGToDAG.h"
20#include "llvm/CodeGen/MachineConstantPool.h"
21#include "llvm/CodeGen/MachineFrameInfo.h"
22#include "llvm/CodeGen/MachineFunction.h"
23#include "llvm/CodeGen/MachineInstrBuilder.h"
24#include "llvm/CodeGen/MachineRegisterInfo.h"
25#include "llvm/CodeGen/SelectionDAGNodes.h"
26#include "llvm/CodeGen/StackProtector.h"
27#include "llvm/IR/CFG.h"
28#include "llvm/IR/GlobalValue.h"
29#include "llvm/IR/Instructions.h"
30#include "llvm/IR/Intrinsics.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"
36using namespace llvm;
37
38#define DEBUG_TYPE "mips-isel"
39#define PASS_NAME "MIPS DAG->DAG Pattern Instruction Selection"
40
41//===----------------------------------------------------------------------===//
42// Instruction Selector Implementation
43//===----------------------------------------------------------------------===//
44
45//===----------------------------------------------------------------------===//
46// MipsDAGToDAGISel - MIPS specific code to select MIPS machine
47// instructions for SelectionDAG operations.
48//===----------------------------------------------------------------------===//
49
50void MipsDAGToDAGISel::getAnalysisUsage(AnalysisUsage &AU) const {
51  // There are multiple MipsDAGToDAGISel instances added to the pass pipeline.
52  // We need to preserve StackProtector for the next one.
53  AU.addPreserved<StackProtector>();
54  SelectionDAGISel::getAnalysisUsage(AU);
55}
56
57bool MipsDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
58  Subtarget = &MF.getSubtarget<MipsSubtarget>();
59  bool Ret = SelectionDAGISel::runOnMachineFunction(MF);
60
61  processFunctionAfterISel(MF);
62
63  return Ret;
64}
65
66/// getGlobalBaseReg - Output the instructions required to put the
67/// GOT address into a register.
68SDNode *MipsDAGToDAGISel::getGlobalBaseReg() {
69  Register GlobalBaseReg = MF->getInfo<MipsFunctionInfo>()->getGlobalBaseReg(*MF);
70  return CurDAG->getRegister(GlobalBaseReg, getTargetLowering()->getPointerTy(
71                                                CurDAG->getDataLayout()))
72      .getNode();
73}
74
75/// ComplexPattern used on MipsInstrInfo
76/// Used on Mips Load/Store instructions
77bool MipsDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base,
78                                        SDValue &Offset) const {
79  llvm_unreachable("Unimplemented function.");
80  return false;
81}
82
83bool MipsDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base,
84                                         SDValue &Offset) const {
85  llvm_unreachable("Unimplemented function.");
86  return false;
87}
88
89bool MipsDAGToDAGISel::selectIntAddr(SDValue Addr, SDValue &Base,
90                                     SDValue &Offset) const {
91  llvm_unreachable("Unimplemented function.");
92  return false;
93}
94
95bool MipsDAGToDAGISel::selectIntAddr11MM(SDValue Addr, SDValue &Base,
96                                       SDValue &Offset) const {
97  llvm_unreachable("Unimplemented function.");
98  return false;
99}
100
101bool MipsDAGToDAGISel::selectIntAddr12MM(SDValue Addr, SDValue &Base,
102                                       SDValue &Offset) const {
103  llvm_unreachable("Unimplemented function.");
104  return false;
105}
106
107bool MipsDAGToDAGISel::selectIntAddr16MM(SDValue Addr, SDValue &Base,
108                                       SDValue &Offset) const {
109  llvm_unreachable("Unimplemented function.");
110  return false;
111}
112
113bool MipsDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base,
114                                           SDValue &Offset) const {
115  llvm_unreachable("Unimplemented function.");
116  return false;
117}
118
119bool MipsDAGToDAGISel::selectIntAddrSImm10(SDValue Addr, SDValue &Base,
120                                           SDValue &Offset) const {
121  llvm_unreachable("Unimplemented function.");
122  return false;
123}
124
125bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl1(SDValue Addr, SDValue &Base,
126                                               SDValue &Offset) const {
127  llvm_unreachable("Unimplemented function.");
128  return false;
129}
130
131bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl2(SDValue Addr, SDValue &Base,
132                                               SDValue &Offset) const {
133  llvm_unreachable("Unimplemented function.");
134  return false;
135}
136
137bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl3(SDValue Addr, SDValue &Base,
138                                               SDValue &Offset) const {
139  llvm_unreachable("Unimplemented function.");
140  return false;
141}
142
143bool MipsDAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base,
144                                    SDValue &Offset) {
145  llvm_unreachable("Unimplemented function.");
146  return false;
147}
148
149bool MipsDAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base,
150                                      SDValue &Offset) {
151  llvm_unreachable("Unimplemented function.");
152  return false;
153}
154
155bool MipsDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm,
156                                    unsigned MinSizeInBits) const {
157  llvm_unreachable("Unimplemented function.");
158  return false;
159}
160
161bool MipsDAGToDAGISel::selectVSplatUimm1(SDValue N, SDValue &Imm) const {
162  llvm_unreachable("Unimplemented function.");
163  return false;
164}
165
166bool MipsDAGToDAGISel::selectVSplatUimm2(SDValue N, SDValue &Imm) const {
167  llvm_unreachable("Unimplemented function.");
168  return false;
169}
170
171bool MipsDAGToDAGISel::selectVSplatUimm3(SDValue N, SDValue &Imm) const {
172  llvm_unreachable("Unimplemented function.");
173  return false;
174}
175
176bool MipsDAGToDAGISel::selectVSplatUimm4(SDValue N, SDValue &Imm) const {
177  llvm_unreachable("Unimplemented function.");
178  return false;
179}
180
181bool MipsDAGToDAGISel::selectVSplatUimm5(SDValue N, SDValue &Imm) const {
182  llvm_unreachable("Unimplemented function.");
183  return false;
184}
185
186bool MipsDAGToDAGISel::selectVSplatUimm6(SDValue N, SDValue &Imm) const {
187  llvm_unreachable("Unimplemented function.");
188  return false;
189}
190
191bool MipsDAGToDAGISel::selectVSplatUimm8(SDValue N, SDValue &Imm) const {
192  llvm_unreachable("Unimplemented function.");
193  return false;
194}
195
196bool MipsDAGToDAGISel::selectVSplatSimm5(SDValue N, SDValue &Imm) const {
197  llvm_unreachable("Unimplemented function.");
198  return false;
199}
200
201bool MipsDAGToDAGISel::selectVSplatUimmPow2(SDValue N, SDValue &Imm) const {
202  llvm_unreachable("Unimplemented function.");
203  return false;
204}
205
206bool MipsDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N, SDValue &Imm) const {
207  llvm_unreachable("Unimplemented function.");
208  return false;
209}
210
211bool MipsDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const {
212  llvm_unreachable("Unimplemented function.");
213  return false;
214}
215
216bool MipsDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const {
217  llvm_unreachable("Unimplemented function.");
218  return false;
219}
220
221/// Convert vector addition with vector subtraction if that allows to encode
222/// constant as an immediate and thus avoid extra 'ldi' instruction.
223/// add X, <-1, -1...> --> sub X, <1, 1...>
224bool MipsDAGToDAGISel::selectVecAddAsVecSubIfProfitable(SDNode *Node) {
225  assert(Node->getOpcode() == ISD::ADD && "Should only get 'add' here.");
226
227  EVT VT = Node->getValueType(0);
228  assert(VT.isVector() && "Should only be called for vectors.");
229
230  SDValue X = Node->getOperand(0);
231  SDValue C = Node->getOperand(1);
232
233  auto *BVN = dyn_cast<BuildVectorSDNode>(C);
234  if (!BVN)
235    return false;
236
237  APInt SplatValue, SplatUndef;
238  unsigned SplatBitSize;
239  bool HasAnyUndefs;
240
241  if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
242                            8, !Subtarget->isLittle()))
243    return false;
244
245  auto IsInlineConstant = [](const APInt &Imm) { return Imm.isIntN(5); };
246
247  if (IsInlineConstant(SplatValue))
248    return false; // Can already be encoded as an immediate.
249
250  APInt NegSplatValue = 0 - SplatValue;
251  if (!IsInlineConstant(NegSplatValue))
252    return false; // Even if we negate it it won't help.
253
254  SDLoc DL(Node);
255
256  SDValue NegC = CurDAG->FoldConstantArithmetic(
257      ISD::SUB, DL, VT, {CurDAG->getConstant(0, DL, VT), C});
258  assert(NegC && "Constant-folding failed!");
259  SDValue NewNode = CurDAG->getNode(ISD::SUB, DL, VT, X, NegC);
260
261  ReplaceNode(Node, NewNode.getNode());
262  SelectCode(NewNode.getNode());
263  return true;
264}
265
266/// Select instructions not customized! Used for
267/// expanded, promoted and normal instructions
268void MipsDAGToDAGISel::Select(SDNode *Node) {
269  unsigned Opcode = Node->getOpcode();
270
271  // If we have a custom node, we already have selected!
272  if (Node->isMachineOpcode()) {
273    LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
274    Node->setNodeId(-1);
275    return;
276  }
277
278  // See if subclasses can handle this node.
279  if (trySelect(Node))
280    return;
281
282  switch(Opcode) {
283  default: break;
284
285  case ISD::ADD:
286    if (Node->getSimpleValueType(0).isVector() &&
287        selectVecAddAsVecSubIfProfitable(Node))
288      return;
289    break;
290
291  // Get target GOT address.
292  case ISD::GLOBAL_OFFSET_TABLE:
293    ReplaceNode(Node, getGlobalBaseReg());
294    return;
295
296#ifndef NDEBUG
297  case ISD::LOAD:
298  case ISD::STORE:
299    assert((Subtarget->systemSupportsUnalignedAccess() ||
300            cast<MemSDNode>(Node)->getAlign() >=
301                cast<MemSDNode>(Node)->getMemoryVT().getStoreSize()) &&
302           "Unexpected unaligned loads/stores.");
303    break;
304#endif
305  }
306
307  // Select the default instruction
308  SelectCode(Node);
309}
310
311bool MipsDAGToDAGISel::
312SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
313                             std::vector<SDValue> &OutOps) {
314  // All memory constraints can at least accept raw pointers.
315  switch(ConstraintID) {
316  default:
317    llvm_unreachable("Unexpected asm memory constraint");
318  case InlineAsm::Constraint_m:
319  case InlineAsm::Constraint_R:
320  case InlineAsm::Constraint_ZC:
321    OutOps.push_back(Op);
322    return false;
323  }
324  return true;
325}
326
327char MipsDAGToDAGISel::ID = 0;
328
329INITIALIZE_PASS(MipsDAGToDAGISel, DEBUG_TYPE, PASS_NAME, false, false)
330