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
20namespace llvm {
21class VESubtarget;
22
23namespace VEISD {
24enum 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.
69inline 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.
97inline 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
143inline static uint64_t getImmVal(const ConstantSDNode *N) {
144 return N->getSExtValue();
145}
146
147/// getFpImmVal - get immediate representation of floating point value
148inline 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
158class VECustomDAG;
159
160class VETargetLowering : public TargetLowering {
161 const VESubtarget *Subtarget;
162
163 void initRegisterClasses();
164 void initSPUActions();
165 void initVPUActions();
166
167public:
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 lowerEXTRACT_VECTOR_ELT(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