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