1 | //===-- VEISelLowering.h - VE DAG Lowering Interface ------------*- C++ -*-===// |
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 the interfaces that VE uses to lower LLVM code into a |
10 | // selection DAG. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_LIB_TARGET_VE_VEISELLOWERING_H |
15 | #define LLVM_LIB_TARGET_VE_VEISELLOWERING_H |
16 | |
17 | #include "VE.h" |
18 | #include "llvm/CodeGen/TargetLowering.h" |
19 | |
20 | namespace llvm { |
21 | class VESubtarget; |
22 | |
23 | namespace VEISD { |
24 | enum NodeType : unsigned { |
25 | FIRST_NUMBER = ISD::BUILTIN_OP_END, |
26 | |
27 | CMPI, // Compare between two signed integer values. |
28 | CMPU, // Compare between two unsigned integer values. |
29 | CMPF, // Compare between two floating-point values. |
30 | CMPQ, // Compare between two quad floating-point values. |
31 | CMOV, // Select between two values using the result of comparison. |
32 | |
33 | CALL, // A call instruction. |
34 | EH_SJLJ_LONGJMP, // SjLj exception handling longjmp. |
35 | EH_SJLJ_SETJMP, // SjLj exception handling setjmp. |
36 | EH_SJLJ_SETUP_DISPATCH, // SjLj exception handling setup_dispatch. |
37 | GETFUNPLT, // Load function address through %plt insturction. |
38 | GETTLSADDR, // Load address for TLS access. |
39 | GETSTACKTOP, // Retrieve address of stack top (first address of |
40 | // locals and temporaries). |
41 | GLOBAL_BASE_REG, // Global base reg for PIC. |
42 | Hi, // Hi/Lo operations, typically on a global address. |
43 | Lo, // Hi/Lo operations, typically on a global address. |
44 | RET_GLUE, // Return with a flag operand. |
45 | TS1AM, // A TS1AM instruction used for 1/2 bytes swap. |
46 | VEC_UNPACK_LO, // unpack the lo v256 slice of a packed v512 vector. |
47 | VEC_UNPACK_HI, // unpack the hi v256 slice of a packed v512 vector. |
48 | // 0: v512 vector, 1: AVL |
49 | VEC_PACK, // pack a lo and a hi vector into one v512 vector |
50 | // 0: v256 lo vector, 1: v256 hi vector, 2: AVL |
51 | |
52 | VEC_BROADCAST, // A vector broadcast instruction. |
53 | // 0: scalar value, 1: VL |
54 | REPL_I32, |
55 | REPL_F32, // Replicate subregister to other half. |
56 | |
57 | // Annotation as a wrapper. LEGALAVL(VL) means that VL refers to 64bit of |
58 | // data, whereas the raw EVL coming in from VP nodes always refers to number |
59 | // of elements, regardless of their size. |
60 | LEGALAVL, |
61 | |
62 | // VVP_* nodes. |
63 | #define ADD_VVP_OP(VVP_NAME, ...) VVP_NAME, |
64 | #include "VVPNodes.def" |
65 | }; |
66 | } |
67 | |
68 | /// Convert a DAG integer condition code to a VE ICC condition. |
69 | inline static VECC::CondCode intCondCode2Icc(ISD::CondCode CC) { |
70 | switch (CC) { |
71 | default: |
72 | llvm_unreachable("Unknown integer condition code!" ); |
73 | case ISD::SETEQ: |
74 | return VECC::CC_IEQ; |
75 | case ISD::SETNE: |
76 | return VECC::CC_INE; |
77 | case ISD::SETLT: |
78 | return VECC::CC_IL; |
79 | case ISD::SETGT: |
80 | return VECC::CC_IG; |
81 | case ISD::SETLE: |
82 | return VECC::CC_ILE; |
83 | case ISD::SETGE: |
84 | return VECC::CC_IGE; |
85 | case ISD::SETULT: |
86 | return VECC::CC_IL; |
87 | case ISD::SETULE: |
88 | return VECC::CC_ILE; |
89 | case ISD::SETUGT: |
90 | return VECC::CC_IG; |
91 | case ISD::SETUGE: |
92 | return VECC::CC_IGE; |
93 | } |
94 | } |
95 | |
96 | /// Convert a DAG floating point condition code to a VE FCC condition. |
97 | inline static VECC::CondCode fpCondCode2Fcc(ISD::CondCode CC) { |
98 | switch (CC) { |
99 | default: |
100 | llvm_unreachable("Unknown fp condition code!" ); |
101 | case ISD::SETFALSE: |
102 | return VECC::CC_AF; |
103 | case ISD::SETEQ: |
104 | case ISD::SETOEQ: |
105 | return VECC::CC_EQ; |
106 | case ISD::SETNE: |
107 | case ISD::SETONE: |
108 | return VECC::CC_NE; |
109 | case ISD::SETLT: |
110 | case ISD::SETOLT: |
111 | return VECC::CC_L; |
112 | case ISD::SETGT: |
113 | case ISD::SETOGT: |
114 | return VECC::CC_G; |
115 | case ISD::SETLE: |
116 | case ISD::SETOLE: |
117 | return VECC::CC_LE; |
118 | case ISD::SETGE: |
119 | case ISD::SETOGE: |
120 | return VECC::CC_GE; |
121 | case ISD::SETO: |
122 | return VECC::CC_NUM; |
123 | case ISD::SETUO: |
124 | return VECC::CC_NAN; |
125 | case ISD::SETUEQ: |
126 | return VECC::CC_EQNAN; |
127 | case ISD::SETUNE: |
128 | return VECC::CC_NENAN; |
129 | case ISD::SETULT: |
130 | return VECC::CC_LNAN; |
131 | case ISD::SETUGT: |
132 | return VECC::CC_GNAN; |
133 | case ISD::SETULE: |
134 | return VECC::CC_LENAN; |
135 | case ISD::SETUGE: |
136 | return VECC::CC_GENAN; |
137 | case ISD::SETTRUE: |
138 | return VECC::CC_AT; |
139 | } |
140 | } |
141 | |
142 | /// getImmVal - get immediate representation of integer value |
143 | inline static uint64_t getImmVal(const ConstantSDNode *N) { |
144 | return N->getSExtValue(); |
145 | } |
146 | |
147 | /// getFpImmVal - get immediate representation of floating point value |
148 | inline static uint64_t getFpImmVal(const ConstantFPSDNode *N) { |
149 | const APInt &Imm = N->getValueAPF().bitcastToAPInt(); |
150 | uint64_t Val = Imm.getZExtValue(); |
151 | if (Imm.getBitWidth() == 32) { |
152 | // Immediate value of float place places at higher bits on VE. |
153 | Val <<= 32; |
154 | } |
155 | return Val; |
156 | } |
157 | |
158 | class VECustomDAG; |
159 | |
160 | class VETargetLowering : public TargetLowering { |
161 | const VESubtarget *Subtarget; |
162 | |
163 | void initRegisterClasses(); |
164 | void initSPUActions(); |
165 | void initVPUActions(); |
166 | |
167 | public: |
168 | VETargetLowering(const TargetMachine &TM, const VESubtarget &STI); |
169 | |
170 | const char *getTargetNodeName(unsigned Opcode) const override; |
171 | MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override { |
172 | return MVT::i32; |
173 | } |
174 | |
175 | Register getRegisterByName(const char *RegName, LLT VT, |
176 | const MachineFunction &MF) const override; |
177 | |
178 | /// getSetCCResultType - Return the ISD::SETCC ValueType |
179 | EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, |
180 | EVT VT) const override; |
181 | |
182 | SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, |
183 | bool isVarArg, |
184 | const SmallVectorImpl<ISD::InputArg> &Ins, |
185 | const SDLoc &dl, SelectionDAG &DAG, |
186 | SmallVectorImpl<SDValue> &InVals) const override; |
187 | |
188 | SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, |
189 | SmallVectorImpl<SDValue> &InVals) const override; |
190 | |
191 | bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, |
192 | bool isVarArg, |
193 | const SmallVectorImpl<ISD::OutputArg> &ArgsFlags, |
194 | LLVMContext &Context) const override; |
195 | SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, |
196 | const SmallVectorImpl<ISD::OutputArg> &Outs, |
197 | const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl, |
198 | SelectionDAG &DAG) const override; |
199 | |
200 | /// Helper functions for atomic operations. |
201 | bool shouldInsertFencesForAtomic(const Instruction *I) const override { |
202 | // VE uses release consistency, so need fence for each atomics. |
203 | return true; |
204 | } |
205 | Instruction *emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, |
206 | AtomicOrdering Ord) const override; |
207 | Instruction *emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, |
208 | AtomicOrdering Ord) const override; |
209 | TargetLoweringBase::AtomicExpansionKind |
210 | shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override; |
211 | ISD::NodeType getExtendForAtomicOps() const override { |
212 | return ISD::ANY_EXTEND; |
213 | } |
214 | |
215 | /// Custom Lower { |
216 | TargetLoweringBase::LegalizeAction |
217 | getCustomOperationAction(SDNode &) const override; |
218 | |
219 | SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; |
220 | unsigned getJumpTableEncoding() const override; |
221 | const MCExpr *LowerCustomJumpTableEntry(const MachineJumpTableInfo *MJTI, |
222 | const MachineBasicBlock *MBB, |
223 | unsigned Uid, |
224 | MCContext &Ctx) const override; |
225 | SDValue getPICJumpTableRelocBase(SDValue Table, |
226 | SelectionDAG &DAG) const override; |
227 | // VE doesn't need getPICJumpTableRelocBaseExpr since it is used for only |
228 | // EK_LabelDifference32. |
229 | |
230 | SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const; |
231 | SDValue lowerATOMIC_SWAP(SDValue Op, SelectionDAG &DAG) const; |
232 | SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; |
233 | SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const; |
234 | SDValue lowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const; |
235 | SDValue lowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG) const; |
236 | SDValue lowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const; |
237 | SDValue lowerEH_SJLJ_SETUP_DISPATCH(SDValue Op, SelectionDAG &DAG) const; |
238 | SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; |
239 | SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; |
240 | SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; |
241 | SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const; |
242 | SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const; |
243 | SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const; |
244 | SDValue lowerToTLSGeneralDynamicModel(SDValue Op, SelectionDAG &DAG) const; |
245 | SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const; |
246 | SDValue lowerVAARG(SDValue Op, SelectionDAG &DAG) const; |
247 | |
248 | SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const; |
249 | SDValue (SDValue Op, SelectionDAG &DAG) const; |
250 | SDValue lowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const; |
251 | /// } Custom Lower |
252 | |
253 | /// Replace the results of node with an illegal result |
254 | /// type with new values built out of custom code. |
255 | /// |
256 | void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results, |
257 | SelectionDAG &DAG) const override; |
258 | |
259 | /// Custom Inserter { |
260 | MachineBasicBlock * |
261 | EmitInstrWithCustomInserter(MachineInstr &MI, |
262 | MachineBasicBlock *MBB) const override; |
263 | MachineBasicBlock *emitEHSjLjLongJmp(MachineInstr &MI, |
264 | MachineBasicBlock *MBB) const; |
265 | MachineBasicBlock *emitEHSjLjSetJmp(MachineInstr &MI, |
266 | MachineBasicBlock *MBB) const; |
267 | MachineBasicBlock *emitSjLjDispatchBlock(MachineInstr &MI, |
268 | MachineBasicBlock *BB) const; |
269 | |
270 | void setupEntryBlockForSjLj(MachineInstr &MI, MachineBasicBlock *MBB, |
271 | MachineBasicBlock *DispatchBB, int FI, |
272 | int Offset) const; |
273 | // Setup basic block address. |
274 | Register prepareMBB(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, |
275 | MachineBasicBlock *TargetBB, const DebugLoc &DL) const; |
276 | // Prepare function/variable address. |
277 | Register prepareSymbol(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, |
278 | StringRef Symbol, const DebugLoc &DL, bool IsLocal, |
279 | bool IsCall) const; |
280 | /// } Custom Inserter |
281 | |
282 | /// VVP Lowering { |
283 | SDValue lowerToVVP(SDValue Op, SelectionDAG &DAG) const; |
284 | SDValue lowerVVP_LOAD_STORE(SDValue Op, VECustomDAG &) const; |
285 | SDValue lowerVVP_GATHER_SCATTER(SDValue Op, VECustomDAG &) const; |
286 | |
287 | SDValue legalizeInternalVectorOp(SDValue Op, SelectionDAG &DAG) const; |
288 | SDValue legalizeInternalLoadStoreOp(SDValue Op, VECustomDAG &CDAG) const; |
289 | SDValue splitVectorOp(SDValue Op, VECustomDAG &CDAG) const; |
290 | SDValue splitPackedLoadStore(SDValue Op, VECustomDAG &CDAG) const; |
291 | SDValue legalizePackedAVL(SDValue Op, VECustomDAG &CDAG) const; |
292 | SDValue splitMaskArithmetic(SDValue Op, SelectionDAG &DAG) const; |
293 | /// } VVPLowering |
294 | |
295 | /// Custom DAGCombine { |
296 | SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; |
297 | |
298 | SDValue combineSelect(SDNode *N, DAGCombinerInfo &DCI) const; |
299 | SDValue combineSelectCC(SDNode *N, DAGCombinerInfo &DCI) const; |
300 | SDValue combineTRUNCATE(SDNode *N, DAGCombinerInfo &DCI) const; |
301 | /// } Custom DAGCombine |
302 | |
303 | SDValue withTargetFlags(SDValue Op, unsigned TF, SelectionDAG &DAG) const; |
304 | SDValue makeHiLoPair(SDValue Op, unsigned HiTF, unsigned LoTF, |
305 | SelectionDAG &DAG) const; |
306 | SDValue makeAddress(SDValue Op, SelectionDAG &DAG) const; |
307 | |
308 | bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; |
309 | bool isFPImmLegal(const APFloat &Imm, EVT VT, |
310 | bool ForCodeSize) const override; |
311 | /// Returns true if the target allows unaligned memory accesses of the |
312 | /// specified type. |
313 | bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AS, Align A, |
314 | MachineMemOperand::Flags Flags, |
315 | unsigned *Fast) const override; |
316 | |
317 | /// Inline Assembly { |
318 | |
319 | ConstraintType getConstraintType(StringRef Constraint) const override; |
320 | std::pair<unsigned, const TargetRegisterClass *> |
321 | getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, |
322 | StringRef Constraint, MVT VT) const override; |
323 | |
324 | /// } Inline Assembly |
325 | |
326 | /// Target Optimization { |
327 | |
328 | // Return lower limit for number of blocks in a jump table. |
329 | unsigned getMinimumJumpTableEntries() const override; |
330 | |
331 | // SX-Aurora VE's s/udiv is 5-9 times slower than multiply. |
332 | bool isIntDivCheap(EVT, AttributeList) const override { return false; } |
333 | // VE doesn't have rem. |
334 | bool hasStandaloneRem(EVT) const override { return false; } |
335 | // VE LDZ instruction returns 64 if the input is zero. |
336 | bool isCheapToSpeculateCtlz(Type *) const override { return true; } |
337 | // VE LDZ instruction is fast. |
338 | bool isCtlzFast() const override { return true; } |
339 | // VE has NND instruction. |
340 | bool hasAndNot(SDValue Y) const override; |
341 | |
342 | /// } Target Optimization |
343 | }; |
344 | } // namespace llvm |
345 | |
346 | #endif // LLVM_LIB_TARGET_VE_VEISELLOWERING_H |
347 | |