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"
36 using 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 
50 void 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 
57 bool 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.
68 SDNode *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
77 bool MipsDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base,
78                                         SDValue &Offset) const {
79   llvm_unreachable("Unimplemented function.");
80   return false;
81 }
82 
83 bool MipsDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base,
84                                          SDValue &Offset) const {
85   llvm_unreachable("Unimplemented function.");
86   return false;
87 }
88 
89 bool MipsDAGToDAGISel::selectIntAddr(SDValue Addr, SDValue &Base,
90                                      SDValue &Offset) const {
91   llvm_unreachable("Unimplemented function.");
92   return false;
93 }
94 
95 bool MipsDAGToDAGISel::selectIntAddr11MM(SDValue Addr, SDValue &Base,
96                                        SDValue &Offset) const {
97   llvm_unreachable("Unimplemented function.");
98   return false;
99 }
100 
101 bool MipsDAGToDAGISel::selectIntAddr12MM(SDValue Addr, SDValue &Base,
102                                        SDValue &Offset) const {
103   llvm_unreachable("Unimplemented function.");
104   return false;
105 }
106 
107 bool MipsDAGToDAGISel::selectIntAddr16MM(SDValue Addr, SDValue &Base,
108                                        SDValue &Offset) const {
109   llvm_unreachable("Unimplemented function.");
110   return false;
111 }
112 
113 bool MipsDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base,
114                                            SDValue &Offset) const {
115   llvm_unreachable("Unimplemented function.");
116   return false;
117 }
118 
119 bool MipsDAGToDAGISel::selectIntAddrSImm10(SDValue Addr, SDValue &Base,
120                                            SDValue &Offset) const {
121   llvm_unreachable("Unimplemented function.");
122   return false;
123 }
124 
125 bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl1(SDValue Addr, SDValue &Base,
126                                                SDValue &Offset) const {
127   llvm_unreachable("Unimplemented function.");
128   return false;
129 }
130 
131 bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl2(SDValue Addr, SDValue &Base,
132                                                SDValue &Offset) const {
133   llvm_unreachable("Unimplemented function.");
134   return false;
135 }
136 
137 bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl3(SDValue Addr, SDValue &Base,
138                                                SDValue &Offset) const {
139   llvm_unreachable("Unimplemented function.");
140   return false;
141 }
142 
143 bool MipsDAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base,
144                                     SDValue &Offset) {
145   llvm_unreachable("Unimplemented function.");
146   return false;
147 }
148 
149 bool MipsDAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base,
150                                       SDValue &Offset) {
151   llvm_unreachable("Unimplemented function.");
152   return false;
153 }
154 
155 bool MipsDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm,
156                                     unsigned MinSizeInBits) const {
157   llvm_unreachable("Unimplemented function.");
158   return false;
159 }
160 
161 bool MipsDAGToDAGISel::selectVSplatUimm1(SDValue N, SDValue &Imm) const {
162   llvm_unreachable("Unimplemented function.");
163   return false;
164 }
165 
166 bool MipsDAGToDAGISel::selectVSplatUimm2(SDValue N, SDValue &Imm) const {
167   llvm_unreachable("Unimplemented function.");
168   return false;
169 }
170 
171 bool MipsDAGToDAGISel::selectVSplatUimm3(SDValue N, SDValue &Imm) const {
172   llvm_unreachable("Unimplemented function.");
173   return false;
174 }
175 
176 bool MipsDAGToDAGISel::selectVSplatUimm4(SDValue N, SDValue &Imm) const {
177   llvm_unreachable("Unimplemented function.");
178   return false;
179 }
180 
181 bool MipsDAGToDAGISel::selectVSplatUimm5(SDValue N, SDValue &Imm) const {
182   llvm_unreachable("Unimplemented function.");
183   return false;
184 }
185 
186 bool MipsDAGToDAGISel::selectVSplatUimm6(SDValue N, SDValue &Imm) const {
187   llvm_unreachable("Unimplemented function.");
188   return false;
189 }
190 
191 bool MipsDAGToDAGISel::selectVSplatUimm8(SDValue N, SDValue &Imm) const {
192   llvm_unreachable("Unimplemented function.");
193   return false;
194 }
195 
196 bool MipsDAGToDAGISel::selectVSplatSimm5(SDValue N, SDValue &Imm) const {
197   llvm_unreachable("Unimplemented function.");
198   return false;
199 }
200 
201 bool MipsDAGToDAGISel::selectVSplatUimmPow2(SDValue N, SDValue &Imm) const {
202   llvm_unreachable("Unimplemented function.");
203   return false;
204 }
205 
206 bool MipsDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N, SDValue &Imm) const {
207   llvm_unreachable("Unimplemented function.");
208   return false;
209 }
210 
211 bool MipsDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const {
212   llvm_unreachable("Unimplemented function.");
213   return false;
214 }
215 
216 bool 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...>
224 bool 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
268 void 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 
311 bool MipsDAGToDAGISel::
312 SelectInlineAsmMemoryOperand(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 
327 char MipsDAGToDAGISel::ID = 0;
328 
329 INITIALIZE_PASS(MipsDAGToDAGISel, DEBUG_TYPE, PASS_NAME, false, false)
330