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.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "VETargetMachine.h"
14 #include "llvm/CodeGen/MachineRegisterInfo.h"
15 #include "llvm/CodeGen/SelectionDAGISel.h"
16 #include "llvm/IR/Intrinsics.h"
17 #include "llvm/Support/Debug.h"
18 #include "llvm/Support/ErrorHandling.h"
19 #include "llvm/Support/raw_ostream.h"
20 using namespace llvm;
21 
22 //===----------------------------------------------------------------------===//
23 // Instruction Selector Implementation
24 //===----------------------------------------------------------------------===//
25 
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;
35 
36 public:
37   explicit VEDAGToDAGISel(VETargetMachine &tm) : SelectionDAGISel(tm) {}
38 
39   bool runOnMachineFunction(MachineFunction &MF) override {
40     Subtarget = &MF.getSubtarget<VESubtarget>();
41     return SelectionDAGISel::runOnMachineFunction(MF);
42   }
43 
44   void Select(SDNode *N) override;
45 
46   // Complex Pattern Selectors.
47   bool selectADDRrri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
48   bool selectADDRrii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
49   bool selectADDRzri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
50   bool selectADDRzii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
51   bool selectADDRri(SDValue N, SDValue &Base, SDValue &Offset);
52 
53   StringRef getPassName() const override {
54     return "VE DAG->DAG Pattern Instruction Selection";
55   }
56 
57   // Include the pieces autogenerated from the target description.
58 #include "VEGenDAGISel.inc"
59 
60 private:
61   SDNode *getGlobalBaseReg();
62 
63   bool matchADDRrr(SDValue N, SDValue &Base, SDValue &Index);
64   bool matchADDRri(SDValue N, SDValue &Base, SDValue &Offset);
65 };
66 } // end anonymous namespace
67 
68 bool VEDAGToDAGISel::selectADDRrri(SDValue Addr, SDValue &Base, SDValue &Index,
69                                    SDValue &Offset) {
70   if (Addr.getOpcode() == ISD::FrameIndex)
71     return false;
72   if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
73       Addr.getOpcode() == ISD::TargetGlobalAddress ||
74       Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
75     return false; // direct calls.
76 
77   SDValue LHS, RHS;
78   if (matchADDRri(Addr, LHS, RHS)) {
79     if (matchADDRrr(LHS, Base, Index)) {
80       Offset = RHS;
81       return true;
82     }
83     // Return false to try selectADDRrii.
84     return false;
85   }
86   if (matchADDRrr(Addr, LHS, RHS)) {
87     if (matchADDRri(RHS, Index, Offset)) {
88       Base = LHS;
89       return true;
90     }
91     if (matchADDRri(LHS, Base, Offset)) {
92       Index = RHS;
93       return true;
94     }
95     Base = LHS;
96     Index = RHS;
97     Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
98     return true;
99   }
100   return false; // Let the reg+imm(=0) pattern catch this!
101 }
102 
103 bool VEDAGToDAGISel::selectADDRrii(SDValue Addr, SDValue &Base, SDValue &Index,
104                                    SDValue &Offset) {
105   if (matchADDRri(Addr, Base, Offset)) {
106     Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
107     return true;
108   }
109 
110   Base = Addr;
111   Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
112   Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
113   return true;
114 }
115 
116 bool VEDAGToDAGISel::selectADDRzri(SDValue Addr, SDValue &Base, SDValue &Index,
117                                    SDValue &Offset) {
118   // Prefer ADDRrii.
119   return false;
120 }
121 
122 bool VEDAGToDAGISel::selectADDRzii(SDValue Addr, SDValue &Base, SDValue &Index,
123                                    SDValue &Offset) {
124   if (dyn_cast<FrameIndexSDNode>(Addr)) {
125     return false;
126   }
127   if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
128       Addr.getOpcode() == ISD::TargetGlobalAddress ||
129       Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
130     return false; // direct calls.
131 
132   if (ConstantSDNode *CN = cast<ConstantSDNode>(Addr)) {
133     if (isInt<32>(CN->getSExtValue())) {
134       Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
135       Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
136       Offset =
137           CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
138       return true;
139     }
140   }
141   return false;
142 }
143 
144 bool VEDAGToDAGISel::selectADDRri(SDValue Addr, SDValue &Base,
145                                   SDValue &Offset) {
146   if (matchADDRri(Addr, Base, Offset))
147     return true;
148 
149   Base = Addr;
150   Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
151   return true;
152 }
153 
154 bool VEDAGToDAGISel::matchADDRrr(SDValue Addr, SDValue &Base, SDValue &Index) {
155   if (dyn_cast<FrameIndexSDNode>(Addr))
156     return false;
157   if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
158       Addr.getOpcode() == ISD::TargetGlobalAddress ||
159       Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
160     return false; // direct calls.
161 
162   if (Addr.getOpcode() == ISD::ADD) {
163     ; // Nothing to do here.
164   } else if (Addr.getOpcode() == ISD::OR) {
165     // We want to look through a transform in InstCombine and DAGCombiner that
166     // turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'.
167     if (!CurDAG->haveNoCommonBitsSet(Addr.getOperand(0), Addr.getOperand(1)))
168       return false;
169   } else {
170     return false;
171   }
172 
173   if (Addr.getOperand(0).getOpcode() == VEISD::Lo ||
174       Addr.getOperand(1).getOpcode() == VEISD::Lo)
175     return false; // Let the LEASL patterns catch this!
176 
177   Base = Addr.getOperand(0);
178   Index = Addr.getOperand(1);
179   return true;
180 }
181 
182 bool VEDAGToDAGISel::matchADDRri(SDValue Addr, SDValue &Base, SDValue &Offset) {
183   auto AddrTy = Addr->getValueType(0);
184   if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
185     Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);
186     Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
187     return true;
188   }
189   if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
190       Addr.getOpcode() == ISD::TargetGlobalAddress ||
191       Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
192     return false; // direct calls.
193 
194   if (CurDAG->isBaseWithConstantOffset(Addr)) {
195     ConstantSDNode *CN = cast<ConstantSDNode>(Addr.getOperand(1));
196     if (isInt<32>(CN->getSExtValue())) {
197       if (FrameIndexSDNode *FIN =
198               dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
199         // Constant offset from frame ref.
200         Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);
201       } else {
202         Base = Addr.getOperand(0);
203       }
204       Offset =
205           CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
206       return true;
207     }
208   }
209   return false;
210 }
211 
212 void VEDAGToDAGISel::Select(SDNode *N) {
213   SDLoc dl(N);
214   if (N->isMachineOpcode()) {
215     N->setNodeId(-1);
216     return; // Already selected.
217   }
218 
219   switch (N->getOpcode()) {
220   case VEISD::GLOBAL_BASE_REG:
221     ReplaceNode(N, getGlobalBaseReg());
222     return;
223   }
224 
225   SelectCode(N);
226 }
227 
228 SDNode *VEDAGToDAGISel::getGlobalBaseReg() {
229   Register GlobalBaseReg = Subtarget->getInstrInfo()->getGlobalBaseReg(MF);
230   return CurDAG
231       ->getRegister(GlobalBaseReg, TLI->getPointerTy(CurDAG->getDataLayout()))
232       .getNode();
233 }
234 
235 /// createVEISelDag - This pass converts a legalized DAG into a
236 /// VE-specific DAG, ready for instruction scheduling.
237 ///
238 FunctionPass *llvm::createVEISelDag(VETargetMachine &TM) {
239   return new VEDAGToDAGISel(TM);
240 }
241