[llvm-shlib] Fix the version naming style of libLLVM for Windows (#85710)
[llvm-project.git] / llvm / lib / Target / VE / VEISelDAGToDAG.cpp
blob87646bc1a12ff25fe6e21875fdbb60f12483f901
1 //===-- VEISelDAGToDAG.cpp - A dag to dag inst selector for VE ------------===//
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 VE target.
11 //===----------------------------------------------------------------------===//
13 #include "VE.h"
14 #include "VETargetMachine.h"
15 #include "llvm/CodeGen/MachineRegisterInfo.h"
16 #include "llvm/CodeGen/SelectionDAGISel.h"
17 #include "llvm/IR/Intrinsics.h"
18 #include "llvm/Support/Debug.h"
19 #include "llvm/Support/ErrorHandling.h"
20 #include "llvm/Support/raw_ostream.h"
21 using namespace llvm;
23 #define DEBUG_TYPE "ve-isel"
24 #define PASS_NAME "VE DAG->DAG Pattern Instruction Selection"
26 //===--------------------------------------------------------------------===//
27 /// VEDAGToDAGISel - VE specific code to select VE machine
28 /// instructions for SelectionDAG operations.
29 ///
30 namespace {
31 class VEDAGToDAGISel : public SelectionDAGISel {
32 /// Subtarget - Keep a pointer to the VE Subtarget around so that we can
33 /// make the right decision when generating code for different targets.
34 const VESubtarget *Subtarget;
36 public:
37 static char ID;
39 VEDAGToDAGISel() = delete;
41 explicit VEDAGToDAGISel(VETargetMachine &tm) : SelectionDAGISel(ID, tm) {}
43 bool runOnMachineFunction(MachineFunction &MF) override {
44 Subtarget = &MF.getSubtarget<VESubtarget>();
45 return SelectionDAGISel::runOnMachineFunction(MF);
48 void Select(SDNode *N) override;
50 // Complex Pattern Selectors.
51 bool selectADDRrri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
52 bool selectADDRrii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
53 bool selectADDRzri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
54 bool selectADDRzii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
55 bool selectADDRri(SDValue N, SDValue &Base, SDValue &Offset);
56 bool selectADDRzi(SDValue N, SDValue &Base, SDValue &Offset);
58 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
59 /// inline asm expressions.
60 bool SelectInlineAsmMemoryOperand(const SDValue &Op,
61 InlineAsm::ConstraintCode ConstraintID,
62 std::vector<SDValue> &OutOps) override;
64 // Include the pieces autogenerated from the target description.
65 #include "VEGenDAGISel.inc"
67 private:
68 SDNode *getGlobalBaseReg();
70 bool matchADDRrr(SDValue N, SDValue &Base, SDValue &Index);
71 bool matchADDRri(SDValue N, SDValue &Base, SDValue &Offset);
73 } // end anonymous namespace
75 char VEDAGToDAGISel::ID = 0;
77 INITIALIZE_PASS(VEDAGToDAGISel, DEBUG_TYPE, PASS_NAME, false, false)
79 bool VEDAGToDAGISel::selectADDRrri(SDValue Addr, SDValue &Base, SDValue &Index,
80 SDValue &Offset) {
81 if (Addr.getOpcode() == ISD::FrameIndex)
82 return false;
83 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
84 Addr.getOpcode() == ISD::TargetGlobalAddress ||
85 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
86 return false; // direct calls.
88 SDValue LHS, RHS;
89 if (matchADDRri(Addr, LHS, RHS)) {
90 if (matchADDRrr(LHS, Base, Index)) {
91 Offset = RHS;
92 return true;
94 // Return false to try selectADDRrii.
95 return false;
97 if (matchADDRrr(Addr, LHS, RHS)) {
98 // If the input is a pair of a frame-index and a register, move a
99 // frame-index to LHS. This generates MI with following operands.
100 // %dest, #FI, %reg, offset
101 // In the eliminateFrameIndex, above MI is converted to the following.
102 // %dest, %fp, %reg, fi_offset + offset
103 if (isa<FrameIndexSDNode>(RHS))
104 std::swap(LHS, RHS);
106 if (matchADDRri(RHS, Index, Offset)) {
107 Base = LHS;
108 return true;
110 if (matchADDRri(LHS, Base, Offset)) {
111 Index = RHS;
112 return true;
114 Base = LHS;
115 Index = RHS;
116 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
117 return true;
119 return false; // Let the reg+imm(=0) pattern catch this!
122 bool VEDAGToDAGISel::selectADDRrii(SDValue Addr, SDValue &Base, SDValue &Index,
123 SDValue &Offset) {
124 if (matchADDRri(Addr, Base, Offset)) {
125 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
126 return true;
129 Base = Addr;
130 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
131 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
132 return true;
135 bool VEDAGToDAGISel::selectADDRzri(SDValue Addr, SDValue &Base, SDValue &Index,
136 SDValue &Offset) {
137 // Prefer ADDRrii.
138 return false;
141 bool VEDAGToDAGISel::selectADDRzii(SDValue Addr, SDValue &Base, SDValue &Index,
142 SDValue &Offset) {
143 if (isa<FrameIndexSDNode>(Addr))
144 return false;
145 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
146 Addr.getOpcode() == ISD::TargetGlobalAddress ||
147 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
148 return false; // direct calls.
150 if (auto *CN = dyn_cast<ConstantSDNode>(Addr)) {
151 if (isInt<32>(CN->getSExtValue())) {
152 Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
153 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
154 Offset =
155 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
156 return true;
159 return false;
162 bool VEDAGToDAGISel::selectADDRri(SDValue Addr, SDValue &Base,
163 SDValue &Offset) {
164 if (matchADDRri(Addr, Base, Offset))
165 return true;
167 Base = Addr;
168 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
169 return true;
172 bool VEDAGToDAGISel::selectADDRzi(SDValue Addr, SDValue &Base,
173 SDValue &Offset) {
174 if (isa<FrameIndexSDNode>(Addr))
175 return false;
176 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
177 Addr.getOpcode() == ISD::TargetGlobalAddress ||
178 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
179 return false; // direct calls.
181 if (auto *CN = dyn_cast<ConstantSDNode>(Addr)) {
182 if (isInt<32>(CN->getSExtValue())) {
183 Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
184 Offset =
185 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
186 return true;
189 return false;
192 bool VEDAGToDAGISel::matchADDRrr(SDValue Addr, SDValue &Base, SDValue &Index) {
193 if (isa<FrameIndexSDNode>(Addr))
194 return false;
195 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
196 Addr.getOpcode() == ISD::TargetGlobalAddress ||
197 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
198 return false; // direct calls.
200 if (Addr.getOpcode() == ISD::ADD) {
201 ; // Nothing to do here.
202 } else if (Addr.getOpcode() == ISD::OR) {
203 // We want to look through a transform in InstCombine and DAGCombiner that
204 // turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'.
205 if (!CurDAG->haveNoCommonBitsSet(Addr.getOperand(0), Addr.getOperand(1)))
206 return false;
207 } else {
208 return false;
211 if (Addr.getOperand(0).getOpcode() == VEISD::Lo ||
212 Addr.getOperand(1).getOpcode() == VEISD::Lo)
213 return false; // Let the LEASL patterns catch this!
215 Base = Addr.getOperand(0);
216 Index = Addr.getOperand(1);
217 return true;
220 bool VEDAGToDAGISel::matchADDRri(SDValue Addr, SDValue &Base, SDValue &Offset) {
221 auto AddrTy = Addr->getValueType(0);
222 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
223 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);
224 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
225 return true;
227 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
228 Addr.getOpcode() == ISD::TargetGlobalAddress ||
229 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
230 return false; // direct calls.
232 if (CurDAG->isBaseWithConstantOffset(Addr)) {
233 ConstantSDNode *CN = cast<ConstantSDNode>(Addr.getOperand(1));
234 if (isInt<32>(CN->getSExtValue())) {
235 if (FrameIndexSDNode *FIN =
236 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
237 // Constant offset from frame ref.
238 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);
239 } else {
240 Base = Addr.getOperand(0);
242 Offset =
243 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
244 return true;
247 return false;
250 void VEDAGToDAGISel::Select(SDNode *N) {
251 SDLoc dl(N);
252 if (N->isMachineOpcode()) {
253 N->setNodeId(-1);
254 return; // Already selected.
257 switch (N->getOpcode()) {
259 // Late eliminate the LEGALAVL wrapper
260 case VEISD::LEGALAVL:
261 ReplaceNode(N, N->getOperand(0).getNode());
262 return;
264 // Lower (broadcast 1) and (broadcast 0) to VM[P]0
265 case VEISD::VEC_BROADCAST: {
266 MVT SplatResTy = N->getSimpleValueType(0);
267 if (SplatResTy.getVectorElementType() != MVT::i1)
268 break;
270 // Constant non-zero broadcast.
271 auto BConst = dyn_cast<ConstantSDNode>(N->getOperand(0));
272 if (!BConst)
273 break;
274 bool BCTrueMask = (BConst->getSExtValue() != 0);
275 if (!BCTrueMask)
276 break;
278 // Packed or non-packed.
279 SDValue New;
280 if (SplatResTy.getVectorNumElements() == StandardVectorWidth) {
281 New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(N), VE::VM0,
282 MVT::v256i1);
283 } else if (SplatResTy.getVectorNumElements() == PackedVectorWidth) {
284 New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(N), VE::VMP0,
285 MVT::v512i1);
286 } else
287 break;
289 // Replace.
290 ReplaceNode(N, New.getNode());
291 return;
294 case VEISD::GLOBAL_BASE_REG:
295 ReplaceNode(N, getGlobalBaseReg());
296 return;
299 SelectCode(N);
302 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
303 /// inline asm expressions.
304 bool VEDAGToDAGISel::SelectInlineAsmMemoryOperand(
305 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
306 std::vector<SDValue> &OutOps) {
307 SDValue Op0, Op1;
308 switch (ConstraintID) {
309 default:
310 llvm_unreachable("Unexpected asm memory constraint");
311 case InlineAsm::ConstraintCode::o:
312 case InlineAsm::ConstraintCode::m: // memory
313 // Try to match ADDRri since reg+imm style is safe for all VE instructions
314 // with a memory operand.
315 if (selectADDRri(Op, Op0, Op1)) {
316 OutOps.push_back(Op0);
317 OutOps.push_back(Op1);
318 return false;
320 // Otherwise, require the address to be in a register and immediate 0.
321 OutOps.push_back(Op);
322 OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32));
323 return false;
325 return true;
328 SDNode *VEDAGToDAGISel::getGlobalBaseReg() {
329 Register GlobalBaseReg = Subtarget->getInstrInfo()->getGlobalBaseReg(MF);
330 return CurDAG
331 ->getRegister(GlobalBaseReg, TLI->getPointerTy(CurDAG->getDataLayout()))
332 .getNode();
335 /// createVEISelDag - This pass converts a legalized DAG into a
336 /// VE-specific DAG, ready for instruction scheduling.
338 FunctionPass *llvm::createVEISelDag(VETargetMachine &TM) {
339 return new VEDAGToDAGISel(TM);