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
getAnalysisUsage(AnalysisUsage & AU) const50 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
runOnMachineFunction(MachineFunction & MF)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.
getGlobalBaseReg()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
selectAddrRegImm(SDValue Addr,SDValue & Base,SDValue & Offset) const77 bool MipsDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base,
78 SDValue &Offset) const {
79 llvm_unreachable("Unimplemented function.");
80 return false;
81 }
82
selectAddrDefault(SDValue Addr,SDValue & Base,SDValue & Offset) const83 bool MipsDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base,
84 SDValue &Offset) const {
85 llvm_unreachable("Unimplemented function.");
86 return false;
87 }
88
selectIntAddr(SDValue Addr,SDValue & Base,SDValue & Offset) const89 bool MipsDAGToDAGISel::selectIntAddr(SDValue Addr, SDValue &Base,
90 SDValue &Offset) const {
91 llvm_unreachable("Unimplemented function.");
92 return false;
93 }
94
selectIntAddr11MM(SDValue Addr,SDValue & Base,SDValue & Offset) const95 bool MipsDAGToDAGISel::selectIntAddr11MM(SDValue Addr, SDValue &Base,
96 SDValue &Offset) const {
97 llvm_unreachable("Unimplemented function.");
98 return false;
99 }
100
selectIntAddr12MM(SDValue Addr,SDValue & Base,SDValue & Offset) const101 bool MipsDAGToDAGISel::selectIntAddr12MM(SDValue Addr, SDValue &Base,
102 SDValue &Offset) const {
103 llvm_unreachable("Unimplemented function.");
104 return false;
105 }
106
selectIntAddr16MM(SDValue Addr,SDValue & Base,SDValue & Offset) const107 bool MipsDAGToDAGISel::selectIntAddr16MM(SDValue Addr, SDValue &Base,
108 SDValue &Offset) const {
109 llvm_unreachable("Unimplemented function.");
110 return false;
111 }
112
selectIntAddrLSL2MM(SDValue Addr,SDValue & Base,SDValue & Offset) const113 bool MipsDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base,
114 SDValue &Offset) const {
115 llvm_unreachable("Unimplemented function.");
116 return false;
117 }
118
selectIntAddrSImm10(SDValue Addr,SDValue & Base,SDValue & Offset) const119 bool MipsDAGToDAGISel::selectIntAddrSImm10(SDValue Addr, SDValue &Base,
120 SDValue &Offset) const {
121 llvm_unreachable("Unimplemented function.");
122 return false;
123 }
124
selectIntAddrSImm10Lsl1(SDValue Addr,SDValue & Base,SDValue & Offset) const125 bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl1(SDValue Addr, SDValue &Base,
126 SDValue &Offset) const {
127 llvm_unreachable("Unimplemented function.");
128 return false;
129 }
130
selectIntAddrSImm10Lsl2(SDValue Addr,SDValue & Base,SDValue & Offset) const131 bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl2(SDValue Addr, SDValue &Base,
132 SDValue &Offset) const {
133 llvm_unreachable("Unimplemented function.");
134 return false;
135 }
136
selectIntAddrSImm10Lsl3(SDValue Addr,SDValue & Base,SDValue & Offset) const137 bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl3(SDValue Addr, SDValue &Base,
138 SDValue &Offset) const {
139 llvm_unreachable("Unimplemented function.");
140 return false;
141 }
142
selectAddr16(SDValue Addr,SDValue & Base,SDValue & Offset)143 bool MipsDAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base,
144 SDValue &Offset) {
145 llvm_unreachable("Unimplemented function.");
146 return false;
147 }
148
selectAddr16SP(SDValue Addr,SDValue & Base,SDValue & Offset)149 bool MipsDAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base,
150 SDValue &Offset) {
151 llvm_unreachable("Unimplemented function.");
152 return false;
153 }
154
selectVSplat(SDNode * N,APInt & Imm,unsigned MinSizeInBits) const155 bool MipsDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm,
156 unsigned MinSizeInBits) const {
157 llvm_unreachable("Unimplemented function.");
158 return false;
159 }
160
selectVSplatUimm1(SDValue N,SDValue & Imm) const161 bool MipsDAGToDAGISel::selectVSplatUimm1(SDValue N, SDValue &Imm) const {
162 llvm_unreachable("Unimplemented function.");
163 return false;
164 }
165
selectVSplatUimm2(SDValue N,SDValue & Imm) const166 bool MipsDAGToDAGISel::selectVSplatUimm2(SDValue N, SDValue &Imm) const {
167 llvm_unreachable("Unimplemented function.");
168 return false;
169 }
170
selectVSplatUimm3(SDValue N,SDValue & Imm) const171 bool MipsDAGToDAGISel::selectVSplatUimm3(SDValue N, SDValue &Imm) const {
172 llvm_unreachable("Unimplemented function.");
173 return false;
174 }
175
selectVSplatUimm4(SDValue N,SDValue & Imm) const176 bool MipsDAGToDAGISel::selectVSplatUimm4(SDValue N, SDValue &Imm) const {
177 llvm_unreachable("Unimplemented function.");
178 return false;
179 }
180
selectVSplatUimm5(SDValue N,SDValue & Imm) const181 bool MipsDAGToDAGISel::selectVSplatUimm5(SDValue N, SDValue &Imm) const {
182 llvm_unreachable("Unimplemented function.");
183 return false;
184 }
185
selectVSplatUimm6(SDValue N,SDValue & Imm) const186 bool MipsDAGToDAGISel::selectVSplatUimm6(SDValue N, SDValue &Imm) const {
187 llvm_unreachable("Unimplemented function.");
188 return false;
189 }
190
selectVSplatUimm8(SDValue N,SDValue & Imm) const191 bool MipsDAGToDAGISel::selectVSplatUimm8(SDValue N, SDValue &Imm) const {
192 llvm_unreachable("Unimplemented function.");
193 return false;
194 }
195
selectVSplatSimm5(SDValue N,SDValue & Imm) const196 bool MipsDAGToDAGISel::selectVSplatSimm5(SDValue N, SDValue &Imm) const {
197 llvm_unreachable("Unimplemented function.");
198 return false;
199 }
200
selectVSplatUimmPow2(SDValue N,SDValue & Imm) const201 bool MipsDAGToDAGISel::selectVSplatUimmPow2(SDValue N, SDValue &Imm) const {
202 llvm_unreachable("Unimplemented function.");
203 return false;
204 }
205
selectVSplatUimmInvPow2(SDValue N,SDValue & Imm) const206 bool MipsDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N, SDValue &Imm) const {
207 llvm_unreachable("Unimplemented function.");
208 return false;
209 }
210
selectVSplatMaskL(SDValue N,SDValue & Imm) const211 bool MipsDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const {
212 llvm_unreachable("Unimplemented function.");
213 return false;
214 }
215
selectVSplatMaskR(SDValue N,SDValue & Imm) const216 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...>
selectVecAddAsVecSubIfProfitable(SDNode * Node)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
Select(SDNode * Node)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::
SelectInlineAsmMemoryOperand(const SDValue & Op,unsigned ConstraintID,std::vector<SDValue> & OutOps)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