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
23/// Convert a DAG integer condition code to a VE ICC condition.
24inline static VECC::CondCode intCondCode2Icc(ISD::CondCode CC) {
25 switch (CC) {
26 default:
27 llvm_unreachable("Unknown integer condition code!");
28 case ISD::SETEQ:
29 return VECC::CC_IEQ;
30 case ISD::SETNE:
31 return VECC::CC_INE;
32 case ISD::SETLT:
33 return VECC::CC_IL;
34 case ISD::SETGT:
35 return VECC::CC_IG;
36 case ISD::SETLE:
37 return VECC::CC_ILE;
38 case ISD::SETGE:
39 return VECC::CC_IGE;
40 case ISD::SETULT:
41 return VECC::CC_IL;
42 case ISD::SETULE:
43 return VECC::CC_ILE;
44 case ISD::SETUGT:
45 return VECC::CC_IG;
46 case ISD::SETUGE:
47 return VECC::CC_IGE;
48 }
49}
50
51/// Convert a DAG floating point condition code to a VE FCC condition.
52inline static VECC::CondCode fpCondCode2Fcc(ISD::CondCode CC) {
53 switch (CC) {
54 default:
55 llvm_unreachable("Unknown fp condition code!");
56 case ISD::SETFALSE:
57 return VECC::CC_AF;
58 case ISD::SETEQ:
59 case ISD::SETOEQ:
60 return VECC::CC_EQ;
61 case ISD::SETNE:
62 case ISD::SETONE:
63 return VECC::CC_NE;
64 case ISD::SETLT:
65 case ISD::SETOLT:
66 return VECC::CC_L;
67 case ISD::SETGT:
68 case ISD::SETOGT:
69 return VECC::CC_G;
70 case ISD::SETLE:
71 case ISD::SETOLE:
72 return VECC::CC_LE;
73 case ISD::SETGE:
74 case ISD::SETOGE:
75 return VECC::CC_GE;
76 case ISD::SETO:
77 return VECC::CC_NUM;
78 case ISD::SETUO:
79 return VECC::CC_NAN;
80 case ISD::SETUEQ:
81 return VECC::CC_EQNAN;
82 case ISD::SETUNE:
83 return VECC::CC_NENAN;
84 case ISD::SETULT:
85 return VECC::CC_LNAN;
86 case ISD::SETUGT:
87 return VECC::CC_GNAN;
88 case ISD::SETULE:
89 return VECC::CC_LENAN;
90 case ISD::SETUGE:
91 return VECC::CC_GENAN;
92 case ISD::SETTRUE:
93 return VECC::CC_AT;
94 }
95}
96
97/// getImmVal - get immediate representation of integer value
98inline static uint64_t getImmVal(const ConstantSDNode *N) {
99 return N->getSExtValue();
100}
101
102/// getFpImmVal - get immediate representation of floating point value
103inline static uint64_t getFpImmVal(const ConstantFPSDNode *N) {
104 const APInt &Imm = N->getValueAPF().bitcastToAPInt();
105 uint64_t Val = Imm.getZExtValue();
106 if (Imm.getBitWidth() == 32) {
107 // Immediate value of float place places at higher bits on VE.
108 Val <<= 32;
109 }
110 return Val;
111}
112
113class VECustomDAG;
114
115class VETargetLowering : public TargetLowering {
116 const VESubtarget *Subtarget;
117
118 void initRegisterClasses();
119 void initSPUActions();
120 void initVPUActions();
121
122public:
123 VETargetLowering(const TargetMachine &TM, const VESubtarget &STI);
124
125 MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override {
126 return MVT::i32;
127 }
128
129 Register getRegisterByName(const char *RegName, LLT VT,
130 const MachineFunction &MF) const override;
131
132 /// getSetCCResultType - Return the ISD::SETCC ValueType
133 EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context,
134 EVT VT) const override;
135
136 SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
137 bool isVarArg,
138 const SmallVectorImpl<ISD::InputArg> &Ins,
139 const SDLoc &dl, SelectionDAG &DAG,
140 SmallVectorImpl<SDValue> &InVals) const override;
141
142 SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
143 SmallVectorImpl<SDValue> &InVals) const override;
144
145 bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
146 bool isVarArg,
147 const SmallVectorImpl<ISD::OutputArg> &ArgsFlags,
148 LLVMContext &Context,
149 const Type *RetTy) const override;
150 SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
151 const SmallVectorImpl<ISD::OutputArg> &Outs,
152 const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl,
153 SelectionDAG &DAG) const override;
154
155 /// Helper functions for atomic operations.
156 bool shouldInsertFencesForAtomic(const Instruction *I) const override {
157 // VE uses release consistency, so need fence for each atomics.
158 return true;
159 }
160 Instruction *emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst,
161 AtomicOrdering Ord) const override;
162 Instruction *emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst,
163 AtomicOrdering Ord) const override;
164 TargetLoweringBase::AtomicExpansionKind
165 shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override;
166 ISD::NodeType getExtendForAtomicOps() const override {
167 return ISD::ANY_EXTEND;
168 }
169
170 /// Custom Lower {
171 TargetLoweringBase::LegalizeAction
172 getCustomOperationAction(SDNode &) const override;
173
174 SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
175 unsigned getJumpTableEncoding() const override;
176 const MCExpr *LowerCustomJumpTableEntry(const MachineJumpTableInfo *MJTI,
177 const MachineBasicBlock *MBB,
178 unsigned Uid,
179 MCContext &Ctx) const override;
180 SDValue getPICJumpTableRelocBase(SDValue Table,
181 SelectionDAG &DAG) const override;
182 // VE doesn't need getPICJumpTableRelocBaseExpr since it is used for only
183 // EK_LabelDifference32.
184
185 SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const;
186 SDValue lowerATOMIC_SWAP(SDValue Op, SelectionDAG &DAG) const;
187 SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
188 SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
189 SDValue lowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
190 SDValue lowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG) const;
191 SDValue lowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const;
192 SDValue lowerEH_SJLJ_SETUP_DISPATCH(SDValue Op, SelectionDAG &DAG) const;
193 SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
194 SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
195 SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
196 SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
197 SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const;
198 SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const;
199 SDValue lowerToTLSGeneralDynamicModel(SDValue Op, SelectionDAG &DAG) const;
200 SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const;
201 SDValue lowerVAARG(SDValue Op, SelectionDAG &DAG) const;
202
203 SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const;
204 SDValue lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
205 SDValue lowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
206 /// } Custom Lower
207
208 /// Replace the results of node with an illegal result
209 /// type with new values built out of custom code.
210 ///
211 void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,
212 SelectionDAG &DAG) const override;
213
214 /// Custom Inserter {
215 MachineBasicBlock *
216 EmitInstrWithCustomInserter(MachineInstr &MI,
217 MachineBasicBlock *MBB) const override;
218 MachineBasicBlock *emitEHSjLjLongJmp(MachineInstr &MI,
219 MachineBasicBlock *MBB) const;
220 MachineBasicBlock *emitEHSjLjSetJmp(MachineInstr &MI,
221 MachineBasicBlock *MBB) const;
222 MachineBasicBlock *emitSjLjDispatchBlock(MachineInstr &MI,
223 MachineBasicBlock *BB) const;
224
225 void setupEntryBlockForSjLj(MachineInstr &MI, MachineBasicBlock *MBB,
226 MachineBasicBlock *DispatchBB, int FI,
227 int Offset) const;
228 // Setup basic block address.
229 Register prepareMBB(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
230 MachineBasicBlock *TargetBB, const DebugLoc &DL) const;
231 // Prepare function/variable address.
232 Register prepareSymbol(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
233 StringRef Symbol, const DebugLoc &DL, bool IsLocal,
234 bool IsCall) const;
235 /// } Custom Inserter
236
237 /// VVP Lowering {
238 SDValue lowerToVVP(SDValue Op, SelectionDAG &DAG) const;
239 SDValue lowerVVP_LOAD_STORE(SDValue Op, VECustomDAG &) const;
240 SDValue lowerVVP_GATHER_SCATTER(SDValue Op, VECustomDAG &) const;
241
242 SDValue legalizeInternalVectorOp(SDValue Op, SelectionDAG &DAG) const;
243 SDValue legalizeInternalLoadStoreOp(SDValue Op, VECustomDAG &CDAG) const;
244 SDValue splitVectorOp(SDValue Op, VECustomDAG &CDAG) const;
245 SDValue splitPackedLoadStore(SDValue Op, VECustomDAG &CDAG) const;
246 SDValue legalizePackedAVL(SDValue Op, VECustomDAG &CDAG) const;
247 SDValue splitMaskArithmetic(SDValue Op, SelectionDAG &DAG) const;
248 /// } VVPLowering
249
250 /// Custom DAGCombine {
251 SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
252
253 SDValue combineSelect(SDNode *N, DAGCombinerInfo &DCI) const;
254 SDValue combineSelectCC(SDNode *N, DAGCombinerInfo &DCI) const;
255 SDValue combineTRUNCATE(SDNode *N, DAGCombinerInfo &DCI) const;
256 /// } Custom DAGCombine
257
258 SDValue withTargetFlags(SDValue Op, unsigned TF, SelectionDAG &DAG) const;
259 SDValue makeHiLoPair(SDValue Op, unsigned HiTF, unsigned LoTF,
260 SelectionDAG &DAG) const;
261 SDValue makeAddress(SDValue Op, SelectionDAG &DAG) const;
262
263 bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
264 bool isFPImmLegal(const APFloat &Imm, EVT VT,
265 bool ForCodeSize) const override;
266 /// Returns true if the target allows unaligned memory accesses of the
267 /// specified type.
268 bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AS, Align A,
269 MachineMemOperand::Flags Flags,
270 unsigned *Fast) const override;
271
272 /// Inline Assembly {
273
274 ConstraintType getConstraintType(StringRef Constraint) const override;
275 std::pair<unsigned, const TargetRegisterClass *>
276 getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
277 StringRef Constraint, MVT VT) const override;
278
279 /// } Inline Assembly
280
281 /// Target Optimization {
282
283 // Return lower limit for number of blocks in a jump table.
284 unsigned getMinimumJumpTableEntries() const override;
285
286 // SX-Aurora VE's s/udiv is 5-9 times slower than multiply.
287 bool isIntDivCheap(EVT, AttributeList) const override { return false; }
288 // VE doesn't have rem.
289 bool hasStandaloneRem(EVT) const override { return false; }
290 // VE LDZ instruction returns 64 if the input is zero.
291 bool isCheapToSpeculateCtlz(Type *) const override { return true; }
292 // VE LDZ instruction is fast.
293 bool isCtlzFast() const override { return true; }
294 // VE has NND instruction.
295 bool hasAndNot(SDValue Y) const override;
296 /// } Target Optimization
297};
298} // namespace llvm
299
300#endif // LLVM_LIB_TARGET_VE_VEISELLOWERING_H
301