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