1480093f4SDimitry Andric //===-- VEISelLowering.cpp - VE DAG Lowering Implementation ---------------===//
2480093f4SDimitry Andric //
3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6480093f4SDimitry Andric //
7480093f4SDimitry Andric //===----------------------------------------------------------------------===//
8480093f4SDimitry Andric //
9480093f4SDimitry Andric // This file implements the interfaces that VE uses to lower LLVM code into a
10480093f4SDimitry Andric // selection DAG.
11480093f4SDimitry Andric //
12480093f4SDimitry Andric //===----------------------------------------------------------------------===//
13480093f4SDimitry Andric 
14480093f4SDimitry Andric #include "VEISelLowering.h"
155ffd83dbSDimitry Andric #include "MCTargetDesc/VEMCExpr.h"
1604eeddc0SDimitry Andric #include "VECustomDAG.h"
17e8d8bef9SDimitry Andric #include "VEInstrBuilder.h"
185ffd83dbSDimitry Andric #include "VEMachineFunctionInfo.h"
19480093f4SDimitry Andric #include "VERegisterInfo.h"
20480093f4SDimitry Andric #include "VETargetMachine.h"
21480093f4SDimitry Andric #include "llvm/ADT/StringSwitch.h"
22480093f4SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h"
23480093f4SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
24480093f4SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
25480093f4SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
26e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineJumpTableInfo.h"
27480093f4SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
28480093f4SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
29480093f4SDimitry Andric #include "llvm/CodeGen/SelectionDAG.h"
30480093f4SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
31480093f4SDimitry Andric #include "llvm/IR/DerivedTypes.h"
32480093f4SDimitry Andric #include "llvm/IR/Function.h"
33fe6060f1SDimitry Andric #include "llvm/IR/IRBuilder.h"
34480093f4SDimitry Andric #include "llvm/IR/Module.h"
35480093f4SDimitry Andric #include "llvm/Support/ErrorHandling.h"
36480093f4SDimitry Andric #include "llvm/Support/KnownBits.h"
37480093f4SDimitry Andric using namespace llvm;
38480093f4SDimitry Andric 
39480093f4SDimitry Andric #define DEBUG_TYPE "ve-lower"
40480093f4SDimitry Andric 
41480093f4SDimitry Andric //===----------------------------------------------------------------------===//
42480093f4SDimitry Andric // Calling Convention Implementation
43480093f4SDimitry Andric //===----------------------------------------------------------------------===//
44480093f4SDimitry Andric 
45e8d8bef9SDimitry Andric #include "VEGenCallingConv.inc"
46e8d8bef9SDimitry Andric 
getReturnCC(CallingConv::ID CallConv)47e8d8bef9SDimitry Andric CCAssignFn *getReturnCC(CallingConv::ID CallConv) {
48e8d8bef9SDimitry Andric   switch (CallConv) {
495ffd83dbSDimitry Andric   default:
50e8d8bef9SDimitry Andric     return RetCC_VE_C;
51e8d8bef9SDimitry Andric   case CallingConv::Fast:
52e8d8bef9SDimitry Andric     return RetCC_VE_Fast;
535ffd83dbSDimitry Andric   }
545ffd83dbSDimitry Andric }
555ffd83dbSDimitry Andric 
getParamCC(CallingConv::ID CallConv,bool IsVarArg)56e8d8bef9SDimitry Andric CCAssignFn *getParamCC(CallingConv::ID CallConv, bool IsVarArg) {
57e8d8bef9SDimitry Andric   if (IsVarArg)
58e8d8bef9SDimitry Andric     return CC_VE2;
59e8d8bef9SDimitry Andric   switch (CallConv) {
60e8d8bef9SDimitry Andric   default:
61e8d8bef9SDimitry Andric     return CC_VE_C;
62e8d8bef9SDimitry Andric   case CallingConv::Fast:
63e8d8bef9SDimitry Andric     return CC_VE_Fast;
64e8d8bef9SDimitry Andric   }
65e8d8bef9SDimitry Andric }
66480093f4SDimitry Andric 
CanLowerReturn(CallingConv::ID CallConv,MachineFunction & MF,bool IsVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,LLVMContext & Context) const67480093f4SDimitry Andric bool VETargetLowering::CanLowerReturn(
68480093f4SDimitry Andric     CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
69480093f4SDimitry Andric     const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
70e8d8bef9SDimitry Andric   CCAssignFn *RetCC = getReturnCC(CallConv);
715ffd83dbSDimitry Andric   SmallVector<CCValAssign, 16> RVLocs;
725ffd83dbSDimitry Andric   CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
735ffd83dbSDimitry Andric   return CCInfo.CheckReturn(Outs, RetCC);
74480093f4SDimitry Andric }
75480093f4SDimitry Andric 
76e8d8bef9SDimitry Andric static const MVT AllVectorVTs[] = {MVT::v256i32, MVT::v512i32, MVT::v256i64,
77e8d8bef9SDimitry Andric                                    MVT::v256f32, MVT::v512f32, MVT::v256f64};
78e8d8bef9SDimitry Andric 
7981ad6265SDimitry Andric static const MVT AllMaskVTs[] = {MVT::v256i1, MVT::v512i1};
8081ad6265SDimitry Andric 
81e8d8bef9SDimitry Andric static const MVT AllPackedVTs[] = {MVT::v512i32, MVT::v512f32};
82e8d8bef9SDimitry Andric 
initRegisterClasses()83e8d8bef9SDimitry Andric void VETargetLowering::initRegisterClasses() {
84e8d8bef9SDimitry Andric   // Set up the register classes.
85e8d8bef9SDimitry Andric   addRegisterClass(MVT::i32, &VE::I32RegClass);
86e8d8bef9SDimitry Andric   addRegisterClass(MVT::i64, &VE::I64RegClass);
87e8d8bef9SDimitry Andric   addRegisterClass(MVT::f32, &VE::F32RegClass);
88e8d8bef9SDimitry Andric   addRegisterClass(MVT::f64, &VE::I64RegClass);
89e8d8bef9SDimitry Andric   addRegisterClass(MVT::f128, &VE::F128RegClass);
90e8d8bef9SDimitry Andric 
91e8d8bef9SDimitry Andric   if (Subtarget->enableVPU()) {
92e8d8bef9SDimitry Andric     for (MVT VecVT : AllVectorVTs)
93e8d8bef9SDimitry Andric       addRegisterClass(VecVT, &VE::V64RegClass);
94e8d8bef9SDimitry Andric     addRegisterClass(MVT::v256i1, &VE::VMRegClass);
95e8d8bef9SDimitry Andric     addRegisterClass(MVT::v512i1, &VE::VM512RegClass);
96e8d8bef9SDimitry Andric   }
97e8d8bef9SDimitry Andric }
98e8d8bef9SDimitry Andric 
initSPUActions()99e8d8bef9SDimitry Andric void VETargetLowering::initSPUActions() {
100e8d8bef9SDimitry Andric   const auto &TM = getTargetMachine();
101e8d8bef9SDimitry Andric   /// Load & Store {
102e8d8bef9SDimitry Andric 
103e8d8bef9SDimitry Andric   // VE doesn't have i1 sign extending load.
104e8d8bef9SDimitry Andric   for (MVT VT : MVT::integer_valuetypes()) {
105e8d8bef9SDimitry Andric     setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote);
106e8d8bef9SDimitry Andric     setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote);
107e8d8bef9SDimitry Andric     setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote);
108e8d8bef9SDimitry Andric     setTruncStoreAction(VT, MVT::i1, Expand);
109e8d8bef9SDimitry Andric   }
110e8d8bef9SDimitry Andric 
111e8d8bef9SDimitry Andric   // VE doesn't have floating point extload/truncstore, so expand them.
112e8d8bef9SDimitry Andric   for (MVT FPVT : MVT::fp_valuetypes()) {
113e8d8bef9SDimitry Andric     for (MVT OtherFPVT : MVT::fp_valuetypes()) {
114e8d8bef9SDimitry Andric       setLoadExtAction(ISD::EXTLOAD, FPVT, OtherFPVT, Expand);
115e8d8bef9SDimitry Andric       setTruncStoreAction(FPVT, OtherFPVT, Expand);
116e8d8bef9SDimitry Andric     }
117e8d8bef9SDimitry Andric   }
118e8d8bef9SDimitry Andric 
119e8d8bef9SDimitry Andric   // VE doesn't have fp128 load/store, so expand them in custom lower.
120e8d8bef9SDimitry Andric   setOperationAction(ISD::LOAD, MVT::f128, Custom);
121e8d8bef9SDimitry Andric   setOperationAction(ISD::STORE, MVT::f128, Custom);
122e8d8bef9SDimitry Andric 
123e8d8bef9SDimitry Andric   /// } Load & Store
124e8d8bef9SDimitry Andric 
125e8d8bef9SDimitry Andric   // Custom legalize address nodes into LO/HI parts.
126e8d8bef9SDimitry Andric   MVT PtrVT = MVT::getIntegerVT(TM.getPointerSizeInBits(0));
127e8d8bef9SDimitry Andric   setOperationAction(ISD::BlockAddress, PtrVT, Custom);
128e8d8bef9SDimitry Andric   setOperationAction(ISD::GlobalAddress, PtrVT, Custom);
129e8d8bef9SDimitry Andric   setOperationAction(ISD::GlobalTLSAddress, PtrVT, Custom);
130e8d8bef9SDimitry Andric   setOperationAction(ISD::ConstantPool, PtrVT, Custom);
131e8d8bef9SDimitry Andric   setOperationAction(ISD::JumpTable, PtrVT, Custom);
132e8d8bef9SDimitry Andric 
133e8d8bef9SDimitry Andric   /// VAARG handling {
134e8d8bef9SDimitry Andric   setOperationAction(ISD::VASTART, MVT::Other, Custom);
135e8d8bef9SDimitry Andric   // VAARG needs to be lowered to access with 8 bytes alignment.
136e8d8bef9SDimitry Andric   setOperationAction(ISD::VAARG, MVT::Other, Custom);
137e8d8bef9SDimitry Andric   // Use the default implementation.
138e8d8bef9SDimitry Andric   setOperationAction(ISD::VACOPY, MVT::Other, Expand);
139e8d8bef9SDimitry Andric   setOperationAction(ISD::VAEND, MVT::Other, Expand);
140e8d8bef9SDimitry Andric   /// } VAARG handling
141e8d8bef9SDimitry Andric 
142e8d8bef9SDimitry Andric   /// Stack {
143e8d8bef9SDimitry Andric   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom);
144e8d8bef9SDimitry Andric   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Custom);
145e8d8bef9SDimitry Andric 
146e8d8bef9SDimitry Andric   // Use the default implementation.
147e8d8bef9SDimitry Andric   setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
148e8d8bef9SDimitry Andric   setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
149e8d8bef9SDimitry Andric   /// } Stack
150e8d8bef9SDimitry Andric 
151e8d8bef9SDimitry Andric   /// Branch {
152e8d8bef9SDimitry Andric 
153e8d8bef9SDimitry Andric   // VE doesn't have BRCOND
154e8d8bef9SDimitry Andric   setOperationAction(ISD::BRCOND, MVT::Other, Expand);
155e8d8bef9SDimitry Andric 
156e8d8bef9SDimitry Andric   // BR_JT is not implemented yet.
157e8d8bef9SDimitry Andric   setOperationAction(ISD::BR_JT, MVT::Other, Expand);
158e8d8bef9SDimitry Andric 
159e8d8bef9SDimitry Andric   /// } Branch
160e8d8bef9SDimitry Andric 
161e8d8bef9SDimitry Andric   /// Int Ops {
162e8d8bef9SDimitry Andric   for (MVT IntVT : {MVT::i32, MVT::i64}) {
163e8d8bef9SDimitry Andric     // VE has no REM or DIVREM operations.
164e8d8bef9SDimitry Andric     setOperationAction(ISD::UREM, IntVT, Expand);
165e8d8bef9SDimitry Andric     setOperationAction(ISD::SREM, IntVT, Expand);
166e8d8bef9SDimitry Andric     setOperationAction(ISD::SDIVREM, IntVT, Expand);
167e8d8bef9SDimitry Andric     setOperationAction(ISD::UDIVREM, IntVT, Expand);
168e8d8bef9SDimitry Andric 
169e8d8bef9SDimitry Andric     // VE has no SHL_PARTS/SRA_PARTS/SRL_PARTS operations.
170e8d8bef9SDimitry Andric     setOperationAction(ISD::SHL_PARTS, IntVT, Expand);
171e8d8bef9SDimitry Andric     setOperationAction(ISD::SRA_PARTS, IntVT, Expand);
172e8d8bef9SDimitry Andric     setOperationAction(ISD::SRL_PARTS, IntVT, Expand);
173e8d8bef9SDimitry Andric 
174e8d8bef9SDimitry Andric     // VE has no MULHU/S or U/SMUL_LOHI operations.
175e8d8bef9SDimitry Andric     // TODO: Use MPD instruction to implement SMUL_LOHI for i32 type.
176e8d8bef9SDimitry Andric     setOperationAction(ISD::MULHU, IntVT, Expand);
177e8d8bef9SDimitry Andric     setOperationAction(ISD::MULHS, IntVT, Expand);
178e8d8bef9SDimitry Andric     setOperationAction(ISD::UMUL_LOHI, IntVT, Expand);
179e8d8bef9SDimitry Andric     setOperationAction(ISD::SMUL_LOHI, IntVT, Expand);
180e8d8bef9SDimitry Andric 
181e8d8bef9SDimitry Andric     // VE has no CTTZ, ROTL, ROTR operations.
182e8d8bef9SDimitry Andric     setOperationAction(ISD::CTTZ, IntVT, Expand);
183e8d8bef9SDimitry Andric     setOperationAction(ISD::ROTL, IntVT, Expand);
184e8d8bef9SDimitry Andric     setOperationAction(ISD::ROTR, IntVT, Expand);
185e8d8bef9SDimitry Andric 
186e8d8bef9SDimitry Andric     // VE has 64 bits instruction which works as i64 BSWAP operation.  This
187e8d8bef9SDimitry Andric     // instruction works fine as i32 BSWAP operation with an additional
188e8d8bef9SDimitry Andric     // parameter.  Use isel patterns to lower BSWAP.
189e8d8bef9SDimitry Andric     setOperationAction(ISD::BSWAP, IntVT, Legal);
190e8d8bef9SDimitry Andric 
191e8d8bef9SDimitry Andric     // VE has only 64 bits instructions which work as i64 BITREVERSE/CTLZ/CTPOP
192e8d8bef9SDimitry Andric     // operations.  Use isel patterns for i64, promote for i32.
193e8d8bef9SDimitry Andric     LegalizeAction Act = (IntVT == MVT::i32) ? Promote : Legal;
194e8d8bef9SDimitry Andric     setOperationAction(ISD::BITREVERSE, IntVT, Act);
195e8d8bef9SDimitry Andric     setOperationAction(ISD::CTLZ, IntVT, Act);
196e8d8bef9SDimitry Andric     setOperationAction(ISD::CTLZ_ZERO_UNDEF, IntVT, Act);
197e8d8bef9SDimitry Andric     setOperationAction(ISD::CTPOP, IntVT, Act);
198e8d8bef9SDimitry Andric 
199e8d8bef9SDimitry Andric     // VE has only 64 bits instructions which work as i64 AND/OR/XOR operations.
200e8d8bef9SDimitry Andric     // Use isel patterns for i64, promote for i32.
201e8d8bef9SDimitry Andric     setOperationAction(ISD::AND, IntVT, Act);
202e8d8bef9SDimitry Andric     setOperationAction(ISD::OR, IntVT, Act);
203e8d8bef9SDimitry Andric     setOperationAction(ISD::XOR, IntVT, Act);
204bdd1243dSDimitry Andric 
205bdd1243dSDimitry Andric     // Legal smax and smin
206bdd1243dSDimitry Andric     setOperationAction(ISD::SMAX, IntVT, Legal);
207bdd1243dSDimitry Andric     setOperationAction(ISD::SMIN, IntVT, Legal);
208e8d8bef9SDimitry Andric   }
209e8d8bef9SDimitry Andric   /// } Int Ops
210e8d8bef9SDimitry Andric 
211e8d8bef9SDimitry Andric   /// Conversion {
212e8d8bef9SDimitry Andric   // VE doesn't have instructions for fp<->uint, so expand them by llvm
213e8d8bef9SDimitry Andric   setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote); // use i64
214e8d8bef9SDimitry Andric   setOperationAction(ISD::UINT_TO_FP, MVT::i32, Promote); // use i64
215e8d8bef9SDimitry Andric   setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand);
216e8d8bef9SDimitry Andric   setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand);
217e8d8bef9SDimitry Andric 
218e8d8bef9SDimitry Andric   // fp16 not supported
219e8d8bef9SDimitry Andric   for (MVT FPVT : MVT::fp_valuetypes()) {
220e8d8bef9SDimitry Andric     setOperationAction(ISD::FP16_TO_FP, FPVT, Expand);
221e8d8bef9SDimitry Andric     setOperationAction(ISD::FP_TO_FP16, FPVT, Expand);
222e8d8bef9SDimitry Andric   }
223e8d8bef9SDimitry Andric   /// } Conversion
224e8d8bef9SDimitry Andric 
225e8d8bef9SDimitry Andric   /// Floating-point Ops {
226e8d8bef9SDimitry Andric   /// Note: Floating-point operations are fneg, fadd, fsub, fmul, fdiv, frem,
227e8d8bef9SDimitry Andric   ///       and fcmp.
228e8d8bef9SDimitry Andric 
229e8d8bef9SDimitry Andric   // VE doesn't have following floating point operations.
230e8d8bef9SDimitry Andric   for (MVT VT : MVT::fp_valuetypes()) {
231e8d8bef9SDimitry Andric     setOperationAction(ISD::FNEG, VT, Expand);
232e8d8bef9SDimitry Andric     setOperationAction(ISD::FREM, VT, Expand);
233e8d8bef9SDimitry Andric   }
234e8d8bef9SDimitry Andric 
235e8d8bef9SDimitry Andric   // VE doesn't have fdiv of f128.
236e8d8bef9SDimitry Andric   setOperationAction(ISD::FDIV, MVT::f128, Expand);
237e8d8bef9SDimitry Andric 
238e8d8bef9SDimitry Andric   for (MVT FPVT : {MVT::f32, MVT::f64}) {
239e8d8bef9SDimitry Andric     // f32 and f64 uses ConstantFP.  f128 uses ConstantPool.
240e8d8bef9SDimitry Andric     setOperationAction(ISD::ConstantFP, FPVT, Legal);
241e8d8bef9SDimitry Andric   }
242e8d8bef9SDimitry Andric   /// } Floating-point Ops
243e8d8bef9SDimitry Andric 
244e8d8bef9SDimitry Andric   /// Floating-point math functions {
245e8d8bef9SDimitry Andric 
246e8d8bef9SDimitry Andric   // VE doesn't have following floating point math functions.
247e8d8bef9SDimitry Andric   for (MVT VT : MVT::fp_valuetypes()) {
248e8d8bef9SDimitry Andric     setOperationAction(ISD::FABS, VT, Expand);
249e8d8bef9SDimitry Andric     setOperationAction(ISD::FCOPYSIGN, VT, Expand);
250e8d8bef9SDimitry Andric     setOperationAction(ISD::FCOS, VT, Expand);
251bdd1243dSDimitry Andric     setOperationAction(ISD::FMA, VT, Expand);
252bdd1243dSDimitry Andric     setOperationAction(ISD::FPOW, VT, Expand);
253e8d8bef9SDimitry Andric     setOperationAction(ISD::FSIN, VT, Expand);
254e8d8bef9SDimitry Andric     setOperationAction(ISD::FSQRT, VT, Expand);
255e8d8bef9SDimitry Andric   }
256e8d8bef9SDimitry Andric 
257bdd1243dSDimitry Andric   // VE has single and double FMINNUM and FMAXNUM
258bdd1243dSDimitry Andric   for (MVT VT : {MVT::f32, MVT::f64}) {
259bdd1243dSDimitry Andric     setOperationAction({ISD::FMAXNUM, ISD::FMINNUM}, VT, Legal);
260bdd1243dSDimitry Andric   }
261bdd1243dSDimitry Andric 
262e8d8bef9SDimitry Andric   /// } Floating-point math functions
263e8d8bef9SDimitry Andric 
264e8d8bef9SDimitry Andric   /// Atomic instructions {
265e8d8bef9SDimitry Andric 
266e8d8bef9SDimitry Andric   setMaxAtomicSizeInBitsSupported(64);
267e8d8bef9SDimitry Andric   setMinCmpXchgSizeInBits(32);
268e8d8bef9SDimitry Andric   setSupportsUnalignedAtomics(false);
269e8d8bef9SDimitry Andric 
270e8d8bef9SDimitry Andric   // Use custom inserter for ATOMIC_FENCE.
271e8d8bef9SDimitry Andric   setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
272e8d8bef9SDimitry Andric 
273e8d8bef9SDimitry Andric   // Other atomic instructions.
274e8d8bef9SDimitry Andric   for (MVT VT : MVT::integer_valuetypes()) {
275e8d8bef9SDimitry Andric     // Support i8/i16 atomic swap.
276e8d8bef9SDimitry Andric     setOperationAction(ISD::ATOMIC_SWAP, VT, Custom);
277e8d8bef9SDimitry Andric 
278e8d8bef9SDimitry Andric     // FIXME: Support "atmam" instructions.
279e8d8bef9SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD_ADD, VT, Expand);
280e8d8bef9SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD_SUB, VT, Expand);
281e8d8bef9SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD_AND, VT, Expand);
282e8d8bef9SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD_OR, VT, Expand);
283e8d8bef9SDimitry Andric 
284e8d8bef9SDimitry Andric     // VE doesn't have follwing instructions.
285e8d8bef9SDimitry Andric     setOperationAction(ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS, VT, Expand);
286e8d8bef9SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD_CLR, VT, Expand);
287e8d8bef9SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD_XOR, VT, Expand);
288e8d8bef9SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD_NAND, VT, Expand);
289e8d8bef9SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD_MIN, VT, Expand);
290e8d8bef9SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD_MAX, VT, Expand);
291e8d8bef9SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD_UMIN, VT, Expand);
292e8d8bef9SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD_UMAX, VT, Expand);
293e8d8bef9SDimitry Andric   }
294e8d8bef9SDimitry Andric 
295e8d8bef9SDimitry Andric   /// } Atomic instructions
296e8d8bef9SDimitry Andric 
297e8d8bef9SDimitry Andric   /// SJLJ instructions {
298e8d8bef9SDimitry Andric   setOperationAction(ISD::EH_SJLJ_LONGJMP, MVT::Other, Custom);
299e8d8bef9SDimitry Andric   setOperationAction(ISD::EH_SJLJ_SETJMP, MVT::i32, Custom);
300e8d8bef9SDimitry Andric   setOperationAction(ISD::EH_SJLJ_SETUP_DISPATCH, MVT::Other, Custom);
301e8d8bef9SDimitry Andric   if (TM.Options.ExceptionModel == ExceptionHandling::SjLj)
302e8d8bef9SDimitry Andric     setLibcallName(RTLIB::UNWIND_RESUME, "_Unwind_SjLj_Resume");
303e8d8bef9SDimitry Andric   /// } SJLJ instructions
304e8d8bef9SDimitry Andric 
305e8d8bef9SDimitry Andric   // Intrinsic instructions
306e8d8bef9SDimitry Andric   setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
307e8d8bef9SDimitry Andric }
308e8d8bef9SDimitry Andric 
initVPUActions()309e8d8bef9SDimitry Andric void VETargetLowering::initVPUActions() {
31081ad6265SDimitry Andric   for (MVT LegalMaskVT : AllMaskVTs)
31181ad6265SDimitry Andric     setOperationAction(ISD::BUILD_VECTOR, LegalMaskVT, Custom);
31281ad6265SDimitry Andric 
31381ad6265SDimitry Andric   for (unsigned Opc : {ISD::AND, ISD::OR, ISD::XOR})
31481ad6265SDimitry Andric     setOperationAction(Opc, MVT::v512i1, Custom);
31581ad6265SDimitry Andric 
316e8d8bef9SDimitry Andric   for (MVT LegalVecVT : AllVectorVTs) {
317e8d8bef9SDimitry Andric     setOperationAction(ISD::BUILD_VECTOR, LegalVecVT, Custom);
318e8d8bef9SDimitry Andric     setOperationAction(ISD::INSERT_VECTOR_ELT, LegalVecVT, Legal);
319e8d8bef9SDimitry Andric     setOperationAction(ISD::EXTRACT_VECTOR_ELT, LegalVecVT, Legal);
320e8d8bef9SDimitry Andric     // Translate all vector instructions with legal element types to VVP_*
321e8d8bef9SDimitry Andric     // nodes.
322e8d8bef9SDimitry Andric     // TODO We will custom-widen into VVP_* nodes in the future. While we are
323e8d8bef9SDimitry Andric     // buildling the infrastructure for this, we only do this for legal vector
324e8d8bef9SDimitry Andric     // VTs.
325e8d8bef9SDimitry Andric #define HANDLE_VP_TO_VVP(VP_OPC, VVP_NAME)                                     \
326e8d8bef9SDimitry Andric   setOperationAction(ISD::VP_OPC, LegalVecVT, Custom);
327e8d8bef9SDimitry Andric #define ADD_VVP_OP(VVP_NAME, ISD_NAME)                                         \
328e8d8bef9SDimitry Andric   setOperationAction(ISD::ISD_NAME, LegalVecVT, Custom);
32981ad6265SDimitry Andric     setOperationAction(ISD::EXPERIMENTAL_VP_STRIDED_LOAD, LegalVecVT, Custom);
33081ad6265SDimitry Andric     setOperationAction(ISD::EXPERIMENTAL_VP_STRIDED_STORE, LegalVecVT, Custom);
331e8d8bef9SDimitry Andric #include "VVPNodes.def"
332e8d8bef9SDimitry Andric   }
333e8d8bef9SDimitry Andric 
334e8d8bef9SDimitry Andric   for (MVT LegalPackedVT : AllPackedVTs) {
335e8d8bef9SDimitry Andric     setOperationAction(ISD::INSERT_VECTOR_ELT, LegalPackedVT, Custom);
336e8d8bef9SDimitry Andric     setOperationAction(ISD::EXTRACT_VECTOR_ELT, LegalPackedVT, Custom);
337e8d8bef9SDimitry Andric   }
33881ad6265SDimitry Andric 
33981ad6265SDimitry Andric   // vNt32, vNt64 ops (legal element types)
34081ad6265SDimitry Andric   for (MVT VT : MVT::vector_valuetypes()) {
34181ad6265SDimitry Andric     MVT ElemVT = VT.getVectorElementType();
34281ad6265SDimitry Andric     unsigned ElemBits = ElemVT.getScalarSizeInBits();
34381ad6265SDimitry Andric     if (ElemBits != 32 && ElemBits != 64)
34481ad6265SDimitry Andric       continue;
34581ad6265SDimitry Andric 
34681ad6265SDimitry Andric     for (unsigned MemOpc : {ISD::MLOAD, ISD::MSTORE, ISD::LOAD, ISD::STORE})
34781ad6265SDimitry Andric       setOperationAction(MemOpc, VT, Custom);
34881ad6265SDimitry Andric 
34981ad6265SDimitry Andric     const ISD::NodeType IntReductionOCs[] = {
35081ad6265SDimitry Andric         ISD::VECREDUCE_ADD,  ISD::VECREDUCE_MUL,  ISD::VECREDUCE_AND,
35181ad6265SDimitry Andric         ISD::VECREDUCE_OR,   ISD::VECREDUCE_XOR,  ISD::VECREDUCE_SMIN,
35281ad6265SDimitry Andric         ISD::VECREDUCE_SMAX, ISD::VECREDUCE_UMIN, ISD::VECREDUCE_UMAX};
35381ad6265SDimitry Andric 
35481ad6265SDimitry Andric     for (unsigned IntRedOpc : IntReductionOCs)
35581ad6265SDimitry Andric       setOperationAction(IntRedOpc, VT, Custom);
35681ad6265SDimitry Andric   }
35781ad6265SDimitry Andric 
35881ad6265SDimitry Andric   // v256i1 and v512i1 ops
35981ad6265SDimitry Andric   for (MVT MaskVT : AllMaskVTs) {
36081ad6265SDimitry Andric     // Custom lower mask ops
36181ad6265SDimitry Andric     setOperationAction(ISD::STORE, MaskVT, Custom);
36281ad6265SDimitry Andric     setOperationAction(ISD::LOAD, MaskVT, Custom);
36381ad6265SDimitry Andric   }
364e8d8bef9SDimitry Andric }
365e8d8bef9SDimitry Andric 
366480093f4SDimitry Andric SDValue
LowerReturn(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,const SmallVectorImpl<SDValue> & OutVals,const SDLoc & DL,SelectionDAG & DAG) const367480093f4SDimitry Andric VETargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
368480093f4SDimitry Andric                               bool IsVarArg,
369480093f4SDimitry Andric                               const SmallVectorImpl<ISD::OutputArg> &Outs,
370480093f4SDimitry Andric                               const SmallVectorImpl<SDValue> &OutVals,
371480093f4SDimitry Andric                               const SDLoc &DL, SelectionDAG &DAG) const {
3725ffd83dbSDimitry Andric   // CCValAssign - represent the assignment of the return value to locations.
3735ffd83dbSDimitry Andric   SmallVector<CCValAssign, 16> RVLocs;
374480093f4SDimitry Andric 
3755ffd83dbSDimitry Andric   // CCState - Info about the registers and stack slot.
3765ffd83dbSDimitry Andric   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
3775ffd83dbSDimitry Andric                  *DAG.getContext());
3785ffd83dbSDimitry Andric 
3795ffd83dbSDimitry Andric   // Analyze return values.
380e8d8bef9SDimitry Andric   CCInfo.AnalyzeReturn(Outs, getReturnCC(CallConv));
3815ffd83dbSDimitry Andric 
38206c3fb27SDimitry Andric   SDValue Glue;
383480093f4SDimitry Andric   SmallVector<SDValue, 4> RetOps(1, Chain);
3845ffd83dbSDimitry Andric 
3855ffd83dbSDimitry Andric   // Copy the result values into the output registers.
3865ffd83dbSDimitry Andric   for (unsigned i = 0; i != RVLocs.size(); ++i) {
3875ffd83dbSDimitry Andric     CCValAssign &VA = RVLocs[i];
3885ffd83dbSDimitry Andric     assert(VA.isRegLoc() && "Can only return in registers!");
389e8d8bef9SDimitry Andric     assert(!VA.needsCustom() && "Unexpected custom lowering");
3905ffd83dbSDimitry Andric     SDValue OutVal = OutVals[i];
3915ffd83dbSDimitry Andric 
3925ffd83dbSDimitry Andric     // Integer return values must be sign or zero extended by the callee.
3935ffd83dbSDimitry Andric     switch (VA.getLocInfo()) {
3945ffd83dbSDimitry Andric     case CCValAssign::Full:
3955ffd83dbSDimitry Andric       break;
3965ffd83dbSDimitry Andric     case CCValAssign::SExt:
3975ffd83dbSDimitry Andric       OutVal = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), OutVal);
3985ffd83dbSDimitry Andric       break;
3995ffd83dbSDimitry Andric     case CCValAssign::ZExt:
4005ffd83dbSDimitry Andric       OutVal = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), OutVal);
4015ffd83dbSDimitry Andric       break;
4025ffd83dbSDimitry Andric     case CCValAssign::AExt:
4035ffd83dbSDimitry Andric       OutVal = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), OutVal);
4045ffd83dbSDimitry Andric       break;
405e8d8bef9SDimitry Andric     case CCValAssign::BCvt: {
406e8d8bef9SDimitry Andric       // Convert a float return value to i64 with padding.
407e8d8bef9SDimitry Andric       //     63     31   0
408e8d8bef9SDimitry Andric       //    +------+------+
409e8d8bef9SDimitry Andric       //    | float|   0  |
410e8d8bef9SDimitry Andric       //    +------+------+
411e8d8bef9SDimitry Andric       assert(VA.getLocVT() == MVT::i64);
412e8d8bef9SDimitry Andric       assert(VA.getValVT() == MVT::f32);
413e8d8bef9SDimitry Andric       SDValue Undef = SDValue(
414e8d8bef9SDimitry Andric           DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MVT::i64), 0);
415e8d8bef9SDimitry Andric       SDValue Sub_f32 = DAG.getTargetConstant(VE::sub_f32, DL, MVT::i32);
416e8d8bef9SDimitry Andric       OutVal = SDValue(DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, DL,
417e8d8bef9SDimitry Andric                                           MVT::i64, Undef, OutVal, Sub_f32),
418e8d8bef9SDimitry Andric                        0);
419e8d8bef9SDimitry Andric       break;
420e8d8bef9SDimitry Andric     }
4215ffd83dbSDimitry Andric     default:
4225ffd83dbSDimitry Andric       llvm_unreachable("Unknown loc info!");
4235ffd83dbSDimitry Andric     }
4245ffd83dbSDimitry Andric 
42506c3fb27SDimitry Andric     Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVal, Glue);
4265ffd83dbSDimitry Andric 
4275ffd83dbSDimitry Andric     // Guarantee that all emitted copies are stuck together with flags.
42806c3fb27SDimitry Andric     Glue = Chain.getValue(1);
4295ffd83dbSDimitry Andric     RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
4305ffd83dbSDimitry Andric   }
4315ffd83dbSDimitry Andric 
432480093f4SDimitry Andric   RetOps[0] = Chain; // Update chain.
4335ffd83dbSDimitry Andric 
43406c3fb27SDimitry Andric   // Add the glue if we have it.
43506c3fb27SDimitry Andric   if (Glue.getNode())
43606c3fb27SDimitry Andric     RetOps.push_back(Glue);
4375ffd83dbSDimitry Andric 
43806c3fb27SDimitry Andric   return DAG.getNode(VEISD::RET_GLUE, DL, MVT::Other, RetOps);
439480093f4SDimitry Andric }
440480093f4SDimitry Andric 
LowerFormalArguments(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::InputArg> & Ins,const SDLoc & DL,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals) const441480093f4SDimitry Andric SDValue VETargetLowering::LowerFormalArguments(
442480093f4SDimitry Andric     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
443480093f4SDimitry Andric     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
444480093f4SDimitry Andric     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
4455ffd83dbSDimitry Andric   MachineFunction &MF = DAG.getMachineFunction();
4465ffd83dbSDimitry Andric 
4475ffd83dbSDimitry Andric   // Get the base offset of the incoming arguments stack space.
448e8d8bef9SDimitry Andric   unsigned ArgsBaseOffset = Subtarget->getRsaSize();
4495ffd83dbSDimitry Andric   // Get the size of the preserved arguments area
4505ffd83dbSDimitry Andric   unsigned ArgsPreserved = 64;
4515ffd83dbSDimitry Andric 
4525ffd83dbSDimitry Andric   // Analyze arguments according to CC_VE.
4535ffd83dbSDimitry Andric   SmallVector<CCValAssign, 16> ArgLocs;
4545ffd83dbSDimitry Andric   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
4555ffd83dbSDimitry Andric                  *DAG.getContext());
4565ffd83dbSDimitry Andric   // Allocate the preserved area first.
4575ffd83dbSDimitry Andric   CCInfo.AllocateStack(ArgsPreserved, Align(8));
4585ffd83dbSDimitry Andric   // We already allocated the preserved area, so the stack offset computed
4595ffd83dbSDimitry Andric   // by CC_VE would be correct now.
460e8d8bef9SDimitry Andric   CCInfo.AnalyzeFormalArguments(Ins, getParamCC(CallConv, false));
4615ffd83dbSDimitry Andric 
4625ffd83dbSDimitry Andric   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4635ffd83dbSDimitry Andric     CCValAssign &VA = ArgLocs[i];
464e8d8bef9SDimitry Andric     assert(!VA.needsCustom() && "Unexpected custom lowering");
4655ffd83dbSDimitry Andric     if (VA.isRegLoc()) {
4665ffd83dbSDimitry Andric       // This argument is passed in a register.
4675ffd83dbSDimitry Andric       // All integer register arguments are promoted by the caller to i64.
4685ffd83dbSDimitry Andric 
4695ffd83dbSDimitry Andric       // Create a virtual register for the promoted live-in value.
47004eeddc0SDimitry Andric       Register VReg =
4715ffd83dbSDimitry Andric           MF.addLiveIn(VA.getLocReg(), getRegClassFor(VA.getLocVT()));
4725ffd83dbSDimitry Andric       SDValue Arg = DAG.getCopyFromReg(Chain, DL, VReg, VA.getLocVT());
4735ffd83dbSDimitry Andric 
4745ffd83dbSDimitry Andric       // The caller promoted the argument, so insert an Assert?ext SDNode so we
4755ffd83dbSDimitry Andric       // won't promote the value again in this function.
4765ffd83dbSDimitry Andric       switch (VA.getLocInfo()) {
4775ffd83dbSDimitry Andric       case CCValAssign::SExt:
4785ffd83dbSDimitry Andric         Arg = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Arg,
4795ffd83dbSDimitry Andric                           DAG.getValueType(VA.getValVT()));
4805ffd83dbSDimitry Andric         break;
4815ffd83dbSDimitry Andric       case CCValAssign::ZExt:
4825ffd83dbSDimitry Andric         Arg = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Arg,
4835ffd83dbSDimitry Andric                           DAG.getValueType(VA.getValVT()));
4845ffd83dbSDimitry Andric         break;
485e8d8bef9SDimitry Andric       case CCValAssign::BCvt: {
486e8d8bef9SDimitry Andric         // Extract a float argument from i64 with padding.
487e8d8bef9SDimitry Andric         //     63     31   0
488e8d8bef9SDimitry Andric         //    +------+------+
489e8d8bef9SDimitry Andric         //    | float|   0  |
490e8d8bef9SDimitry Andric         //    +------+------+
491e8d8bef9SDimitry Andric         assert(VA.getLocVT() == MVT::i64);
492e8d8bef9SDimitry Andric         assert(VA.getValVT() == MVT::f32);
493e8d8bef9SDimitry Andric         SDValue Sub_f32 = DAG.getTargetConstant(VE::sub_f32, DL, MVT::i32);
494e8d8bef9SDimitry Andric         Arg = SDValue(DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL,
495e8d8bef9SDimitry Andric                                          MVT::f32, Arg, Sub_f32),
496e8d8bef9SDimitry Andric                       0);
497e8d8bef9SDimitry Andric         break;
498e8d8bef9SDimitry Andric       }
4995ffd83dbSDimitry Andric       default:
5005ffd83dbSDimitry Andric         break;
5015ffd83dbSDimitry Andric       }
5025ffd83dbSDimitry Andric 
5035ffd83dbSDimitry Andric       // Truncate the register down to the argument type.
5045ffd83dbSDimitry Andric       if (VA.isExtInLoc())
5055ffd83dbSDimitry Andric         Arg = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Arg);
5065ffd83dbSDimitry Andric 
5075ffd83dbSDimitry Andric       InVals.push_back(Arg);
5085ffd83dbSDimitry Andric       continue;
5095ffd83dbSDimitry Andric     }
5105ffd83dbSDimitry Andric 
5115ffd83dbSDimitry Andric     // The registers are exhausted. This argument was passed on the stack.
5125ffd83dbSDimitry Andric     assert(VA.isMemLoc());
5135ffd83dbSDimitry Andric     // The CC_VE_Full/Half functions compute stack offsets relative to the
514e8d8bef9SDimitry Andric     // beginning of the arguments area at %fp + the size of reserved area.
5155ffd83dbSDimitry Andric     unsigned Offset = VA.getLocMemOffset() + ArgsBaseOffset;
5165ffd83dbSDimitry Andric     unsigned ValSize = VA.getValVT().getSizeInBits() / 8;
517e8d8bef9SDimitry Andric 
518e8d8bef9SDimitry Andric     // Adjust offset for a float argument by adding 4 since the argument is
519e8d8bef9SDimitry Andric     // stored in 8 bytes buffer with offset like below.  LLVM generates
520e8d8bef9SDimitry Andric     // 4 bytes load instruction, so need to adjust offset here.  This
521e8d8bef9SDimitry Andric     // adjustment is required in only LowerFormalArguments.  In LowerCall,
522e8d8bef9SDimitry Andric     // a float argument is converted to i64 first, and stored as 8 bytes
523e8d8bef9SDimitry Andric     // data, which is required by ABI, so no need for adjustment.
524e8d8bef9SDimitry Andric     //    0      4
525e8d8bef9SDimitry Andric     //    +------+------+
526e8d8bef9SDimitry Andric     //    | empty| float|
527e8d8bef9SDimitry Andric     //    +------+------+
528e8d8bef9SDimitry Andric     if (VA.getValVT() == MVT::f32)
529e8d8bef9SDimitry Andric       Offset += 4;
530e8d8bef9SDimitry Andric 
5315ffd83dbSDimitry Andric     int FI = MF.getFrameInfo().CreateFixedObject(ValSize, Offset, true);
5325ffd83dbSDimitry Andric     InVals.push_back(
5335ffd83dbSDimitry Andric         DAG.getLoad(VA.getValVT(), DL, Chain,
5345ffd83dbSDimitry Andric                     DAG.getFrameIndex(FI, getPointerTy(MF.getDataLayout())),
5355ffd83dbSDimitry Andric                     MachinePointerInfo::getFixedStack(MF, FI)));
5365ffd83dbSDimitry Andric   }
5375ffd83dbSDimitry Andric 
5385ffd83dbSDimitry Andric   if (!IsVarArg)
5395ffd83dbSDimitry Andric     return Chain;
5405ffd83dbSDimitry Andric 
5415ffd83dbSDimitry Andric   // This function takes variable arguments, some of which may have been passed
5425ffd83dbSDimitry Andric   // in registers %s0-%s8.
5435ffd83dbSDimitry Andric   //
5445ffd83dbSDimitry Andric   // The va_start intrinsic needs to know the offset to the first variable
5455ffd83dbSDimitry Andric   // argument.
5465ffd83dbSDimitry Andric   // TODO: need to calculate offset correctly once we support f128.
5475ffd83dbSDimitry Andric   unsigned ArgOffset = ArgLocs.size() * 8;
5485ffd83dbSDimitry Andric   VEMachineFunctionInfo *FuncInfo = MF.getInfo<VEMachineFunctionInfo>();
549e8d8bef9SDimitry Andric   // Skip the reserved area at the top of stack.
5505ffd83dbSDimitry Andric   FuncInfo->setVarArgsFrameOffset(ArgOffset + ArgsBaseOffset);
5515ffd83dbSDimitry Andric 
552480093f4SDimitry Andric   return Chain;
553480093f4SDimitry Andric }
554480093f4SDimitry Andric 
555480093f4SDimitry Andric // FIXME? Maybe this could be a TableGen attribute on some registers and
556480093f4SDimitry Andric // this table could be generated automatically from RegInfo.
getRegisterByName(const char * RegName,LLT VT,const MachineFunction & MF) const557480093f4SDimitry Andric Register VETargetLowering::getRegisterByName(const char *RegName, LLT VT,
558480093f4SDimitry Andric                                              const MachineFunction &MF) const {
559480093f4SDimitry Andric   Register Reg = StringSwitch<Register>(RegName)
560480093f4SDimitry Andric                      .Case("sp", VE::SX11)    // Stack pointer
561480093f4SDimitry Andric                      .Case("fp", VE::SX9)     // Frame pointer
562480093f4SDimitry Andric                      .Case("sl", VE::SX8)     // Stack limit
5635ffd83dbSDimitry Andric                      .Case("lr", VE::SX10)    // Link register
564480093f4SDimitry Andric                      .Case("tp", VE::SX14)    // Thread pointer
565480093f4SDimitry Andric                      .Case("outer", VE::SX12) // Outer regiser
566480093f4SDimitry Andric                      .Case("info", VE::SX17)  // Info area register
567480093f4SDimitry Andric                      .Case("got", VE::SX15)   // Global offset table register
568480093f4SDimitry Andric                      .Case("plt", VE::SX16) // Procedure linkage table register
569480093f4SDimitry Andric                      .Default(0);
570480093f4SDimitry Andric 
571480093f4SDimitry Andric   if (Reg)
572480093f4SDimitry Andric     return Reg;
573480093f4SDimitry Andric 
574480093f4SDimitry Andric   report_fatal_error("Invalid register name global variable");
575480093f4SDimitry Andric }
576480093f4SDimitry Andric 
577480093f4SDimitry Andric //===----------------------------------------------------------------------===//
578480093f4SDimitry Andric // TargetLowering Implementation
579480093f4SDimitry Andric //===----------------------------------------------------------------------===//
580480093f4SDimitry Andric 
LowerCall(TargetLowering::CallLoweringInfo & CLI,SmallVectorImpl<SDValue> & InVals) const5815ffd83dbSDimitry Andric SDValue VETargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
5825ffd83dbSDimitry Andric                                     SmallVectorImpl<SDValue> &InVals) const {
5835ffd83dbSDimitry Andric   SelectionDAG &DAG = CLI.DAG;
5845ffd83dbSDimitry Andric   SDLoc DL = CLI.DL;
5855ffd83dbSDimitry Andric   SDValue Chain = CLI.Chain;
5865ffd83dbSDimitry Andric   auto PtrVT = getPointerTy(DAG.getDataLayout());
5875ffd83dbSDimitry Andric 
5885ffd83dbSDimitry Andric   // VE target does not yet support tail call optimization.
5895ffd83dbSDimitry Andric   CLI.IsTailCall = false;
5905ffd83dbSDimitry Andric 
5915ffd83dbSDimitry Andric   // Get the base offset of the outgoing arguments stack space.
592e8d8bef9SDimitry Andric   unsigned ArgsBaseOffset = Subtarget->getRsaSize();
5935ffd83dbSDimitry Andric   // Get the size of the preserved arguments area
5945ffd83dbSDimitry Andric   unsigned ArgsPreserved = 8 * 8u;
5955ffd83dbSDimitry Andric 
5965ffd83dbSDimitry Andric   // Analyze operands of the call, assigning locations to each operand.
5975ffd83dbSDimitry Andric   SmallVector<CCValAssign, 16> ArgLocs;
5985ffd83dbSDimitry Andric   CCState CCInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), ArgLocs,
5995ffd83dbSDimitry Andric                  *DAG.getContext());
6005ffd83dbSDimitry Andric   // Allocate the preserved area first.
6015ffd83dbSDimitry Andric   CCInfo.AllocateStack(ArgsPreserved, Align(8));
6025ffd83dbSDimitry Andric   // We already allocated the preserved area, so the stack offset computed
6035ffd83dbSDimitry Andric   // by CC_VE would be correct now.
604e8d8bef9SDimitry Andric   CCInfo.AnalyzeCallOperands(CLI.Outs, getParamCC(CLI.CallConv, false));
6055ffd83dbSDimitry Andric 
6065ffd83dbSDimitry Andric   // VE requires to use both register and stack for varargs or no-prototyped
6075ffd83dbSDimitry Andric   // functions.
6085ffd83dbSDimitry Andric   bool UseBoth = CLI.IsVarArg;
6095ffd83dbSDimitry Andric 
6105ffd83dbSDimitry Andric   // Analyze operands again if it is required to store BOTH.
6115ffd83dbSDimitry Andric   SmallVector<CCValAssign, 16> ArgLocs2;
6125ffd83dbSDimitry Andric   CCState CCInfo2(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(),
6135ffd83dbSDimitry Andric                   ArgLocs2, *DAG.getContext());
6145ffd83dbSDimitry Andric   if (UseBoth)
615e8d8bef9SDimitry Andric     CCInfo2.AnalyzeCallOperands(CLI.Outs, getParamCC(CLI.CallConv, true));
6165ffd83dbSDimitry Andric 
6175ffd83dbSDimitry Andric   // Get the size of the outgoing arguments stack space requirement.
61806c3fb27SDimitry Andric   unsigned ArgsSize = CCInfo.getStackSize();
6195ffd83dbSDimitry Andric 
6205ffd83dbSDimitry Andric   // Keep stack frames 16-byte aligned.
6215ffd83dbSDimitry Andric   ArgsSize = alignTo(ArgsSize, 16);
6225ffd83dbSDimitry Andric 
6235ffd83dbSDimitry Andric   // Adjust the stack pointer to make room for the arguments.
6245ffd83dbSDimitry Andric   // FIXME: Use hasReservedCallFrame to avoid %sp adjustments around all calls
6255ffd83dbSDimitry Andric   // with more than 6 arguments.
6265ffd83dbSDimitry Andric   Chain = DAG.getCALLSEQ_START(Chain, ArgsSize, 0, DL);
6275ffd83dbSDimitry Andric 
6285ffd83dbSDimitry Andric   // Collect the set of registers to pass to the function and their values.
6295ffd83dbSDimitry Andric   // This will be emitted as a sequence of CopyToReg nodes glued to the call
6305ffd83dbSDimitry Andric   // instruction.
6315ffd83dbSDimitry Andric   SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
6325ffd83dbSDimitry Andric 
6335ffd83dbSDimitry Andric   // Collect chains from all the memory opeations that copy arguments to the
6345ffd83dbSDimitry Andric   // stack. They must follow the stack pointer adjustment above and precede the
6355ffd83dbSDimitry Andric   // call instruction itself.
6365ffd83dbSDimitry Andric   SmallVector<SDValue, 8> MemOpChains;
6375ffd83dbSDimitry Andric 
6385ffd83dbSDimitry Andric   // VE needs to get address of callee function in a register
6395ffd83dbSDimitry Andric   // So, prepare to copy it to SX12 here.
6405ffd83dbSDimitry Andric 
6415ffd83dbSDimitry Andric   // If the callee is a GlobalAddress node (quite common, every direct call is)
6425ffd83dbSDimitry Andric   // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
6435ffd83dbSDimitry Andric   // Likewise ExternalSymbol -> TargetExternalSymbol.
6445ffd83dbSDimitry Andric   SDValue Callee = CLI.Callee;
6455ffd83dbSDimitry Andric 
6465ffd83dbSDimitry Andric   bool IsPICCall = isPositionIndependent();
6475ffd83dbSDimitry Andric 
6485ffd83dbSDimitry Andric   // PC-relative references to external symbols should go through $stub.
6495ffd83dbSDimitry Andric   // If so, we need to prepare GlobalBaseReg first.
6505ffd83dbSDimitry Andric   const TargetMachine &TM = DAG.getTarget();
6515ffd83dbSDimitry Andric   const Module *Mod = DAG.getMachineFunction().getFunction().getParent();
6525ffd83dbSDimitry Andric   const GlobalValue *GV = nullptr;
6535ffd83dbSDimitry Andric   auto *CalleeG = dyn_cast<GlobalAddressSDNode>(Callee);
6545ffd83dbSDimitry Andric   if (CalleeG)
6555ffd83dbSDimitry Andric     GV = CalleeG->getGlobal();
6565ffd83dbSDimitry Andric   bool Local = TM.shouldAssumeDSOLocal(*Mod, GV);
6575ffd83dbSDimitry Andric   bool UsePlt = !Local;
6585ffd83dbSDimitry Andric   MachineFunction &MF = DAG.getMachineFunction();
6595ffd83dbSDimitry Andric 
6605ffd83dbSDimitry Andric   // Turn GlobalAddress/ExternalSymbol node into a value node
6615ffd83dbSDimitry Andric   // containing the address of them here.
6625ffd83dbSDimitry Andric   if (CalleeG) {
6635ffd83dbSDimitry Andric     if (IsPICCall) {
6645ffd83dbSDimitry Andric       if (UsePlt)
6655ffd83dbSDimitry Andric         Subtarget->getInstrInfo()->getGlobalBaseReg(&MF);
6665ffd83dbSDimitry Andric       Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, 0);
6675ffd83dbSDimitry Andric       Callee = DAG.getNode(VEISD::GETFUNPLT, DL, PtrVT, Callee);
6685ffd83dbSDimitry Andric     } else {
6695ffd83dbSDimitry Andric       Callee =
6705ffd83dbSDimitry Andric           makeHiLoPair(Callee, VEMCExpr::VK_VE_HI32, VEMCExpr::VK_VE_LO32, DAG);
6715ffd83dbSDimitry Andric     }
6725ffd83dbSDimitry Andric   } else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) {
6735ffd83dbSDimitry Andric     if (IsPICCall) {
6745ffd83dbSDimitry Andric       if (UsePlt)
6755ffd83dbSDimitry Andric         Subtarget->getInstrInfo()->getGlobalBaseReg(&MF);
6765ffd83dbSDimitry Andric       Callee = DAG.getTargetExternalSymbol(E->getSymbol(), PtrVT, 0);
6775ffd83dbSDimitry Andric       Callee = DAG.getNode(VEISD::GETFUNPLT, DL, PtrVT, Callee);
6785ffd83dbSDimitry Andric     } else {
6795ffd83dbSDimitry Andric       Callee =
6805ffd83dbSDimitry Andric           makeHiLoPair(Callee, VEMCExpr::VK_VE_HI32, VEMCExpr::VK_VE_LO32, DAG);
6815ffd83dbSDimitry Andric     }
6825ffd83dbSDimitry Andric   }
6835ffd83dbSDimitry Andric 
6845ffd83dbSDimitry Andric   RegsToPass.push_back(std::make_pair(VE::SX12, Callee));
6855ffd83dbSDimitry Andric 
6865ffd83dbSDimitry Andric   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
6875ffd83dbSDimitry Andric     CCValAssign &VA = ArgLocs[i];
6885ffd83dbSDimitry Andric     SDValue Arg = CLI.OutVals[i];
6895ffd83dbSDimitry Andric 
6905ffd83dbSDimitry Andric     // Promote the value if needed.
6915ffd83dbSDimitry Andric     switch (VA.getLocInfo()) {
6925ffd83dbSDimitry Andric     default:
6935ffd83dbSDimitry Andric       llvm_unreachable("Unknown location info!");
6945ffd83dbSDimitry Andric     case CCValAssign::Full:
6955ffd83dbSDimitry Andric       break;
6965ffd83dbSDimitry Andric     case CCValAssign::SExt:
6975ffd83dbSDimitry Andric       Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
6985ffd83dbSDimitry Andric       break;
6995ffd83dbSDimitry Andric     case CCValAssign::ZExt:
7005ffd83dbSDimitry Andric       Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
7015ffd83dbSDimitry Andric       break;
7025ffd83dbSDimitry Andric     case CCValAssign::AExt:
7035ffd83dbSDimitry Andric       Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
7045ffd83dbSDimitry Andric       break;
705e8d8bef9SDimitry Andric     case CCValAssign::BCvt: {
706e8d8bef9SDimitry Andric       // Convert a float argument to i64 with padding.
707e8d8bef9SDimitry Andric       //     63     31   0
708e8d8bef9SDimitry Andric       //    +------+------+
709e8d8bef9SDimitry Andric       //    | float|   0  |
710e8d8bef9SDimitry Andric       //    +------+------+
711e8d8bef9SDimitry Andric       assert(VA.getLocVT() == MVT::i64);
712e8d8bef9SDimitry Andric       assert(VA.getValVT() == MVT::f32);
713e8d8bef9SDimitry Andric       SDValue Undef = SDValue(
714e8d8bef9SDimitry Andric           DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MVT::i64), 0);
715e8d8bef9SDimitry Andric       SDValue Sub_f32 = DAG.getTargetConstant(VE::sub_f32, DL, MVT::i32);
716e8d8bef9SDimitry Andric       Arg = SDValue(DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, DL,
717e8d8bef9SDimitry Andric                                        MVT::i64, Undef, Arg, Sub_f32),
718e8d8bef9SDimitry Andric                     0);
719e8d8bef9SDimitry Andric       break;
720e8d8bef9SDimitry Andric     }
7215ffd83dbSDimitry Andric     }
7225ffd83dbSDimitry Andric 
7235ffd83dbSDimitry Andric     if (VA.isRegLoc()) {
7245ffd83dbSDimitry Andric       RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
7255ffd83dbSDimitry Andric       if (!UseBoth)
7265ffd83dbSDimitry Andric         continue;
7275ffd83dbSDimitry Andric       VA = ArgLocs2[i];
7285ffd83dbSDimitry Andric     }
7295ffd83dbSDimitry Andric 
7305ffd83dbSDimitry Andric     assert(VA.isMemLoc());
7315ffd83dbSDimitry Andric 
7325ffd83dbSDimitry Andric     // Create a store off the stack pointer for this argument.
7335ffd83dbSDimitry Andric     SDValue StackPtr = DAG.getRegister(VE::SX11, PtrVT);
734e8d8bef9SDimitry Andric     // The argument area starts at %fp/%sp + the size of reserved area.
7355ffd83dbSDimitry Andric     SDValue PtrOff =
7365ffd83dbSDimitry Andric         DAG.getIntPtrConstant(VA.getLocMemOffset() + ArgsBaseOffset, DL);
7375ffd83dbSDimitry Andric     PtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, PtrOff);
7385ffd83dbSDimitry Andric     MemOpChains.push_back(
7395ffd83dbSDimitry Andric         DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo()));
7405ffd83dbSDimitry Andric   }
7415ffd83dbSDimitry Andric 
7425ffd83dbSDimitry Andric   // Emit all stores, make sure they occur before the call.
7435ffd83dbSDimitry Andric   if (!MemOpChains.empty())
7445ffd83dbSDimitry Andric     Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
7455ffd83dbSDimitry Andric 
7465ffd83dbSDimitry Andric   // Build a sequence of CopyToReg nodes glued together with token chain and
7475ffd83dbSDimitry Andric   // glue operands which copy the outgoing args into registers. The InGlue is
7485ffd83dbSDimitry Andric   // necessary since all emitted instructions must be stuck together in order
7495ffd83dbSDimitry Andric   // to pass the live physical registers.
7505ffd83dbSDimitry Andric   SDValue InGlue;
7515ffd83dbSDimitry Andric   for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
7525ffd83dbSDimitry Andric     Chain = DAG.getCopyToReg(Chain, DL, RegsToPass[i].first,
7535ffd83dbSDimitry Andric                              RegsToPass[i].second, InGlue);
7545ffd83dbSDimitry Andric     InGlue = Chain.getValue(1);
7555ffd83dbSDimitry Andric   }
7565ffd83dbSDimitry Andric 
7575ffd83dbSDimitry Andric   // Build the operands for the call instruction itself.
7585ffd83dbSDimitry Andric   SmallVector<SDValue, 8> Ops;
7595ffd83dbSDimitry Andric   Ops.push_back(Chain);
7605ffd83dbSDimitry Andric   for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
7615ffd83dbSDimitry Andric     Ops.push_back(DAG.getRegister(RegsToPass[i].first,
7625ffd83dbSDimitry Andric                                   RegsToPass[i].second.getValueType()));
7635ffd83dbSDimitry Andric 
7645ffd83dbSDimitry Andric   // Add a register mask operand representing the call-preserved registers.
7655ffd83dbSDimitry Andric   const VERegisterInfo *TRI = Subtarget->getRegisterInfo();
7665ffd83dbSDimitry Andric   const uint32_t *Mask =
7675ffd83dbSDimitry Andric       TRI->getCallPreservedMask(DAG.getMachineFunction(), CLI.CallConv);
7685ffd83dbSDimitry Andric   assert(Mask && "Missing call preserved mask for calling convention");
7695ffd83dbSDimitry Andric   Ops.push_back(DAG.getRegisterMask(Mask));
7705ffd83dbSDimitry Andric 
7715ffd83dbSDimitry Andric   // Make sure the CopyToReg nodes are glued to the call instruction which
7725ffd83dbSDimitry Andric   // consumes the registers.
7735ffd83dbSDimitry Andric   if (InGlue.getNode())
7745ffd83dbSDimitry Andric     Ops.push_back(InGlue);
7755ffd83dbSDimitry Andric 
7765ffd83dbSDimitry Andric   // Now the call itself.
7775ffd83dbSDimitry Andric   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
7785ffd83dbSDimitry Andric   Chain = DAG.getNode(VEISD::CALL, DL, NodeTys, Ops);
7795ffd83dbSDimitry Andric   InGlue = Chain.getValue(1);
7805ffd83dbSDimitry Andric 
7815ffd83dbSDimitry Andric   // Revert the stack pointer immediately after the call.
782bdd1243dSDimitry Andric   Chain = DAG.getCALLSEQ_END(Chain, ArgsSize, 0, InGlue, DL);
7835ffd83dbSDimitry Andric   InGlue = Chain.getValue(1);
7845ffd83dbSDimitry Andric 
7855ffd83dbSDimitry Andric   // Now extract the return values. This is more or less the same as
7865ffd83dbSDimitry Andric   // LowerFormalArguments.
7875ffd83dbSDimitry Andric 
7885ffd83dbSDimitry Andric   // Assign locations to each value returned by this call.
7895ffd83dbSDimitry Andric   SmallVector<CCValAssign, 16> RVLocs;
7905ffd83dbSDimitry Andric   CCState RVInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), RVLocs,
7915ffd83dbSDimitry Andric                  *DAG.getContext());
7925ffd83dbSDimitry Andric 
7935ffd83dbSDimitry Andric   // Set inreg flag manually for codegen generated library calls that
7945ffd83dbSDimitry Andric   // return float.
7955ffd83dbSDimitry Andric   if (CLI.Ins.size() == 1 && CLI.Ins[0].VT == MVT::f32 && !CLI.CB)
7965ffd83dbSDimitry Andric     CLI.Ins[0].Flags.setInReg();
7975ffd83dbSDimitry Andric 
798e8d8bef9SDimitry Andric   RVInfo.AnalyzeCallResult(CLI.Ins, getReturnCC(CLI.CallConv));
7995ffd83dbSDimitry Andric 
8005ffd83dbSDimitry Andric   // Copy all of the result registers out of their specified physreg.
8015ffd83dbSDimitry Andric   for (unsigned i = 0; i != RVLocs.size(); ++i) {
8025ffd83dbSDimitry Andric     CCValAssign &VA = RVLocs[i];
803e8d8bef9SDimitry Andric     assert(!VA.needsCustom() && "Unexpected custom lowering");
80404eeddc0SDimitry Andric     Register Reg = VA.getLocReg();
8055ffd83dbSDimitry Andric 
8065ffd83dbSDimitry Andric     // When returning 'inreg {i32, i32 }', two consecutive i32 arguments can
8075ffd83dbSDimitry Andric     // reside in the same register in the high and low bits. Reuse the
8085ffd83dbSDimitry Andric     // CopyFromReg previous node to avoid duplicate copies.
8095ffd83dbSDimitry Andric     SDValue RV;
8105ffd83dbSDimitry Andric     if (RegisterSDNode *SrcReg = dyn_cast<RegisterSDNode>(Chain.getOperand(1)))
8115ffd83dbSDimitry Andric       if (SrcReg->getReg() == Reg && Chain->getOpcode() == ISD::CopyFromReg)
8125ffd83dbSDimitry Andric         RV = Chain.getValue(0);
8135ffd83dbSDimitry Andric 
8145ffd83dbSDimitry Andric     // But usually we'll create a new CopyFromReg for a different register.
8155ffd83dbSDimitry Andric     if (!RV.getNode()) {
8165ffd83dbSDimitry Andric       RV = DAG.getCopyFromReg(Chain, DL, Reg, RVLocs[i].getLocVT(), InGlue);
8175ffd83dbSDimitry Andric       Chain = RV.getValue(1);
8185ffd83dbSDimitry Andric       InGlue = Chain.getValue(2);
8195ffd83dbSDimitry Andric     }
8205ffd83dbSDimitry Andric 
8215ffd83dbSDimitry Andric     // The callee promoted the return value, so insert an Assert?ext SDNode so
8225ffd83dbSDimitry Andric     // we won't promote the value again in this function.
8235ffd83dbSDimitry Andric     switch (VA.getLocInfo()) {
8245ffd83dbSDimitry Andric     case CCValAssign::SExt:
8255ffd83dbSDimitry Andric       RV = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), RV,
8265ffd83dbSDimitry Andric                        DAG.getValueType(VA.getValVT()));
8275ffd83dbSDimitry Andric       break;
8285ffd83dbSDimitry Andric     case CCValAssign::ZExt:
8295ffd83dbSDimitry Andric       RV = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), RV,
8305ffd83dbSDimitry Andric                        DAG.getValueType(VA.getValVT()));
8315ffd83dbSDimitry Andric       break;
832e8d8bef9SDimitry Andric     case CCValAssign::BCvt: {
833e8d8bef9SDimitry Andric       // Extract a float return value from i64 with padding.
834e8d8bef9SDimitry Andric       //     63     31   0
835e8d8bef9SDimitry Andric       //    +------+------+
836e8d8bef9SDimitry Andric       //    | float|   0  |
837e8d8bef9SDimitry Andric       //    +------+------+
838e8d8bef9SDimitry Andric       assert(VA.getLocVT() == MVT::i64);
839e8d8bef9SDimitry Andric       assert(VA.getValVT() == MVT::f32);
840e8d8bef9SDimitry Andric       SDValue Sub_f32 = DAG.getTargetConstant(VE::sub_f32, DL, MVT::i32);
841e8d8bef9SDimitry Andric       RV = SDValue(DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL,
842e8d8bef9SDimitry Andric                                       MVT::f32, RV, Sub_f32),
843e8d8bef9SDimitry Andric                    0);
844e8d8bef9SDimitry Andric       break;
845e8d8bef9SDimitry Andric     }
8465ffd83dbSDimitry Andric     default:
8475ffd83dbSDimitry Andric       break;
8485ffd83dbSDimitry Andric     }
8495ffd83dbSDimitry Andric 
8505ffd83dbSDimitry Andric     // Truncate the register down to the return value type.
8515ffd83dbSDimitry Andric     if (VA.isExtInLoc())
8525ffd83dbSDimitry Andric       RV = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), RV);
8535ffd83dbSDimitry Andric 
8545ffd83dbSDimitry Andric     InVals.push_back(RV);
8555ffd83dbSDimitry Andric   }
8565ffd83dbSDimitry Andric 
8575ffd83dbSDimitry Andric   return Chain;
8585ffd83dbSDimitry Andric }
8595ffd83dbSDimitry Andric 
isOffsetFoldingLegal(const GlobalAddressSDNode * GA) const860e8d8bef9SDimitry Andric bool VETargetLowering::isOffsetFoldingLegal(
861e8d8bef9SDimitry Andric     const GlobalAddressSDNode *GA) const {
862e8d8bef9SDimitry Andric   // VE uses 64 bit addressing, so we need multiple instructions to generate
863e8d8bef9SDimitry Andric   // an address.  Folding address with offset increases the number of
864e8d8bef9SDimitry Andric   // instructions, so that we disable it here.  Offsets will be folded in
865e8d8bef9SDimitry Andric   // the DAG combine later if it worth to do so.
866e8d8bef9SDimitry Andric   return false;
867e8d8bef9SDimitry Andric }
868e8d8bef9SDimitry Andric 
8695ffd83dbSDimitry Andric /// isFPImmLegal - Returns true if the target can instruction select the
8705ffd83dbSDimitry Andric /// specified FP immediate natively. If false, the legalizer will
8715ffd83dbSDimitry Andric /// materialize the FP immediate as a load from a constant pool.
isFPImmLegal(const APFloat & Imm,EVT VT,bool ForCodeSize) const8725ffd83dbSDimitry Andric bool VETargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
8735ffd83dbSDimitry Andric                                     bool ForCodeSize) const {
8745ffd83dbSDimitry Andric   return VT == MVT::f32 || VT == MVT::f64;
8755ffd83dbSDimitry Andric }
8765ffd83dbSDimitry Andric 
8775ffd83dbSDimitry Andric /// Determine if the target supports unaligned memory accesses.
8785ffd83dbSDimitry Andric ///
8795ffd83dbSDimitry Andric /// This function returns true if the target allows unaligned memory accesses
8805ffd83dbSDimitry Andric /// of the specified type in the given address space. If true, it also returns
8815ffd83dbSDimitry Andric /// whether the unaligned memory access is "fast" in the last argument by
8825ffd83dbSDimitry Andric /// reference. This is used, for example, in situations where an array
8835ffd83dbSDimitry Andric /// copy/move/set is converted to a sequence of store operations. Its use
8845ffd83dbSDimitry Andric /// helps to ensure that such replacements don't generate code that causes an
8855ffd83dbSDimitry Andric /// alignment error (trap) on the target machine.
allowsMisalignedMemoryAccesses(EVT VT,unsigned AddrSpace,Align A,MachineMemOperand::Flags,unsigned * Fast) const8865ffd83dbSDimitry Andric bool VETargetLowering::allowsMisalignedMemoryAccesses(EVT VT,
8875ffd83dbSDimitry Andric                                                       unsigned AddrSpace,
888fe6060f1SDimitry Andric                                                       Align A,
8895ffd83dbSDimitry Andric                                                       MachineMemOperand::Flags,
890bdd1243dSDimitry Andric                                                       unsigned *Fast) const {
8915ffd83dbSDimitry Andric   if (Fast) {
8925ffd83dbSDimitry Andric     // It's fast anytime on VE
893bdd1243dSDimitry Andric     *Fast = 1;
8945ffd83dbSDimitry Andric   }
8955ffd83dbSDimitry Andric   return true;
8965ffd83dbSDimitry Andric }
8975ffd83dbSDimitry Andric 
VETargetLowering(const TargetMachine & TM,const VESubtarget & STI)898480093f4SDimitry Andric VETargetLowering::VETargetLowering(const TargetMachine &TM,
899480093f4SDimitry Andric                                    const VESubtarget &STI)
900480093f4SDimitry Andric     : TargetLowering(TM), Subtarget(&STI) {
901480093f4SDimitry Andric   // Instructions which use registers as conditionals examine all the
902480093f4SDimitry Andric   // bits (as does the pseudo SELECT_CC expansion). I don't think it
903480093f4SDimitry Andric   // matters much whether it's ZeroOrOneBooleanContent, or
904480093f4SDimitry Andric   // ZeroOrNegativeOneBooleanContent, so, arbitrarily choose the
905480093f4SDimitry Andric   // former.
906480093f4SDimitry Andric   setBooleanContents(ZeroOrOneBooleanContent);
907480093f4SDimitry Andric   setBooleanVectorContents(ZeroOrOneBooleanContent);
908480093f4SDimitry Andric 
909e8d8bef9SDimitry Andric   initRegisterClasses();
910e8d8bef9SDimitry Andric   initSPUActions();
911e8d8bef9SDimitry Andric   initVPUActions();
912480093f4SDimitry Andric 
913480093f4SDimitry Andric   setStackPointerRegisterToSaveRestore(VE::SX11);
914480093f4SDimitry Andric 
915e8d8bef9SDimitry Andric   // We have target-specific dag combine patterns for the following nodes:
916e8d8bef9SDimitry Andric   setTargetDAGCombine(ISD::TRUNCATE);
917bdd1243dSDimitry Andric   setTargetDAGCombine(ISD::SELECT);
918bdd1243dSDimitry Andric   setTargetDAGCombine(ISD::SELECT_CC);
919e8d8bef9SDimitry Andric 
920480093f4SDimitry Andric   // Set function alignment to 16 bytes
921480093f4SDimitry Andric   setMinFunctionAlignment(Align(16));
922480093f4SDimitry Andric 
923480093f4SDimitry Andric   // VE stores all argument by 8 bytes alignment
924480093f4SDimitry Andric   setMinStackArgumentAlignment(Align(8));
925480093f4SDimitry Andric 
926480093f4SDimitry Andric   computeRegisterProperties(Subtarget->getRegisterInfo());
927480093f4SDimitry Andric }
928480093f4SDimitry Andric 
getTargetNodeName(unsigned Opcode) const929480093f4SDimitry Andric const char *VETargetLowering::getTargetNodeName(unsigned Opcode) const {
9305ffd83dbSDimitry Andric #define TARGET_NODE_CASE(NAME)                                                 \
9315ffd83dbSDimitry Andric   case VEISD::NAME:                                                            \
9325ffd83dbSDimitry Andric     return "VEISD::" #NAME;
933480093f4SDimitry Andric   switch ((VEISD::NodeType)Opcode) {
934480093f4SDimitry Andric   case VEISD::FIRST_NUMBER:
935480093f4SDimitry Andric     break;
936bdd1243dSDimitry Andric     TARGET_NODE_CASE(CMPI)
937bdd1243dSDimitry Andric     TARGET_NODE_CASE(CMPU)
938bdd1243dSDimitry Andric     TARGET_NODE_CASE(CMPF)
939bdd1243dSDimitry Andric     TARGET_NODE_CASE(CMPQ)
940bdd1243dSDimitry Andric     TARGET_NODE_CASE(CMOV)
941e8d8bef9SDimitry Andric     TARGET_NODE_CASE(CALL)
942e8d8bef9SDimitry Andric     TARGET_NODE_CASE(EH_SJLJ_LONGJMP)
943e8d8bef9SDimitry Andric     TARGET_NODE_CASE(EH_SJLJ_SETJMP)
944e8d8bef9SDimitry Andric     TARGET_NODE_CASE(EH_SJLJ_SETUP_DISPATCH)
9455ffd83dbSDimitry Andric     TARGET_NODE_CASE(GETFUNPLT)
9465ffd83dbSDimitry Andric     TARGET_NODE_CASE(GETSTACKTOP)
9475ffd83dbSDimitry Andric     TARGET_NODE_CASE(GETTLSADDR)
9485ffd83dbSDimitry Andric     TARGET_NODE_CASE(GLOBAL_BASE_REG)
949e8d8bef9SDimitry Andric     TARGET_NODE_CASE(Hi)
950e8d8bef9SDimitry Andric     TARGET_NODE_CASE(Lo)
95106c3fb27SDimitry Andric     TARGET_NODE_CASE(RET_GLUE)
952e8d8bef9SDimitry Andric     TARGET_NODE_CASE(TS1AM)
95381ad6265SDimitry Andric     TARGET_NODE_CASE(VEC_UNPACK_LO)
95481ad6265SDimitry Andric     TARGET_NODE_CASE(VEC_UNPACK_HI)
95581ad6265SDimitry Andric     TARGET_NODE_CASE(VEC_PACK)
956e8d8bef9SDimitry Andric     TARGET_NODE_CASE(VEC_BROADCAST)
95704eeddc0SDimitry Andric     TARGET_NODE_CASE(REPL_I32)
95804eeddc0SDimitry Andric     TARGET_NODE_CASE(REPL_F32)
959e8d8bef9SDimitry Andric 
96081ad6265SDimitry Andric     TARGET_NODE_CASE(LEGALAVL)
96181ad6265SDimitry Andric 
962e8d8bef9SDimitry Andric     // Register the VVP_* SDNodes.
963e8d8bef9SDimitry Andric #define ADD_VVP_OP(VVP_NAME, ...) TARGET_NODE_CASE(VVP_NAME)
964e8d8bef9SDimitry Andric #include "VVPNodes.def"
965480093f4SDimitry Andric   }
9665ffd83dbSDimitry Andric #undef TARGET_NODE_CASE
967480093f4SDimitry Andric   return nullptr;
968480093f4SDimitry Andric }
969480093f4SDimitry Andric 
getSetCCResultType(const DataLayout &,LLVMContext &,EVT VT) const970480093f4SDimitry Andric EVT VETargetLowering::getSetCCResultType(const DataLayout &, LLVMContext &,
971480093f4SDimitry Andric                                          EVT VT) const {
9725ffd83dbSDimitry Andric   return MVT::i32;
973480093f4SDimitry Andric }
9745ffd83dbSDimitry Andric 
9755ffd83dbSDimitry Andric // Convert to a target node and set target flags.
withTargetFlags(SDValue Op,unsigned TF,SelectionDAG & DAG) const9765ffd83dbSDimitry Andric SDValue VETargetLowering::withTargetFlags(SDValue Op, unsigned TF,
9775ffd83dbSDimitry Andric                                           SelectionDAG &DAG) const {
9785ffd83dbSDimitry Andric   if (const GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op))
9795ffd83dbSDimitry Andric     return DAG.getTargetGlobalAddress(GA->getGlobal(), SDLoc(GA),
9805ffd83dbSDimitry Andric                                       GA->getValueType(0), GA->getOffset(), TF);
9815ffd83dbSDimitry Andric 
9825ffd83dbSDimitry Andric   if (const BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op))
9835ffd83dbSDimitry Andric     return DAG.getTargetBlockAddress(BA->getBlockAddress(), Op.getValueType(),
9845ffd83dbSDimitry Andric                                      0, TF);
9855ffd83dbSDimitry Andric 
986e8d8bef9SDimitry Andric   if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Op))
987e8d8bef9SDimitry Andric     return DAG.getTargetConstantPool(CP->getConstVal(), CP->getValueType(0),
988e8d8bef9SDimitry Andric                                      CP->getAlign(), CP->getOffset(), TF);
989e8d8bef9SDimitry Andric 
9905ffd83dbSDimitry Andric   if (const ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op))
9915ffd83dbSDimitry Andric     return DAG.getTargetExternalSymbol(ES->getSymbol(), ES->getValueType(0),
9925ffd83dbSDimitry Andric                                        TF);
9935ffd83dbSDimitry Andric 
994e8d8bef9SDimitry Andric   if (const JumpTableSDNode *JT = dyn_cast<JumpTableSDNode>(Op))
995e8d8bef9SDimitry Andric     return DAG.getTargetJumpTable(JT->getIndex(), JT->getValueType(0), TF);
996e8d8bef9SDimitry Andric 
9975ffd83dbSDimitry Andric   llvm_unreachable("Unhandled address SDNode");
9985ffd83dbSDimitry Andric }
9995ffd83dbSDimitry Andric 
10005ffd83dbSDimitry Andric // Split Op into high and low parts according to HiTF and LoTF.
10015ffd83dbSDimitry Andric // Return an ADD node combining the parts.
makeHiLoPair(SDValue Op,unsigned HiTF,unsigned LoTF,SelectionDAG & DAG) const10025ffd83dbSDimitry Andric SDValue VETargetLowering::makeHiLoPair(SDValue Op, unsigned HiTF, unsigned LoTF,
10035ffd83dbSDimitry Andric                                        SelectionDAG &DAG) const {
10045ffd83dbSDimitry Andric   SDLoc DL(Op);
10055ffd83dbSDimitry Andric   EVT VT = Op.getValueType();
10065ffd83dbSDimitry Andric   SDValue Hi = DAG.getNode(VEISD::Hi, DL, VT, withTargetFlags(Op, HiTF, DAG));
10075ffd83dbSDimitry Andric   SDValue Lo = DAG.getNode(VEISD::Lo, DL, VT, withTargetFlags(Op, LoTF, DAG));
10085ffd83dbSDimitry Andric   return DAG.getNode(ISD::ADD, DL, VT, Hi, Lo);
10095ffd83dbSDimitry Andric }
10105ffd83dbSDimitry Andric 
10115ffd83dbSDimitry Andric // Build SDNodes for producing an address from a GlobalAddress, ConstantPool,
10125ffd83dbSDimitry Andric // or ExternalSymbol SDNode.
makeAddress(SDValue Op,SelectionDAG & DAG) const10135ffd83dbSDimitry Andric SDValue VETargetLowering::makeAddress(SDValue Op, SelectionDAG &DAG) const {
10145ffd83dbSDimitry Andric   SDLoc DL(Op);
10155ffd83dbSDimitry Andric   EVT PtrVT = Op.getValueType();
10165ffd83dbSDimitry Andric 
10175ffd83dbSDimitry Andric   // Handle PIC mode first. VE needs a got load for every variable!
10185ffd83dbSDimitry Andric   if (isPositionIndependent()) {
10195ffd83dbSDimitry Andric     auto GlobalN = dyn_cast<GlobalAddressSDNode>(Op);
10205ffd83dbSDimitry Andric 
1021e8d8bef9SDimitry Andric     if (isa<ConstantPoolSDNode>(Op) || isa<JumpTableSDNode>(Op) ||
10225ffd83dbSDimitry Andric         (GlobalN && GlobalN->getGlobal()->hasLocalLinkage())) {
10235ffd83dbSDimitry Andric       // Create following instructions for local linkage PIC code.
1024e8d8bef9SDimitry Andric       //     lea %reg, label@gotoff_lo
1025e8d8bef9SDimitry Andric       //     and %reg, %reg, (32)0
1026e8d8bef9SDimitry Andric       //     lea.sl %reg, label@gotoff_hi(%reg, %got)
10275ffd83dbSDimitry Andric       SDValue HiLo = makeHiLoPair(Op, VEMCExpr::VK_VE_GOTOFF_HI32,
10285ffd83dbSDimitry Andric                                   VEMCExpr::VK_VE_GOTOFF_LO32, DAG);
10295ffd83dbSDimitry Andric       SDValue GlobalBase = DAG.getNode(VEISD::GLOBAL_BASE_REG, DL, PtrVT);
10305ffd83dbSDimitry Andric       return DAG.getNode(ISD::ADD, DL, PtrVT, GlobalBase, HiLo);
10315ffd83dbSDimitry Andric     }
10325ffd83dbSDimitry Andric     // Create following instructions for not local linkage PIC code.
1033e8d8bef9SDimitry Andric     //     lea %reg, label@got_lo
1034e8d8bef9SDimitry Andric     //     and %reg, %reg, (32)0
1035e8d8bef9SDimitry Andric     //     lea.sl %reg, label@got_hi(%reg)
1036e8d8bef9SDimitry Andric     //     ld %reg, (%reg, %got)
10375ffd83dbSDimitry Andric     SDValue HiLo = makeHiLoPair(Op, VEMCExpr::VK_VE_GOT_HI32,
10385ffd83dbSDimitry Andric                                 VEMCExpr::VK_VE_GOT_LO32, DAG);
10395ffd83dbSDimitry Andric     SDValue GlobalBase = DAG.getNode(VEISD::GLOBAL_BASE_REG, DL, PtrVT);
10405ffd83dbSDimitry Andric     SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, PtrVT, GlobalBase, HiLo);
10415ffd83dbSDimitry Andric     return DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), AbsAddr,
10425ffd83dbSDimitry Andric                        MachinePointerInfo::getGOT(DAG.getMachineFunction()));
10435ffd83dbSDimitry Andric   }
10445ffd83dbSDimitry Andric 
10455ffd83dbSDimitry Andric   // This is one of the absolute code models.
10465ffd83dbSDimitry Andric   switch (getTargetMachine().getCodeModel()) {
10475ffd83dbSDimitry Andric   default:
10485ffd83dbSDimitry Andric     llvm_unreachable("Unsupported absolute code model");
10495ffd83dbSDimitry Andric   case CodeModel::Small:
10505ffd83dbSDimitry Andric   case CodeModel::Medium:
10515ffd83dbSDimitry Andric   case CodeModel::Large:
10525ffd83dbSDimitry Andric     // abs64.
10535ffd83dbSDimitry Andric     return makeHiLoPair(Op, VEMCExpr::VK_VE_HI32, VEMCExpr::VK_VE_LO32, DAG);
10545ffd83dbSDimitry Andric   }
10555ffd83dbSDimitry Andric }
10565ffd83dbSDimitry Andric 
10575ffd83dbSDimitry Andric /// Custom Lower {
10585ffd83dbSDimitry Andric 
1059e8d8bef9SDimitry Andric // The mappings for emitLeading/TrailingFence for VE is designed by following
1060e8d8bef9SDimitry Andric // http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
emitLeadingFence(IRBuilderBase & Builder,Instruction * Inst,AtomicOrdering Ord) const1061fe6060f1SDimitry Andric Instruction *VETargetLowering::emitLeadingFence(IRBuilderBase &Builder,
1062e8d8bef9SDimitry Andric                                                 Instruction *Inst,
1063e8d8bef9SDimitry Andric                                                 AtomicOrdering Ord) const {
1064e8d8bef9SDimitry Andric   switch (Ord) {
1065e8d8bef9SDimitry Andric   case AtomicOrdering::NotAtomic:
1066e8d8bef9SDimitry Andric   case AtomicOrdering::Unordered:
1067e8d8bef9SDimitry Andric     llvm_unreachable("Invalid fence: unordered/non-atomic");
1068e8d8bef9SDimitry Andric   case AtomicOrdering::Monotonic:
1069e8d8bef9SDimitry Andric   case AtomicOrdering::Acquire:
1070e8d8bef9SDimitry Andric     return nullptr; // Nothing to do
1071e8d8bef9SDimitry Andric   case AtomicOrdering::Release:
1072e8d8bef9SDimitry Andric   case AtomicOrdering::AcquireRelease:
1073e8d8bef9SDimitry Andric     return Builder.CreateFence(AtomicOrdering::Release);
1074e8d8bef9SDimitry Andric   case AtomicOrdering::SequentiallyConsistent:
1075e8d8bef9SDimitry Andric     if (!Inst->hasAtomicStore())
1076e8d8bef9SDimitry Andric       return nullptr; // Nothing to do
1077e8d8bef9SDimitry Andric     return Builder.CreateFence(AtomicOrdering::SequentiallyConsistent);
1078e8d8bef9SDimitry Andric   }
1079e8d8bef9SDimitry Andric   llvm_unreachable("Unknown fence ordering in emitLeadingFence");
1080e8d8bef9SDimitry Andric }
1081e8d8bef9SDimitry Andric 
emitTrailingFence(IRBuilderBase & Builder,Instruction * Inst,AtomicOrdering Ord) const1082fe6060f1SDimitry Andric Instruction *VETargetLowering::emitTrailingFence(IRBuilderBase &Builder,
1083e8d8bef9SDimitry Andric                                                  Instruction *Inst,
1084e8d8bef9SDimitry Andric                                                  AtomicOrdering Ord) const {
1085e8d8bef9SDimitry Andric   switch (Ord) {
1086e8d8bef9SDimitry Andric   case AtomicOrdering::NotAtomic:
1087e8d8bef9SDimitry Andric   case AtomicOrdering::Unordered:
1088e8d8bef9SDimitry Andric     llvm_unreachable("Invalid fence: unordered/not-atomic");
1089e8d8bef9SDimitry Andric   case AtomicOrdering::Monotonic:
1090e8d8bef9SDimitry Andric   case AtomicOrdering::Release:
1091e8d8bef9SDimitry Andric     return nullptr; // Nothing to do
1092e8d8bef9SDimitry Andric   case AtomicOrdering::Acquire:
1093e8d8bef9SDimitry Andric   case AtomicOrdering::AcquireRelease:
1094e8d8bef9SDimitry Andric     return Builder.CreateFence(AtomicOrdering::Acquire);
1095e8d8bef9SDimitry Andric   case AtomicOrdering::SequentiallyConsistent:
1096e8d8bef9SDimitry Andric     return Builder.CreateFence(AtomicOrdering::SequentiallyConsistent);
1097e8d8bef9SDimitry Andric   }
1098e8d8bef9SDimitry Andric   llvm_unreachable("Unknown fence ordering in emitTrailingFence");
1099e8d8bef9SDimitry Andric }
1100e8d8bef9SDimitry Andric 
lowerATOMIC_FENCE(SDValue Op,SelectionDAG & DAG) const1101e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerATOMIC_FENCE(SDValue Op,
1102e8d8bef9SDimitry Andric                                             SelectionDAG &DAG) const {
1103e8d8bef9SDimitry Andric   SDLoc DL(Op);
1104*647cbc5dSDimitry Andric   AtomicOrdering FenceOrdering =
1105*647cbc5dSDimitry Andric       static_cast<AtomicOrdering>(Op.getConstantOperandVal(1));
1106*647cbc5dSDimitry Andric   SyncScope::ID FenceSSID =
1107*647cbc5dSDimitry Andric       static_cast<SyncScope::ID>(Op.getConstantOperandVal(2));
1108e8d8bef9SDimitry Andric 
1109e8d8bef9SDimitry Andric   // VE uses Release consistency, so need a fence instruction if it is a
1110e8d8bef9SDimitry Andric   // cross-thread fence.
1111e8d8bef9SDimitry Andric   if (FenceSSID == SyncScope::System) {
1112e8d8bef9SDimitry Andric     switch (FenceOrdering) {
1113e8d8bef9SDimitry Andric     case AtomicOrdering::NotAtomic:
1114e8d8bef9SDimitry Andric     case AtomicOrdering::Unordered:
1115e8d8bef9SDimitry Andric     case AtomicOrdering::Monotonic:
1116e8d8bef9SDimitry Andric       // No need to generate fencem instruction here.
1117e8d8bef9SDimitry Andric       break;
1118e8d8bef9SDimitry Andric     case AtomicOrdering::Acquire:
1119e8d8bef9SDimitry Andric       // Generate "fencem 2" as acquire fence.
1120e8d8bef9SDimitry Andric       return SDValue(DAG.getMachineNode(VE::FENCEM, DL, MVT::Other,
1121e8d8bef9SDimitry Andric                                         DAG.getTargetConstant(2, DL, MVT::i32),
1122e8d8bef9SDimitry Andric                                         Op.getOperand(0)),
1123e8d8bef9SDimitry Andric                      0);
1124e8d8bef9SDimitry Andric     case AtomicOrdering::Release:
1125e8d8bef9SDimitry Andric       // Generate "fencem 1" as release fence.
1126e8d8bef9SDimitry Andric       return SDValue(DAG.getMachineNode(VE::FENCEM, DL, MVT::Other,
1127e8d8bef9SDimitry Andric                                         DAG.getTargetConstant(1, DL, MVT::i32),
1128e8d8bef9SDimitry Andric                                         Op.getOperand(0)),
1129e8d8bef9SDimitry Andric                      0);
1130e8d8bef9SDimitry Andric     case AtomicOrdering::AcquireRelease:
1131e8d8bef9SDimitry Andric     case AtomicOrdering::SequentiallyConsistent:
1132e8d8bef9SDimitry Andric       // Generate "fencem 3" as acq_rel and seq_cst fence.
11335f757f3fSDimitry Andric       // FIXME: "fencem 3" doesn't wait for PCIe deveices accesses,
1134e8d8bef9SDimitry Andric       //        so  seq_cst may require more instruction for them.
1135e8d8bef9SDimitry Andric       return SDValue(DAG.getMachineNode(VE::FENCEM, DL, MVT::Other,
1136e8d8bef9SDimitry Andric                                         DAG.getTargetConstant(3, DL, MVT::i32),
1137e8d8bef9SDimitry Andric                                         Op.getOperand(0)),
1138e8d8bef9SDimitry Andric                      0);
1139e8d8bef9SDimitry Andric     }
1140e8d8bef9SDimitry Andric   }
1141e8d8bef9SDimitry Andric 
1142e8d8bef9SDimitry Andric   // MEMBARRIER is a compiler barrier; it codegens to a no-op.
1143bdd1243dSDimitry Andric   return DAG.getNode(ISD::MEMBARRIER, DL, MVT::Other, Op.getOperand(0));
1144e8d8bef9SDimitry Andric }
1145e8d8bef9SDimitry Andric 
1146e8d8bef9SDimitry Andric TargetLowering::AtomicExpansionKind
shouldExpandAtomicRMWInIR(AtomicRMWInst * AI) const1147e8d8bef9SDimitry Andric VETargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
1148e8d8bef9SDimitry Andric   // We have TS1AM implementation for i8/i16/i32/i64, so use it.
1149e8d8bef9SDimitry Andric   if (AI->getOperation() == AtomicRMWInst::Xchg) {
1150e8d8bef9SDimitry Andric     return AtomicExpansionKind::None;
1151e8d8bef9SDimitry Andric   }
1152e8d8bef9SDimitry Andric   // FIXME: Support "ATMAM" instruction for LOAD_ADD/SUB/AND/OR.
1153e8d8bef9SDimitry Andric 
1154e8d8bef9SDimitry Andric   // Otherwise, expand it using compare and exchange instruction to not call
1155e8d8bef9SDimitry Andric   // __sync_fetch_and_* functions.
1156e8d8bef9SDimitry Andric   return AtomicExpansionKind::CmpXChg;
1157e8d8bef9SDimitry Andric }
1158e8d8bef9SDimitry Andric 
prepareTS1AM(SDValue Op,SelectionDAG & DAG,SDValue & Flag,SDValue & Bits)1159e8d8bef9SDimitry Andric static SDValue prepareTS1AM(SDValue Op, SelectionDAG &DAG, SDValue &Flag,
1160e8d8bef9SDimitry Andric                             SDValue &Bits) {
1161e8d8bef9SDimitry Andric   SDLoc DL(Op);
1162e8d8bef9SDimitry Andric   AtomicSDNode *N = cast<AtomicSDNode>(Op);
1163e8d8bef9SDimitry Andric   SDValue Ptr = N->getOperand(1);
1164e8d8bef9SDimitry Andric   SDValue Val = N->getOperand(2);
1165e8d8bef9SDimitry Andric   EVT PtrVT = Ptr.getValueType();
1166e8d8bef9SDimitry Andric   bool Byte = N->getMemoryVT() == MVT::i8;
1167e8d8bef9SDimitry Andric   //   Remainder = AND Ptr, 3
1168e8d8bef9SDimitry Andric   //   Flag = 1 << Remainder  ; If Byte is true (1 byte swap flag)
1169e8d8bef9SDimitry Andric   //   Flag = 3 << Remainder  ; If Byte is false (2 bytes swap flag)
1170e8d8bef9SDimitry Andric   //   Bits = Remainder << 3
1171e8d8bef9SDimitry Andric   //   NewVal = Val << Bits
1172e8d8bef9SDimitry Andric   SDValue Const3 = DAG.getConstant(3, DL, PtrVT);
1173e8d8bef9SDimitry Andric   SDValue Remainder = DAG.getNode(ISD::AND, DL, PtrVT, {Ptr, Const3});
1174e8d8bef9SDimitry Andric   SDValue Mask = Byte ? DAG.getConstant(1, DL, MVT::i32)
1175e8d8bef9SDimitry Andric                       : DAG.getConstant(3, DL, MVT::i32);
1176e8d8bef9SDimitry Andric   Flag = DAG.getNode(ISD::SHL, DL, MVT::i32, {Mask, Remainder});
1177e8d8bef9SDimitry Andric   Bits = DAG.getNode(ISD::SHL, DL, PtrVT, {Remainder, Const3});
1178e8d8bef9SDimitry Andric   return DAG.getNode(ISD::SHL, DL, Val.getValueType(), {Val, Bits});
1179e8d8bef9SDimitry Andric }
1180e8d8bef9SDimitry Andric 
finalizeTS1AM(SDValue Op,SelectionDAG & DAG,SDValue Data,SDValue Bits)1181e8d8bef9SDimitry Andric static SDValue finalizeTS1AM(SDValue Op, SelectionDAG &DAG, SDValue Data,
1182e8d8bef9SDimitry Andric                              SDValue Bits) {
1183e8d8bef9SDimitry Andric   SDLoc DL(Op);
1184e8d8bef9SDimitry Andric   EVT VT = Data.getValueType();
1185e8d8bef9SDimitry Andric   bool Byte = cast<AtomicSDNode>(Op)->getMemoryVT() == MVT::i8;
1186e8d8bef9SDimitry Andric   //   NewData = Data >> Bits
1187e8d8bef9SDimitry Andric   //   Result = NewData & 0xff   ; If Byte is true (1 byte)
1188e8d8bef9SDimitry Andric   //   Result = NewData & 0xffff ; If Byte is false (2 bytes)
1189e8d8bef9SDimitry Andric 
1190e8d8bef9SDimitry Andric   SDValue NewData = DAG.getNode(ISD::SRL, DL, VT, Data, Bits);
1191e8d8bef9SDimitry Andric   return DAG.getNode(ISD::AND, DL, VT,
1192e8d8bef9SDimitry Andric                      {NewData, DAG.getConstant(Byte ? 0xff : 0xffff, DL, VT)});
1193e8d8bef9SDimitry Andric }
1194e8d8bef9SDimitry Andric 
lowerATOMIC_SWAP(SDValue Op,SelectionDAG & DAG) const1195e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerATOMIC_SWAP(SDValue Op,
1196e8d8bef9SDimitry Andric                                            SelectionDAG &DAG) const {
1197e8d8bef9SDimitry Andric   SDLoc DL(Op);
1198e8d8bef9SDimitry Andric   AtomicSDNode *N = cast<AtomicSDNode>(Op);
1199e8d8bef9SDimitry Andric 
1200e8d8bef9SDimitry Andric   if (N->getMemoryVT() == MVT::i8) {
1201e8d8bef9SDimitry Andric     // For i8, use "ts1am"
1202e8d8bef9SDimitry Andric     //   Input:
1203e8d8bef9SDimitry Andric     //     ATOMIC_SWAP Ptr, Val, Order
1204e8d8bef9SDimitry Andric     //
1205e8d8bef9SDimitry Andric     //   Output:
1206e8d8bef9SDimitry Andric     //     Remainder = AND Ptr, 3
1207e8d8bef9SDimitry Andric     //     Flag = 1 << Remainder   ; 1 byte swap flag for TS1AM inst.
1208e8d8bef9SDimitry Andric     //     Bits = Remainder << 3
1209e8d8bef9SDimitry Andric     //     NewVal = Val << Bits
1210e8d8bef9SDimitry Andric     //
1211e8d8bef9SDimitry Andric     //     Aligned = AND Ptr, -4
1212e8d8bef9SDimitry Andric     //     Data = TS1AM Aligned, Flag, NewVal
1213e8d8bef9SDimitry Andric     //
1214e8d8bef9SDimitry Andric     //     NewData = Data >> Bits
1215e8d8bef9SDimitry Andric     //     Result = NewData & 0xff ; 1 byte result
1216e8d8bef9SDimitry Andric     SDValue Flag;
1217e8d8bef9SDimitry Andric     SDValue Bits;
1218e8d8bef9SDimitry Andric     SDValue NewVal = prepareTS1AM(Op, DAG, Flag, Bits);
1219e8d8bef9SDimitry Andric 
1220e8d8bef9SDimitry Andric     SDValue Ptr = N->getOperand(1);
1221e8d8bef9SDimitry Andric     SDValue Aligned = DAG.getNode(ISD::AND, DL, Ptr.getValueType(),
1222e8d8bef9SDimitry Andric                                   {Ptr, DAG.getConstant(-4, DL, MVT::i64)});
1223e8d8bef9SDimitry Andric     SDValue TS1AM = DAG.getAtomic(VEISD::TS1AM, DL, N->getMemoryVT(),
1224e8d8bef9SDimitry Andric                                   DAG.getVTList(Op.getNode()->getValueType(0),
1225e8d8bef9SDimitry Andric                                                 Op.getNode()->getValueType(1)),
1226e8d8bef9SDimitry Andric                                   {N->getChain(), Aligned, Flag, NewVal},
1227e8d8bef9SDimitry Andric                                   N->getMemOperand());
1228e8d8bef9SDimitry Andric 
1229e8d8bef9SDimitry Andric     SDValue Result = finalizeTS1AM(Op, DAG, TS1AM, Bits);
1230e8d8bef9SDimitry Andric     SDValue Chain = TS1AM.getValue(1);
1231e8d8bef9SDimitry Andric     return DAG.getMergeValues({Result, Chain}, DL);
1232e8d8bef9SDimitry Andric   }
1233e8d8bef9SDimitry Andric   if (N->getMemoryVT() == MVT::i16) {
1234e8d8bef9SDimitry Andric     // For i16, use "ts1am"
1235e8d8bef9SDimitry Andric     SDValue Flag;
1236e8d8bef9SDimitry Andric     SDValue Bits;
1237e8d8bef9SDimitry Andric     SDValue NewVal = prepareTS1AM(Op, DAG, Flag, Bits);
1238e8d8bef9SDimitry Andric 
1239e8d8bef9SDimitry Andric     SDValue Ptr = N->getOperand(1);
1240e8d8bef9SDimitry Andric     SDValue Aligned = DAG.getNode(ISD::AND, DL, Ptr.getValueType(),
1241e8d8bef9SDimitry Andric                                   {Ptr, DAG.getConstant(-4, DL, MVT::i64)});
1242e8d8bef9SDimitry Andric     SDValue TS1AM = DAG.getAtomic(VEISD::TS1AM, DL, N->getMemoryVT(),
1243e8d8bef9SDimitry Andric                                   DAG.getVTList(Op.getNode()->getValueType(0),
1244e8d8bef9SDimitry Andric                                                 Op.getNode()->getValueType(1)),
1245e8d8bef9SDimitry Andric                                   {N->getChain(), Aligned, Flag, NewVal},
1246e8d8bef9SDimitry Andric                                   N->getMemOperand());
1247e8d8bef9SDimitry Andric 
1248e8d8bef9SDimitry Andric     SDValue Result = finalizeTS1AM(Op, DAG, TS1AM, Bits);
1249e8d8bef9SDimitry Andric     SDValue Chain = TS1AM.getValue(1);
1250e8d8bef9SDimitry Andric     return DAG.getMergeValues({Result, Chain}, DL);
1251e8d8bef9SDimitry Andric   }
1252e8d8bef9SDimitry Andric   // Otherwise, let llvm legalize it.
1253e8d8bef9SDimitry Andric   return Op;
1254e8d8bef9SDimitry Andric }
1255e8d8bef9SDimitry Andric 
lowerGlobalAddress(SDValue Op,SelectionDAG & DAG) const1256e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerGlobalAddress(SDValue Op,
12575ffd83dbSDimitry Andric                                              SelectionDAG &DAG) const {
12585ffd83dbSDimitry Andric   return makeAddress(Op, DAG);
12595ffd83dbSDimitry Andric }
12605ffd83dbSDimitry Andric 
lowerBlockAddress(SDValue Op,SelectionDAG & DAG) const1261e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerBlockAddress(SDValue Op,
1262e8d8bef9SDimitry Andric                                             SelectionDAG &DAG) const {
1263e8d8bef9SDimitry Andric   return makeAddress(Op, DAG);
1264e8d8bef9SDimitry Andric }
1265e8d8bef9SDimitry Andric 
lowerConstantPool(SDValue Op,SelectionDAG & DAG) const1266e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerConstantPool(SDValue Op,
12675ffd83dbSDimitry Andric                                             SelectionDAG &DAG) const {
12685ffd83dbSDimitry Andric   return makeAddress(Op, DAG);
12695ffd83dbSDimitry Andric }
12705ffd83dbSDimitry Andric 
12715ffd83dbSDimitry Andric SDValue
lowerToTLSGeneralDynamicModel(SDValue Op,SelectionDAG & DAG) const1272e8d8bef9SDimitry Andric VETargetLowering::lowerToTLSGeneralDynamicModel(SDValue Op,
12735ffd83dbSDimitry Andric                                                 SelectionDAG &DAG) const {
1274e8d8bef9SDimitry Andric   SDLoc DL(Op);
12755ffd83dbSDimitry Andric 
12765ffd83dbSDimitry Andric   // Generate the following code:
12775ffd83dbSDimitry Andric   //   t1: ch,glue = callseq_start t0, 0, 0
12785ffd83dbSDimitry Andric   //   t2: i64,ch,glue = VEISD::GETTLSADDR t1, label, t1:1
12795ffd83dbSDimitry Andric   //   t3: ch,glue = callseq_end t2, 0, 0, t2:2
12805ffd83dbSDimitry Andric   //   t4: i64,ch,glue = CopyFromReg t3, Register:i64 $sx0, t3:1
12815ffd83dbSDimitry Andric   SDValue Label = withTargetFlags(Op, 0, DAG);
12825ffd83dbSDimitry Andric   EVT PtrVT = Op.getValueType();
12835ffd83dbSDimitry Andric 
12845ffd83dbSDimitry Andric   // Lowering the machine isd will make sure everything is in the right
12855ffd83dbSDimitry Andric   // location.
12865ffd83dbSDimitry Andric   SDValue Chain = DAG.getEntryNode();
12875ffd83dbSDimitry Andric   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
12885ffd83dbSDimitry Andric   const uint32_t *Mask = Subtarget->getRegisterInfo()->getCallPreservedMask(
12895ffd83dbSDimitry Andric       DAG.getMachineFunction(), CallingConv::C);
1290e8d8bef9SDimitry Andric   Chain = DAG.getCALLSEQ_START(Chain, 64, 0, DL);
12915ffd83dbSDimitry Andric   SDValue Args[] = {Chain, Label, DAG.getRegisterMask(Mask), Chain.getValue(1)};
1292e8d8bef9SDimitry Andric   Chain = DAG.getNode(VEISD::GETTLSADDR, DL, NodeTys, Args);
1293bdd1243dSDimitry Andric   Chain = DAG.getCALLSEQ_END(Chain, 64, 0, Chain.getValue(1), DL);
1294e8d8bef9SDimitry Andric   Chain = DAG.getCopyFromReg(Chain, DL, VE::SX0, PtrVT, Chain.getValue(1));
12955ffd83dbSDimitry Andric 
12965ffd83dbSDimitry Andric   // GETTLSADDR will be codegen'ed as call. Inform MFI that function has calls.
12975ffd83dbSDimitry Andric   MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
12985ffd83dbSDimitry Andric   MFI.setHasCalls(true);
12995ffd83dbSDimitry Andric 
13005ffd83dbSDimitry Andric   // Also generate code to prepare a GOT register if it is PIC.
13015ffd83dbSDimitry Andric   if (isPositionIndependent()) {
13025ffd83dbSDimitry Andric     MachineFunction &MF = DAG.getMachineFunction();
13035ffd83dbSDimitry Andric     Subtarget->getInstrInfo()->getGlobalBaseReg(&MF);
13045ffd83dbSDimitry Andric   }
13055ffd83dbSDimitry Andric 
13065ffd83dbSDimitry Andric   return Chain;
13075ffd83dbSDimitry Andric }
13085ffd83dbSDimitry Andric 
lowerGlobalTLSAddress(SDValue Op,SelectionDAG & DAG) const1309e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerGlobalTLSAddress(SDValue Op,
13105ffd83dbSDimitry Andric                                                 SelectionDAG &DAG) const {
13115ffd83dbSDimitry Andric   // The current implementation of nld (2.26) doesn't allow local exec model
13125ffd83dbSDimitry Andric   // code described in VE-tls_v1.1.pdf (*1) as its input. Instead, we always
13135ffd83dbSDimitry Andric   // generate the general dynamic model code sequence.
13145ffd83dbSDimitry Andric   //
13155ffd83dbSDimitry Andric   // *1: https://www.nec.com/en/global/prod/hpc/aurora/document/VE-tls_v1.1.pdf
1316e8d8bef9SDimitry Andric   return lowerToTLSGeneralDynamicModel(Op, DAG);
13175ffd83dbSDimitry Andric }
13185ffd83dbSDimitry Andric 
lowerJumpTable(SDValue Op,SelectionDAG & DAG) const1319e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerJumpTable(SDValue Op, SelectionDAG &DAG) const {
1320e8d8bef9SDimitry Andric   return makeAddress(Op, DAG);
1321e8d8bef9SDimitry Andric }
1322e8d8bef9SDimitry Andric 
1323e8d8bef9SDimitry Andric // Lower a f128 load into two f64 loads.
lowerLoadF128(SDValue Op,SelectionDAG & DAG)1324e8d8bef9SDimitry Andric static SDValue lowerLoadF128(SDValue Op, SelectionDAG &DAG) {
1325e8d8bef9SDimitry Andric   SDLoc DL(Op);
1326e8d8bef9SDimitry Andric   LoadSDNode *LdNode = dyn_cast<LoadSDNode>(Op.getNode());
1327e8d8bef9SDimitry Andric   assert(LdNode && LdNode->getOffset().isUndef() && "Unexpected node type");
1328bdd1243dSDimitry Andric   Align Alignment = LdNode->getAlign();
1329e8d8bef9SDimitry Andric   if (Alignment > 8)
1330bdd1243dSDimitry Andric     Alignment = Align(8);
1331e8d8bef9SDimitry Andric 
1332e8d8bef9SDimitry Andric   SDValue Lo64 =
1333e8d8bef9SDimitry Andric       DAG.getLoad(MVT::f64, DL, LdNode->getChain(), LdNode->getBasePtr(),
1334e8d8bef9SDimitry Andric                   LdNode->getPointerInfo(), Alignment,
1335e8d8bef9SDimitry Andric                   LdNode->isVolatile() ? MachineMemOperand::MOVolatile
1336e8d8bef9SDimitry Andric                                        : MachineMemOperand::MONone);
1337e8d8bef9SDimitry Andric   EVT AddrVT = LdNode->getBasePtr().getValueType();
1338e8d8bef9SDimitry Andric   SDValue HiPtr = DAG.getNode(ISD::ADD, DL, AddrVT, LdNode->getBasePtr(),
1339e8d8bef9SDimitry Andric                               DAG.getConstant(8, DL, AddrVT));
1340e8d8bef9SDimitry Andric   SDValue Hi64 =
1341e8d8bef9SDimitry Andric       DAG.getLoad(MVT::f64, DL, LdNode->getChain(), HiPtr,
1342e8d8bef9SDimitry Andric                   LdNode->getPointerInfo(), Alignment,
1343e8d8bef9SDimitry Andric                   LdNode->isVolatile() ? MachineMemOperand::MOVolatile
1344e8d8bef9SDimitry Andric                                        : MachineMemOperand::MONone);
1345e8d8bef9SDimitry Andric 
1346e8d8bef9SDimitry Andric   SDValue SubRegEven = DAG.getTargetConstant(VE::sub_even, DL, MVT::i32);
1347e8d8bef9SDimitry Andric   SDValue SubRegOdd = DAG.getTargetConstant(VE::sub_odd, DL, MVT::i32);
1348e8d8bef9SDimitry Andric 
1349e8d8bef9SDimitry Andric   // VE stores Hi64 to 8(addr) and Lo64 to 0(addr)
1350e8d8bef9SDimitry Andric   SDNode *InFP128 =
1351e8d8bef9SDimitry Andric       DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MVT::f128);
1352e8d8bef9SDimitry Andric   InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, DL, MVT::f128,
1353e8d8bef9SDimitry Andric                                SDValue(InFP128, 0), Hi64, SubRegEven);
1354e8d8bef9SDimitry Andric   InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, DL, MVT::f128,
1355e8d8bef9SDimitry Andric                                SDValue(InFP128, 0), Lo64, SubRegOdd);
1356e8d8bef9SDimitry Andric   SDValue OutChains[2] = {SDValue(Lo64.getNode(), 1),
1357e8d8bef9SDimitry Andric                           SDValue(Hi64.getNode(), 1)};
1358e8d8bef9SDimitry Andric   SDValue OutChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
1359e8d8bef9SDimitry Andric   SDValue Ops[2] = {SDValue(InFP128, 0), OutChain};
1360e8d8bef9SDimitry Andric   return DAG.getMergeValues(Ops, DL);
1361e8d8bef9SDimitry Andric }
1362e8d8bef9SDimitry Andric 
136381ad6265SDimitry Andric // Lower a vXi1 load into following instructions
136481ad6265SDimitry Andric //   LDrii %1, (,%addr)
136581ad6265SDimitry Andric //   LVMxir  %vm, 0, %1
136681ad6265SDimitry Andric //   LDrii %2, 8(,%addr)
136781ad6265SDimitry Andric //   LVMxir  %vm, 0, %2
136881ad6265SDimitry Andric //   ...
lowerLoadI1(SDValue Op,SelectionDAG & DAG)136981ad6265SDimitry Andric static SDValue lowerLoadI1(SDValue Op, SelectionDAG &DAG) {
137081ad6265SDimitry Andric   SDLoc DL(Op);
137181ad6265SDimitry Andric   LoadSDNode *LdNode = dyn_cast<LoadSDNode>(Op.getNode());
137281ad6265SDimitry Andric   assert(LdNode && LdNode->getOffset().isUndef() && "Unexpected node type");
137381ad6265SDimitry Andric 
137481ad6265SDimitry Andric   SDValue BasePtr = LdNode->getBasePtr();
1375bdd1243dSDimitry Andric   Align Alignment = LdNode->getAlign();
137681ad6265SDimitry Andric   if (Alignment > 8)
1377bdd1243dSDimitry Andric     Alignment = Align(8);
137881ad6265SDimitry Andric 
137981ad6265SDimitry Andric   EVT AddrVT = BasePtr.getValueType();
138081ad6265SDimitry Andric   EVT MemVT = LdNode->getMemoryVT();
138181ad6265SDimitry Andric   if (MemVT == MVT::v256i1 || MemVT == MVT::v4i64) {
138281ad6265SDimitry Andric     SDValue OutChains[4];
138381ad6265SDimitry Andric     SDNode *VM = DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MemVT);
138481ad6265SDimitry Andric     for (int i = 0; i < 4; ++i) {
138581ad6265SDimitry Andric       // Generate load dag and prepare chains.
138681ad6265SDimitry Andric       SDValue Addr = DAG.getNode(ISD::ADD, DL, AddrVT, BasePtr,
138781ad6265SDimitry Andric                                  DAG.getConstant(8 * i, DL, AddrVT));
138881ad6265SDimitry Andric       SDValue Val =
138981ad6265SDimitry Andric           DAG.getLoad(MVT::i64, DL, LdNode->getChain(), Addr,
139081ad6265SDimitry Andric                       LdNode->getPointerInfo(), Alignment,
139181ad6265SDimitry Andric                       LdNode->isVolatile() ? MachineMemOperand::MOVolatile
139281ad6265SDimitry Andric                                            : MachineMemOperand::MONone);
139381ad6265SDimitry Andric       OutChains[i] = SDValue(Val.getNode(), 1);
139481ad6265SDimitry Andric 
139581ad6265SDimitry Andric       VM = DAG.getMachineNode(VE::LVMir_m, DL, MVT::i64,
139681ad6265SDimitry Andric                               DAG.getTargetConstant(i, DL, MVT::i64), Val,
139781ad6265SDimitry Andric                               SDValue(VM, 0));
139881ad6265SDimitry Andric     }
139981ad6265SDimitry Andric     SDValue OutChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
140081ad6265SDimitry Andric     SDValue Ops[2] = {SDValue(VM, 0), OutChain};
140181ad6265SDimitry Andric     return DAG.getMergeValues(Ops, DL);
140281ad6265SDimitry Andric   } else if (MemVT == MVT::v512i1 || MemVT == MVT::v8i64) {
140381ad6265SDimitry Andric     SDValue OutChains[8];
140481ad6265SDimitry Andric     SDNode *VM = DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MemVT);
140581ad6265SDimitry Andric     for (int i = 0; i < 8; ++i) {
140681ad6265SDimitry Andric       // Generate load dag and prepare chains.
140781ad6265SDimitry Andric       SDValue Addr = DAG.getNode(ISD::ADD, DL, AddrVT, BasePtr,
140881ad6265SDimitry Andric                                  DAG.getConstant(8 * i, DL, AddrVT));
140981ad6265SDimitry Andric       SDValue Val =
141081ad6265SDimitry Andric           DAG.getLoad(MVT::i64, DL, LdNode->getChain(), Addr,
141181ad6265SDimitry Andric                       LdNode->getPointerInfo(), Alignment,
141281ad6265SDimitry Andric                       LdNode->isVolatile() ? MachineMemOperand::MOVolatile
141381ad6265SDimitry Andric                                            : MachineMemOperand::MONone);
141481ad6265SDimitry Andric       OutChains[i] = SDValue(Val.getNode(), 1);
141581ad6265SDimitry Andric 
141681ad6265SDimitry Andric       VM = DAG.getMachineNode(VE::LVMyir_y, DL, MVT::i64,
141781ad6265SDimitry Andric                               DAG.getTargetConstant(i, DL, MVT::i64), Val,
141881ad6265SDimitry Andric                               SDValue(VM, 0));
141981ad6265SDimitry Andric     }
142081ad6265SDimitry Andric     SDValue OutChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
142181ad6265SDimitry Andric     SDValue Ops[2] = {SDValue(VM, 0), OutChain};
142281ad6265SDimitry Andric     return DAG.getMergeValues(Ops, DL);
142381ad6265SDimitry Andric   } else {
142481ad6265SDimitry Andric     // Otherwise, ask llvm to expand it.
142581ad6265SDimitry Andric     return SDValue();
142681ad6265SDimitry Andric   }
142781ad6265SDimitry Andric }
142881ad6265SDimitry Andric 
lowerLOAD(SDValue Op,SelectionDAG & DAG) const1429e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const {
1430e8d8bef9SDimitry Andric   LoadSDNode *LdNode = cast<LoadSDNode>(Op.getNode());
143181ad6265SDimitry Andric   EVT MemVT = LdNode->getMemoryVT();
143281ad6265SDimitry Andric 
14335f757f3fSDimitry Andric   // If VPU is enabled, always expand non-mask vector loads to VVP
14345f757f3fSDimitry Andric   if (Subtarget->enableVPU() && MemVT.isVector() && !isMaskType(MemVT))
143581ad6265SDimitry Andric     return lowerToVVP(Op, DAG);
143681ad6265SDimitry Andric 
1437e8d8bef9SDimitry Andric   SDValue BasePtr = LdNode->getBasePtr();
1438e8d8bef9SDimitry Andric   if (isa<FrameIndexSDNode>(BasePtr.getNode())) {
1439e8d8bef9SDimitry Andric     // Do not expand store instruction with frame index here because of
1440e8d8bef9SDimitry Andric     // dependency problems.  We expand it later in eliminateFrameIndex().
1441e8d8bef9SDimitry Andric     return Op;
1442e8d8bef9SDimitry Andric   }
1443e8d8bef9SDimitry Andric 
1444e8d8bef9SDimitry Andric   if (MemVT == MVT::f128)
1445e8d8bef9SDimitry Andric     return lowerLoadF128(Op, DAG);
144681ad6265SDimitry Andric   if (isMaskType(MemVT))
144781ad6265SDimitry Andric     return lowerLoadI1(Op, DAG);
1448e8d8bef9SDimitry Andric 
1449e8d8bef9SDimitry Andric   return Op;
1450e8d8bef9SDimitry Andric }
1451e8d8bef9SDimitry Andric 
1452e8d8bef9SDimitry Andric // Lower a f128 store into two f64 stores.
lowerStoreF128(SDValue Op,SelectionDAG & DAG)1453e8d8bef9SDimitry Andric static SDValue lowerStoreF128(SDValue Op, SelectionDAG &DAG) {
1454e8d8bef9SDimitry Andric   SDLoc DL(Op);
1455e8d8bef9SDimitry Andric   StoreSDNode *StNode = dyn_cast<StoreSDNode>(Op.getNode());
1456e8d8bef9SDimitry Andric   assert(StNode && StNode->getOffset().isUndef() && "Unexpected node type");
1457e8d8bef9SDimitry Andric 
1458e8d8bef9SDimitry Andric   SDValue SubRegEven = DAG.getTargetConstant(VE::sub_even, DL, MVT::i32);
1459e8d8bef9SDimitry Andric   SDValue SubRegOdd = DAG.getTargetConstant(VE::sub_odd, DL, MVT::i32);
1460e8d8bef9SDimitry Andric 
1461e8d8bef9SDimitry Andric   SDNode *Hi64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, MVT::i64,
1462e8d8bef9SDimitry Andric                                     StNode->getValue(), SubRegEven);
1463e8d8bef9SDimitry Andric   SDNode *Lo64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, MVT::i64,
1464e8d8bef9SDimitry Andric                                     StNode->getValue(), SubRegOdd);
1465e8d8bef9SDimitry Andric 
1466bdd1243dSDimitry Andric   Align Alignment = StNode->getAlign();
1467e8d8bef9SDimitry Andric   if (Alignment > 8)
1468bdd1243dSDimitry Andric     Alignment = Align(8);
1469e8d8bef9SDimitry Andric 
1470e8d8bef9SDimitry Andric   // VE stores Hi64 to 8(addr) and Lo64 to 0(addr)
1471e8d8bef9SDimitry Andric   SDValue OutChains[2];
1472e8d8bef9SDimitry Andric   OutChains[0] =
1473e8d8bef9SDimitry Andric       DAG.getStore(StNode->getChain(), DL, SDValue(Lo64, 0),
1474e8d8bef9SDimitry Andric                    StNode->getBasePtr(), MachinePointerInfo(), Alignment,
1475e8d8bef9SDimitry Andric                    StNode->isVolatile() ? MachineMemOperand::MOVolatile
1476e8d8bef9SDimitry Andric                                         : MachineMemOperand::MONone);
1477e8d8bef9SDimitry Andric   EVT AddrVT = StNode->getBasePtr().getValueType();
1478e8d8bef9SDimitry Andric   SDValue HiPtr = DAG.getNode(ISD::ADD, DL, AddrVT, StNode->getBasePtr(),
1479e8d8bef9SDimitry Andric                               DAG.getConstant(8, DL, AddrVT));
1480e8d8bef9SDimitry Andric   OutChains[1] =
1481e8d8bef9SDimitry Andric       DAG.getStore(StNode->getChain(), DL, SDValue(Hi64, 0), HiPtr,
1482e8d8bef9SDimitry Andric                    MachinePointerInfo(), Alignment,
1483e8d8bef9SDimitry Andric                    StNode->isVolatile() ? MachineMemOperand::MOVolatile
1484e8d8bef9SDimitry Andric                                         : MachineMemOperand::MONone);
1485e8d8bef9SDimitry Andric   return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
1486e8d8bef9SDimitry Andric }
1487e8d8bef9SDimitry Andric 
148881ad6265SDimitry Andric // Lower a vXi1 store into following instructions
148981ad6265SDimitry Andric //   SVMi  %1, %vm, 0
149081ad6265SDimitry Andric //   STrii %1, (,%addr)
149181ad6265SDimitry Andric //   SVMi  %2, %vm, 1
149281ad6265SDimitry Andric //   STrii %2, 8(,%addr)
149381ad6265SDimitry Andric //   ...
lowerStoreI1(SDValue Op,SelectionDAG & DAG)149481ad6265SDimitry Andric static SDValue lowerStoreI1(SDValue Op, SelectionDAG &DAG) {
149581ad6265SDimitry Andric   SDLoc DL(Op);
149681ad6265SDimitry Andric   StoreSDNode *StNode = dyn_cast<StoreSDNode>(Op.getNode());
149781ad6265SDimitry Andric   assert(StNode && StNode->getOffset().isUndef() && "Unexpected node type");
149881ad6265SDimitry Andric 
149981ad6265SDimitry Andric   SDValue BasePtr = StNode->getBasePtr();
1500bdd1243dSDimitry Andric   Align Alignment = StNode->getAlign();
150181ad6265SDimitry Andric   if (Alignment > 8)
1502bdd1243dSDimitry Andric     Alignment = Align(8);
150381ad6265SDimitry Andric   EVT AddrVT = BasePtr.getValueType();
150481ad6265SDimitry Andric   EVT MemVT = StNode->getMemoryVT();
150581ad6265SDimitry Andric   if (MemVT == MVT::v256i1 || MemVT == MVT::v4i64) {
150681ad6265SDimitry Andric     SDValue OutChains[4];
150781ad6265SDimitry Andric     for (int i = 0; i < 4; ++i) {
150881ad6265SDimitry Andric       SDNode *V =
150981ad6265SDimitry Andric           DAG.getMachineNode(VE::SVMmi, DL, MVT::i64, StNode->getValue(),
151081ad6265SDimitry Andric                              DAG.getTargetConstant(i, DL, MVT::i64));
151181ad6265SDimitry Andric       SDValue Addr = DAG.getNode(ISD::ADD, DL, AddrVT, BasePtr,
151281ad6265SDimitry Andric                                  DAG.getConstant(8 * i, DL, AddrVT));
151381ad6265SDimitry Andric       OutChains[i] =
151481ad6265SDimitry Andric           DAG.getStore(StNode->getChain(), DL, SDValue(V, 0), Addr,
151581ad6265SDimitry Andric                        MachinePointerInfo(), Alignment,
151681ad6265SDimitry Andric                        StNode->isVolatile() ? MachineMemOperand::MOVolatile
151781ad6265SDimitry Andric                                             : MachineMemOperand::MONone);
151881ad6265SDimitry Andric     }
151981ad6265SDimitry Andric     return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
152081ad6265SDimitry Andric   } else if (MemVT == MVT::v512i1 || MemVT == MVT::v8i64) {
152181ad6265SDimitry Andric     SDValue OutChains[8];
152281ad6265SDimitry Andric     for (int i = 0; i < 8; ++i) {
152381ad6265SDimitry Andric       SDNode *V =
152481ad6265SDimitry Andric           DAG.getMachineNode(VE::SVMyi, DL, MVT::i64, StNode->getValue(),
152581ad6265SDimitry Andric                              DAG.getTargetConstant(i, DL, MVT::i64));
152681ad6265SDimitry Andric       SDValue Addr = DAG.getNode(ISD::ADD, DL, AddrVT, BasePtr,
152781ad6265SDimitry Andric                                  DAG.getConstant(8 * i, DL, AddrVT));
152881ad6265SDimitry Andric       OutChains[i] =
152981ad6265SDimitry Andric           DAG.getStore(StNode->getChain(), DL, SDValue(V, 0), Addr,
153081ad6265SDimitry Andric                        MachinePointerInfo(), Alignment,
153181ad6265SDimitry Andric                        StNode->isVolatile() ? MachineMemOperand::MOVolatile
153281ad6265SDimitry Andric                                             : MachineMemOperand::MONone);
153381ad6265SDimitry Andric     }
153481ad6265SDimitry Andric     return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
153581ad6265SDimitry Andric   } else {
153681ad6265SDimitry Andric     // Otherwise, ask llvm to expand it.
153781ad6265SDimitry Andric     return SDValue();
153881ad6265SDimitry Andric   }
153981ad6265SDimitry Andric }
154081ad6265SDimitry Andric 
lowerSTORE(SDValue Op,SelectionDAG & DAG) const1541e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const {
1542e8d8bef9SDimitry Andric   StoreSDNode *StNode = cast<StoreSDNode>(Op.getNode());
1543e8d8bef9SDimitry Andric   assert(StNode && StNode->getOffset().isUndef() && "Unexpected node type");
154481ad6265SDimitry Andric   EVT MemVT = StNode->getMemoryVT();
15455f757f3fSDimitry Andric 
15465f757f3fSDimitry Andric   // If VPU is enabled, always expand non-mask vector stores to VVP
15475f757f3fSDimitry Andric   if (Subtarget->enableVPU() && MemVT.isVector() && !isMaskType(MemVT))
154881ad6265SDimitry Andric     return lowerToVVP(Op, DAG);
154981ad6265SDimitry Andric 
1550e8d8bef9SDimitry Andric   SDValue BasePtr = StNode->getBasePtr();
1551e8d8bef9SDimitry Andric   if (isa<FrameIndexSDNode>(BasePtr.getNode())) {
1552e8d8bef9SDimitry Andric     // Do not expand store instruction with frame index here because of
1553e8d8bef9SDimitry Andric     // dependency problems.  We expand it later in eliminateFrameIndex().
1554e8d8bef9SDimitry Andric     return Op;
1555e8d8bef9SDimitry Andric   }
1556e8d8bef9SDimitry Andric 
1557e8d8bef9SDimitry Andric   if (MemVT == MVT::f128)
1558e8d8bef9SDimitry Andric     return lowerStoreF128(Op, DAG);
155981ad6265SDimitry Andric   if (isMaskType(MemVT))
156081ad6265SDimitry Andric     return lowerStoreI1(Op, DAG);
1561e8d8bef9SDimitry Andric 
1562e8d8bef9SDimitry Andric   // Otherwise, ask llvm to expand it.
1563e8d8bef9SDimitry Andric   return SDValue();
1564e8d8bef9SDimitry Andric }
1565e8d8bef9SDimitry Andric 
lowerVASTART(SDValue Op,SelectionDAG & DAG) const1566e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const {
15675ffd83dbSDimitry Andric   MachineFunction &MF = DAG.getMachineFunction();
15685ffd83dbSDimitry Andric   VEMachineFunctionInfo *FuncInfo = MF.getInfo<VEMachineFunctionInfo>();
15695ffd83dbSDimitry Andric   auto PtrVT = getPointerTy(DAG.getDataLayout());
15705ffd83dbSDimitry Andric 
15715ffd83dbSDimitry Andric   // Need frame address to find the address of VarArgsFrameIndex.
15725ffd83dbSDimitry Andric   MF.getFrameInfo().setFrameAddressIsTaken(true);
15735ffd83dbSDimitry Andric 
15745ffd83dbSDimitry Andric   // vastart just stores the address of the VarArgsFrameIndex slot into the
15755ffd83dbSDimitry Andric   // memory location argument.
15765ffd83dbSDimitry Andric   SDLoc DL(Op);
15775ffd83dbSDimitry Andric   SDValue Offset =
15785ffd83dbSDimitry Andric       DAG.getNode(ISD::ADD, DL, PtrVT, DAG.getRegister(VE::SX9, PtrVT),
15795ffd83dbSDimitry Andric                   DAG.getIntPtrConstant(FuncInfo->getVarArgsFrameOffset(), DL));
15805ffd83dbSDimitry Andric   const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
15815ffd83dbSDimitry Andric   return DAG.getStore(Op.getOperand(0), DL, Offset, Op.getOperand(1),
15825ffd83dbSDimitry Andric                       MachinePointerInfo(SV));
15835ffd83dbSDimitry Andric }
15845ffd83dbSDimitry Andric 
lowerVAARG(SDValue Op,SelectionDAG & DAG) const1585e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const {
15865ffd83dbSDimitry Andric   SDNode *Node = Op.getNode();
15875ffd83dbSDimitry Andric   EVT VT = Node->getValueType(0);
15885ffd83dbSDimitry Andric   SDValue InChain = Node->getOperand(0);
15895ffd83dbSDimitry Andric   SDValue VAListPtr = Node->getOperand(1);
15905ffd83dbSDimitry Andric   EVT PtrVT = VAListPtr.getValueType();
15915ffd83dbSDimitry Andric   const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
15925ffd83dbSDimitry Andric   SDLoc DL(Node);
15935ffd83dbSDimitry Andric   SDValue VAList =
15945ffd83dbSDimitry Andric       DAG.getLoad(PtrVT, DL, InChain, VAListPtr, MachinePointerInfo(SV));
15955ffd83dbSDimitry Andric   SDValue Chain = VAList.getValue(1);
15965ffd83dbSDimitry Andric   SDValue NextPtr;
15975ffd83dbSDimitry Andric 
1598e8d8bef9SDimitry Andric   if (VT == MVT::f128) {
159981ad6265SDimitry Andric     // VE f128 values must be stored with 16 bytes alignment.  We don't
1600e8d8bef9SDimitry Andric     // know the actual alignment of VAList, so we take alignment of it
160181ad6265SDimitry Andric     // dynamically.
1602e8d8bef9SDimitry Andric     int Align = 16;
1603e8d8bef9SDimitry Andric     VAList = DAG.getNode(ISD::ADD, DL, PtrVT, VAList,
1604e8d8bef9SDimitry Andric                          DAG.getConstant(Align - 1, DL, PtrVT));
1605e8d8bef9SDimitry Andric     VAList = DAG.getNode(ISD::AND, DL, PtrVT, VAList,
1606e8d8bef9SDimitry Andric                          DAG.getConstant(-Align, DL, PtrVT));
1607e8d8bef9SDimitry Andric     // Increment the pointer, VAList, by 16 to the next vaarg.
1608e8d8bef9SDimitry Andric     NextPtr =
1609e8d8bef9SDimitry Andric         DAG.getNode(ISD::ADD, DL, PtrVT, VAList, DAG.getIntPtrConstant(16, DL));
1610e8d8bef9SDimitry Andric   } else if (VT == MVT::f32) {
16115ffd83dbSDimitry Andric     // float --> need special handling like below.
16125ffd83dbSDimitry Andric     //    0      4
16135ffd83dbSDimitry Andric     //    +------+------+
16145ffd83dbSDimitry Andric     //    | empty| float|
16155ffd83dbSDimitry Andric     //    +------+------+
16165ffd83dbSDimitry Andric     // Increment the pointer, VAList, by 8 to the next vaarg.
16175ffd83dbSDimitry Andric     NextPtr =
16185ffd83dbSDimitry Andric         DAG.getNode(ISD::ADD, DL, PtrVT, VAList, DAG.getIntPtrConstant(8, DL));
16195ffd83dbSDimitry Andric     // Then, adjust VAList.
16205ffd83dbSDimitry Andric     unsigned InternalOffset = 4;
16215ffd83dbSDimitry Andric     VAList = DAG.getNode(ISD::ADD, DL, PtrVT, VAList,
16225ffd83dbSDimitry Andric                          DAG.getConstant(InternalOffset, DL, PtrVT));
16235ffd83dbSDimitry Andric   } else {
16245ffd83dbSDimitry Andric     // Increment the pointer, VAList, by 8 to the next vaarg.
16255ffd83dbSDimitry Andric     NextPtr =
16265ffd83dbSDimitry Andric         DAG.getNode(ISD::ADD, DL, PtrVT, VAList, DAG.getIntPtrConstant(8, DL));
16275ffd83dbSDimitry Andric   }
16285ffd83dbSDimitry Andric 
16295ffd83dbSDimitry Andric   // Store the incremented VAList to the legalized pointer.
16305ffd83dbSDimitry Andric   InChain = DAG.getStore(Chain, DL, NextPtr, VAListPtr, MachinePointerInfo(SV));
16315ffd83dbSDimitry Andric 
16325ffd83dbSDimitry Andric   // Load the actual argument out of the pointer VAList.
16335ffd83dbSDimitry Andric   // We can't count on greater alignment than the word size.
1634bdd1243dSDimitry Andric   return DAG.getLoad(
1635bdd1243dSDimitry Andric       VT, DL, InChain, VAList, MachinePointerInfo(),
1636bdd1243dSDimitry Andric       Align(std::min(PtrVT.getSizeInBits(), VT.getSizeInBits()) / 8));
16375ffd83dbSDimitry Andric }
16385ffd83dbSDimitry Andric 
lowerDYNAMIC_STACKALLOC(SDValue Op,SelectionDAG & DAG) const16395ffd83dbSDimitry Andric SDValue VETargetLowering::lowerDYNAMIC_STACKALLOC(SDValue Op,
16405ffd83dbSDimitry Andric                                                   SelectionDAG &DAG) const {
16415ffd83dbSDimitry Andric   // Generate following code.
16425ffd83dbSDimitry Andric   //   (void)__llvm_grow_stack(size);
16435ffd83dbSDimitry Andric   //   ret = GETSTACKTOP;        // pseudo instruction
16445ffd83dbSDimitry Andric   SDLoc DL(Op);
16455ffd83dbSDimitry Andric 
16465ffd83dbSDimitry Andric   // Get the inputs.
16475ffd83dbSDimitry Andric   SDNode *Node = Op.getNode();
16485ffd83dbSDimitry Andric   SDValue Chain = Op.getOperand(0);
16495ffd83dbSDimitry Andric   SDValue Size = Op.getOperand(1);
16505ffd83dbSDimitry Andric   MaybeAlign Alignment(Op.getConstantOperandVal(2));
16515ffd83dbSDimitry Andric   EVT VT = Node->getValueType(0);
16525ffd83dbSDimitry Andric 
16535ffd83dbSDimitry Andric   // Chain the dynamic stack allocation so that it doesn't modify the stack
16545ffd83dbSDimitry Andric   // pointer when other instructions are using the stack.
16555ffd83dbSDimitry Andric   Chain = DAG.getCALLSEQ_START(Chain, 0, 0, DL);
16565ffd83dbSDimitry Andric 
16575ffd83dbSDimitry Andric   const TargetFrameLowering &TFI = *Subtarget->getFrameLowering();
16585ffd83dbSDimitry Andric   Align StackAlign = TFI.getStackAlign();
16595ffd83dbSDimitry Andric   bool NeedsAlign = Alignment.valueOrOne() > StackAlign;
16605ffd83dbSDimitry Andric 
16615ffd83dbSDimitry Andric   // Prepare arguments
16625ffd83dbSDimitry Andric   TargetLowering::ArgListTy Args;
16635ffd83dbSDimitry Andric   TargetLowering::ArgListEntry Entry;
16645ffd83dbSDimitry Andric   Entry.Node = Size;
16655ffd83dbSDimitry Andric   Entry.Ty = Entry.Node.getValueType().getTypeForEVT(*DAG.getContext());
16665ffd83dbSDimitry Andric   Args.push_back(Entry);
16675ffd83dbSDimitry Andric   if (NeedsAlign) {
16685ffd83dbSDimitry Andric     Entry.Node = DAG.getConstant(~(Alignment->value() - 1ULL), DL, VT);
16695ffd83dbSDimitry Andric     Entry.Ty = Entry.Node.getValueType().getTypeForEVT(*DAG.getContext());
16705ffd83dbSDimitry Andric     Args.push_back(Entry);
16715ffd83dbSDimitry Andric   }
16725ffd83dbSDimitry Andric   Type *RetTy = Type::getVoidTy(*DAG.getContext());
16735ffd83dbSDimitry Andric 
16745ffd83dbSDimitry Andric   EVT PtrVT = Op.getValueType();
16755ffd83dbSDimitry Andric   SDValue Callee;
16765ffd83dbSDimitry Andric   if (NeedsAlign) {
16775ffd83dbSDimitry Andric     Callee = DAG.getTargetExternalSymbol("__ve_grow_stack_align", PtrVT, 0);
16785ffd83dbSDimitry Andric   } else {
16795ffd83dbSDimitry Andric     Callee = DAG.getTargetExternalSymbol("__ve_grow_stack", PtrVT, 0);
16805ffd83dbSDimitry Andric   }
16815ffd83dbSDimitry Andric 
16825ffd83dbSDimitry Andric   TargetLowering::CallLoweringInfo CLI(DAG);
16835ffd83dbSDimitry Andric   CLI.setDebugLoc(DL)
16845ffd83dbSDimitry Andric       .setChain(Chain)
16855ffd83dbSDimitry Andric       .setCallee(CallingConv::PreserveAll, RetTy, Callee, std::move(Args))
16865ffd83dbSDimitry Andric       .setDiscardResult(true);
16875ffd83dbSDimitry Andric   std::pair<SDValue, SDValue> pair = LowerCallTo(CLI);
16885ffd83dbSDimitry Andric   Chain = pair.second;
16895ffd83dbSDimitry Andric   SDValue Result = DAG.getNode(VEISD::GETSTACKTOP, DL, VT, Chain);
16905ffd83dbSDimitry Andric   if (NeedsAlign) {
16915ffd83dbSDimitry Andric     Result = DAG.getNode(ISD::ADD, DL, VT, Result,
16925ffd83dbSDimitry Andric                          DAG.getConstant((Alignment->value() - 1ULL), DL, VT));
16935ffd83dbSDimitry Andric     Result = DAG.getNode(ISD::AND, DL, VT, Result,
16945ffd83dbSDimitry Andric                          DAG.getConstant(~(Alignment->value() - 1ULL), DL, VT));
16955ffd83dbSDimitry Andric   }
16965ffd83dbSDimitry Andric   //  Chain = Result.getValue(1);
1697bdd1243dSDimitry Andric   Chain = DAG.getCALLSEQ_END(Chain, 0, 0, SDValue(), DL);
16985ffd83dbSDimitry Andric 
16995ffd83dbSDimitry Andric   SDValue Ops[2] = {Result, Chain};
17005ffd83dbSDimitry Andric   return DAG.getMergeValues(Ops, DL);
17015ffd83dbSDimitry Andric }
17025ffd83dbSDimitry Andric 
lowerEH_SJLJ_LONGJMP(SDValue Op,SelectionDAG & DAG) const1703e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerEH_SJLJ_LONGJMP(SDValue Op,
1704e8d8bef9SDimitry Andric                                                SelectionDAG &DAG) const {
1705e8d8bef9SDimitry Andric   SDLoc DL(Op);
1706e8d8bef9SDimitry Andric   return DAG.getNode(VEISD::EH_SJLJ_LONGJMP, DL, MVT::Other, Op.getOperand(0),
1707e8d8bef9SDimitry Andric                      Op.getOperand(1));
1708e8d8bef9SDimitry Andric }
1709e8d8bef9SDimitry Andric 
lowerEH_SJLJ_SETJMP(SDValue Op,SelectionDAG & DAG) const1710e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerEH_SJLJ_SETJMP(SDValue Op,
1711e8d8bef9SDimitry Andric                                               SelectionDAG &DAG) const {
1712e8d8bef9SDimitry Andric   SDLoc DL(Op);
1713e8d8bef9SDimitry Andric   return DAG.getNode(VEISD::EH_SJLJ_SETJMP, DL,
1714e8d8bef9SDimitry Andric                      DAG.getVTList(MVT::i32, MVT::Other), Op.getOperand(0),
1715e8d8bef9SDimitry Andric                      Op.getOperand(1));
1716e8d8bef9SDimitry Andric }
1717e8d8bef9SDimitry Andric 
lowerEH_SJLJ_SETUP_DISPATCH(SDValue Op,SelectionDAG & DAG) const1718e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerEH_SJLJ_SETUP_DISPATCH(SDValue Op,
1719e8d8bef9SDimitry Andric                                                       SelectionDAG &DAG) const {
1720e8d8bef9SDimitry Andric   SDLoc DL(Op);
1721e8d8bef9SDimitry Andric   return DAG.getNode(VEISD::EH_SJLJ_SETUP_DISPATCH, DL, MVT::Other,
1722e8d8bef9SDimitry Andric                      Op.getOperand(0));
1723e8d8bef9SDimitry Andric }
1724e8d8bef9SDimitry Andric 
lowerFRAMEADDR(SDValue Op,SelectionDAG & DAG,const VETargetLowering & TLI,const VESubtarget * Subtarget)1725e8d8bef9SDimitry Andric static SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG,
1726e8d8bef9SDimitry Andric                               const VETargetLowering &TLI,
1727e8d8bef9SDimitry Andric                               const VESubtarget *Subtarget) {
1728e8d8bef9SDimitry Andric   SDLoc DL(Op);
1729e8d8bef9SDimitry Andric   MachineFunction &MF = DAG.getMachineFunction();
1730e8d8bef9SDimitry Andric   EVT PtrVT = TLI.getPointerTy(MF.getDataLayout());
1731e8d8bef9SDimitry Andric 
1732e8d8bef9SDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
1733e8d8bef9SDimitry Andric   MFI.setFrameAddressIsTaken(true);
1734e8d8bef9SDimitry Andric 
1735e8d8bef9SDimitry Andric   unsigned Depth = Op.getConstantOperandVal(0);
1736e8d8bef9SDimitry Andric   const VERegisterInfo *RegInfo = Subtarget->getRegisterInfo();
173704eeddc0SDimitry Andric   Register FrameReg = RegInfo->getFrameRegister(MF);
1738e8d8bef9SDimitry Andric   SDValue FrameAddr =
1739e8d8bef9SDimitry Andric       DAG.getCopyFromReg(DAG.getEntryNode(), DL, FrameReg, PtrVT);
1740e8d8bef9SDimitry Andric   while (Depth--)
1741e8d8bef9SDimitry Andric     FrameAddr = DAG.getLoad(Op.getValueType(), DL, DAG.getEntryNode(),
1742e8d8bef9SDimitry Andric                             FrameAddr, MachinePointerInfo());
1743e8d8bef9SDimitry Andric   return FrameAddr;
1744e8d8bef9SDimitry Andric }
1745e8d8bef9SDimitry Andric 
lowerRETURNADDR(SDValue Op,SelectionDAG & DAG,const VETargetLowering & TLI,const VESubtarget * Subtarget)1746e8d8bef9SDimitry Andric static SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG,
1747e8d8bef9SDimitry Andric                                const VETargetLowering &TLI,
1748e8d8bef9SDimitry Andric                                const VESubtarget *Subtarget) {
1749e8d8bef9SDimitry Andric   MachineFunction &MF = DAG.getMachineFunction();
1750e8d8bef9SDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
1751e8d8bef9SDimitry Andric   MFI.setReturnAddressIsTaken(true);
1752e8d8bef9SDimitry Andric 
1753e8d8bef9SDimitry Andric   if (TLI.verifyReturnAddressArgumentIsConstant(Op, DAG))
1754e8d8bef9SDimitry Andric     return SDValue();
1755e8d8bef9SDimitry Andric 
1756e8d8bef9SDimitry Andric   SDValue FrameAddr = lowerFRAMEADDR(Op, DAG, TLI, Subtarget);
1757e8d8bef9SDimitry Andric 
1758e8d8bef9SDimitry Andric   SDLoc DL(Op);
1759e8d8bef9SDimitry Andric   EVT VT = Op.getValueType();
1760e8d8bef9SDimitry Andric   SDValue Offset = DAG.getConstant(8, DL, VT);
1761e8d8bef9SDimitry Andric   return DAG.getLoad(VT, DL, DAG.getEntryNode(),
1762e8d8bef9SDimitry Andric                      DAG.getNode(ISD::ADD, DL, VT, FrameAddr, Offset),
1763e8d8bef9SDimitry Andric                      MachinePointerInfo());
1764e8d8bef9SDimitry Andric }
1765e8d8bef9SDimitry Andric 
lowerINTRINSIC_WO_CHAIN(SDValue Op,SelectionDAG & DAG) const1766e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
1767e8d8bef9SDimitry Andric                                                   SelectionDAG &DAG) const {
1768e8d8bef9SDimitry Andric   SDLoc DL(Op);
1769*647cbc5dSDimitry Andric   unsigned IntNo = Op.getConstantOperandVal(0);
1770e8d8bef9SDimitry Andric   switch (IntNo) {
1771e8d8bef9SDimitry Andric   default: // Don't custom lower most intrinsics.
1772e8d8bef9SDimitry Andric     return SDValue();
1773e8d8bef9SDimitry Andric   case Intrinsic::eh_sjlj_lsda: {
1774e8d8bef9SDimitry Andric     MachineFunction &MF = DAG.getMachineFunction();
1775e8d8bef9SDimitry Andric     MVT VT = Op.getSimpleValueType();
1776e8d8bef9SDimitry Andric     const VETargetMachine *TM =
1777e8d8bef9SDimitry Andric         static_cast<const VETargetMachine *>(&DAG.getTarget());
1778e8d8bef9SDimitry Andric 
1779e8d8bef9SDimitry Andric     // Create GCC_except_tableXX string.  The real symbol for that will be
1780e8d8bef9SDimitry Andric     // generated in EHStreamer::emitExceptionTable() later.  So, we just
1781e8d8bef9SDimitry Andric     // borrow it's name here.
1782e8d8bef9SDimitry Andric     TM->getStrList()->push_back(std::string(
1783e8d8bef9SDimitry Andric         (Twine("GCC_except_table") + Twine(MF.getFunctionNumber())).str()));
1784e8d8bef9SDimitry Andric     SDValue Addr =
1785e8d8bef9SDimitry Andric         DAG.getTargetExternalSymbol(TM->getStrList()->back().c_str(), VT, 0);
1786e8d8bef9SDimitry Andric     if (isPositionIndependent()) {
1787e8d8bef9SDimitry Andric       Addr = makeHiLoPair(Addr, VEMCExpr::VK_VE_GOTOFF_HI32,
1788e8d8bef9SDimitry Andric                           VEMCExpr::VK_VE_GOTOFF_LO32, DAG);
1789e8d8bef9SDimitry Andric       SDValue GlobalBase = DAG.getNode(VEISD::GLOBAL_BASE_REG, DL, VT);
1790e8d8bef9SDimitry Andric       return DAG.getNode(ISD::ADD, DL, VT, GlobalBase, Addr);
1791e8d8bef9SDimitry Andric     }
1792e8d8bef9SDimitry Andric     return makeHiLoPair(Addr, VEMCExpr::VK_VE_HI32, VEMCExpr::VK_VE_LO32, DAG);
1793e8d8bef9SDimitry Andric   }
1794e8d8bef9SDimitry Andric   }
1795e8d8bef9SDimitry Andric }
1796e8d8bef9SDimitry Andric 
getUniqueInsertion(SDNode * N,unsigned & UniqueIdx)1797e8d8bef9SDimitry Andric static bool getUniqueInsertion(SDNode *N, unsigned &UniqueIdx) {
1798e8d8bef9SDimitry Andric   if (!isa<BuildVectorSDNode>(N))
1799e8d8bef9SDimitry Andric     return false;
1800e8d8bef9SDimitry Andric   const auto *BVN = cast<BuildVectorSDNode>(N);
1801e8d8bef9SDimitry Andric 
1802e8d8bef9SDimitry Andric   // Find first non-undef insertion.
1803e8d8bef9SDimitry Andric   unsigned Idx;
1804e8d8bef9SDimitry Andric   for (Idx = 0; Idx < BVN->getNumOperands(); ++Idx) {
1805e8d8bef9SDimitry Andric     auto ElemV = BVN->getOperand(Idx);
1806e8d8bef9SDimitry Andric     if (!ElemV->isUndef())
1807e8d8bef9SDimitry Andric       break;
1808e8d8bef9SDimitry Andric   }
1809e8d8bef9SDimitry Andric   // Catch the (hypothetical) all-undef case.
1810e8d8bef9SDimitry Andric   if (Idx == BVN->getNumOperands())
1811e8d8bef9SDimitry Andric     return false;
1812e8d8bef9SDimitry Andric   // Remember insertion.
1813e8d8bef9SDimitry Andric   UniqueIdx = Idx++;
1814e8d8bef9SDimitry Andric   // Verify that all other insertions are undef.
1815e8d8bef9SDimitry Andric   for (; Idx < BVN->getNumOperands(); ++Idx) {
1816e8d8bef9SDimitry Andric     auto ElemV = BVN->getOperand(Idx);
1817e8d8bef9SDimitry Andric     if (!ElemV->isUndef())
1818e8d8bef9SDimitry Andric       return false;
1819e8d8bef9SDimitry Andric   }
1820e8d8bef9SDimitry Andric   return true;
1821e8d8bef9SDimitry Andric }
1822e8d8bef9SDimitry Andric 
getSplatValue(SDNode * N)1823e8d8bef9SDimitry Andric static SDValue getSplatValue(SDNode *N) {
1824e8d8bef9SDimitry Andric   if (auto *BuildVec = dyn_cast<BuildVectorSDNode>(N)) {
1825e8d8bef9SDimitry Andric     return BuildVec->getSplatValue();
1826e8d8bef9SDimitry Andric   }
1827e8d8bef9SDimitry Andric   return SDValue();
1828e8d8bef9SDimitry Andric }
1829e8d8bef9SDimitry Andric 
lowerBUILD_VECTOR(SDValue Op,SelectionDAG & DAG) const1830e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerBUILD_VECTOR(SDValue Op,
1831e8d8bef9SDimitry Andric                                             SelectionDAG &DAG) const {
183204eeddc0SDimitry Andric   VECustomDAG CDAG(DAG, Op);
183304eeddc0SDimitry Andric   MVT ResultVT = Op.getSimpleValueType();
1834e8d8bef9SDimitry Andric 
1835e8d8bef9SDimitry Andric   // If there is just one element, expand to INSERT_VECTOR_ELT.
1836e8d8bef9SDimitry Andric   unsigned UniqueIdx;
1837e8d8bef9SDimitry Andric   if (getUniqueInsertion(Op.getNode(), UniqueIdx)) {
183804eeddc0SDimitry Andric     SDValue AccuV = CDAG.getUNDEF(Op.getValueType());
1839e8d8bef9SDimitry Andric     auto ElemV = Op->getOperand(UniqueIdx);
184004eeddc0SDimitry Andric     SDValue IdxV = CDAG.getConstant(UniqueIdx, MVT::i64);
184104eeddc0SDimitry Andric     return CDAG.getNode(ISD::INSERT_VECTOR_ELT, ResultVT, {AccuV, ElemV, IdxV});
1842e8d8bef9SDimitry Andric   }
1843e8d8bef9SDimitry Andric 
1844e8d8bef9SDimitry Andric   // Else emit a broadcast.
1845e8d8bef9SDimitry Andric   if (SDValue ScalarV = getSplatValue(Op.getNode())) {
184604eeddc0SDimitry Andric     unsigned NumEls = ResultVT.getVectorNumElements();
184781ad6265SDimitry Andric     auto AVL = CDAG.getConstant(NumEls, MVT::i32);
184881ad6265SDimitry Andric     return CDAG.getBroadcast(ResultVT, ScalarV, AVL);
1849e8d8bef9SDimitry Andric   }
1850e8d8bef9SDimitry Andric 
1851e8d8bef9SDimitry Andric   // Expand
1852e8d8bef9SDimitry Andric   return SDValue();
1853e8d8bef9SDimitry Andric }
1854e8d8bef9SDimitry Andric 
185581ad6265SDimitry Andric TargetLowering::LegalizeAction
getCustomOperationAction(SDNode & Op) const185681ad6265SDimitry Andric VETargetLowering::getCustomOperationAction(SDNode &Op) const {
185781ad6265SDimitry Andric   // Custom legalization on VVP_* and VEC_* opcodes is required to pack-legalize
185881ad6265SDimitry Andric   // these operations (transform nodes such that their AVL parameter refers to
185981ad6265SDimitry Andric   // packs of 64bit, instead of number of elements.
1860e8d8bef9SDimitry Andric 
186181ad6265SDimitry Andric   // Packing opcodes are created with a pack-legal AVL (LEGALAVL). No need to
186281ad6265SDimitry Andric   // re-visit them.
186381ad6265SDimitry Andric   if (isPackingSupportOpcode(Op.getOpcode()))
186481ad6265SDimitry Andric     return Legal;
186581ad6265SDimitry Andric 
186681ad6265SDimitry Andric   // Custom lower to legalize AVL for packed mode.
186781ad6265SDimitry Andric   if (isVVPOrVEC(Op.getOpcode()))
186881ad6265SDimitry Andric     return Custom;
186981ad6265SDimitry Andric   return Legal;
187081ad6265SDimitry Andric }
187181ad6265SDimitry Andric 
LowerOperation(SDValue Op,SelectionDAG & DAG) const187281ad6265SDimitry Andric SDValue VETargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
18735f757f3fSDimitry Andric   LLVM_DEBUG(dbgs() << "::LowerOperation "; Op.dump(&DAG));
187481ad6265SDimitry Andric   unsigned Opcode = Op.getOpcode();
187581ad6265SDimitry Andric 
187681ad6265SDimitry Andric   /// Scalar isel.
1877e8d8bef9SDimitry Andric   switch (Opcode) {
1878e8d8bef9SDimitry Andric   case ISD::ATOMIC_FENCE:
1879e8d8bef9SDimitry Andric     return lowerATOMIC_FENCE(Op, DAG);
1880e8d8bef9SDimitry Andric   case ISD::ATOMIC_SWAP:
1881e8d8bef9SDimitry Andric     return lowerATOMIC_SWAP(Op, DAG);
18825ffd83dbSDimitry Andric   case ISD::BlockAddress:
1883e8d8bef9SDimitry Andric     return lowerBlockAddress(Op, DAG);
1884e8d8bef9SDimitry Andric   case ISD::ConstantPool:
1885e8d8bef9SDimitry Andric     return lowerConstantPool(Op, DAG);
18865ffd83dbSDimitry Andric   case ISD::DYNAMIC_STACKALLOC:
18875ffd83dbSDimitry Andric     return lowerDYNAMIC_STACKALLOC(Op, DAG);
1888e8d8bef9SDimitry Andric   case ISD::EH_SJLJ_LONGJMP:
1889e8d8bef9SDimitry Andric     return lowerEH_SJLJ_LONGJMP(Op, DAG);
1890e8d8bef9SDimitry Andric   case ISD::EH_SJLJ_SETJMP:
1891e8d8bef9SDimitry Andric     return lowerEH_SJLJ_SETJMP(Op, DAG);
1892e8d8bef9SDimitry Andric   case ISD::EH_SJLJ_SETUP_DISPATCH:
1893e8d8bef9SDimitry Andric     return lowerEH_SJLJ_SETUP_DISPATCH(Op, DAG);
1894e8d8bef9SDimitry Andric   case ISD::FRAMEADDR:
1895e8d8bef9SDimitry Andric     return lowerFRAMEADDR(Op, DAG, *this, Subtarget);
18965ffd83dbSDimitry Andric   case ISD::GlobalAddress:
1897e8d8bef9SDimitry Andric     return lowerGlobalAddress(Op, DAG);
18985ffd83dbSDimitry Andric   case ISD::GlobalTLSAddress:
1899e8d8bef9SDimitry Andric     return lowerGlobalTLSAddress(Op, DAG);
1900e8d8bef9SDimitry Andric   case ISD::INTRINSIC_WO_CHAIN:
1901e8d8bef9SDimitry Andric     return lowerINTRINSIC_WO_CHAIN(Op, DAG);
1902e8d8bef9SDimitry Andric   case ISD::JumpTable:
1903e8d8bef9SDimitry Andric     return lowerJumpTable(Op, DAG);
1904e8d8bef9SDimitry Andric   case ISD::LOAD:
1905e8d8bef9SDimitry Andric     return lowerLOAD(Op, DAG);
1906e8d8bef9SDimitry Andric   case ISD::RETURNADDR:
1907e8d8bef9SDimitry Andric     return lowerRETURNADDR(Op, DAG, *this, Subtarget);
1908e8d8bef9SDimitry Andric   case ISD::BUILD_VECTOR:
1909e8d8bef9SDimitry Andric     return lowerBUILD_VECTOR(Op, DAG);
1910e8d8bef9SDimitry Andric   case ISD::STORE:
1911e8d8bef9SDimitry Andric     return lowerSTORE(Op, DAG);
19125ffd83dbSDimitry Andric   case ISD::VASTART:
1913e8d8bef9SDimitry Andric     return lowerVASTART(Op, DAG);
19145ffd83dbSDimitry Andric   case ISD::VAARG:
1915e8d8bef9SDimitry Andric     return lowerVAARG(Op, DAG);
1916e8d8bef9SDimitry Andric 
1917e8d8bef9SDimitry Andric   case ISD::INSERT_VECTOR_ELT:
1918e8d8bef9SDimitry Andric     return lowerINSERT_VECTOR_ELT(Op, DAG);
1919e8d8bef9SDimitry Andric   case ISD::EXTRACT_VECTOR_ELT:
1920e8d8bef9SDimitry Andric     return lowerEXTRACT_VECTOR_ELT(Op, DAG);
192181ad6265SDimitry Andric   }
1922e8d8bef9SDimitry Andric 
192381ad6265SDimitry Andric   /// Vector isel.
192481ad6265SDimitry Andric   if (ISD::isVPOpcode(Opcode))
192581ad6265SDimitry Andric     return lowerToVVP(Op, DAG);
192681ad6265SDimitry Andric 
192781ad6265SDimitry Andric   switch (Opcode) {
192881ad6265SDimitry Andric   default:
192981ad6265SDimitry Andric     llvm_unreachable("Should not custom lower this!");
193081ad6265SDimitry Andric 
193181ad6265SDimitry Andric   // Legalize the AVL of this internal node.
193281ad6265SDimitry Andric   case VEISD::VEC_BROADCAST:
193381ad6265SDimitry Andric #define ADD_VVP_OP(VVP_NAME, ...) case VEISD::VVP_NAME:
193481ad6265SDimitry Andric #include "VVPNodes.def"
193581ad6265SDimitry Andric     // AVL already legalized.
193681ad6265SDimitry Andric     if (getAnnotatedNodeAVL(Op).second)
193781ad6265SDimitry Andric       return Op;
193881ad6265SDimitry Andric     return legalizeInternalVectorOp(Op, DAG);
193981ad6265SDimitry Andric 
194081ad6265SDimitry Andric     // Translate into a VEC_*/VVP_* layer operation.
194181ad6265SDimitry Andric   case ISD::MLOAD:
194281ad6265SDimitry Andric   case ISD::MSTORE:
194304eeddc0SDimitry Andric #define ADD_VVP_OP(VVP_NAME, ISD_NAME) case ISD::ISD_NAME:
1944e8d8bef9SDimitry Andric #include "VVPNodes.def"
194581ad6265SDimitry Andric     if (isMaskArithmetic(Op) && isPackedVectorType(Op.getValueType()))
194681ad6265SDimitry Andric       return splitMaskArithmetic(Op, DAG);
1947e8d8bef9SDimitry Andric     return lowerToVVP(Op, DAG);
19485ffd83dbSDimitry Andric   }
19495ffd83dbSDimitry Andric }
19505ffd83dbSDimitry Andric /// } Custom Lower
1951e8d8bef9SDimitry Andric 
ReplaceNodeResults(SDNode * N,SmallVectorImpl<SDValue> & Results,SelectionDAG & DAG) const1952e8d8bef9SDimitry Andric void VETargetLowering::ReplaceNodeResults(SDNode *N,
1953e8d8bef9SDimitry Andric                                           SmallVectorImpl<SDValue> &Results,
1954e8d8bef9SDimitry Andric                                           SelectionDAG &DAG) const {
1955e8d8bef9SDimitry Andric   switch (N->getOpcode()) {
1956e8d8bef9SDimitry Andric   case ISD::ATOMIC_SWAP:
1957e8d8bef9SDimitry Andric     // Let LLVM expand atomic swap instruction through LowerOperation.
1958e8d8bef9SDimitry Andric     return;
1959e8d8bef9SDimitry Andric   default:
1960e8d8bef9SDimitry Andric     LLVM_DEBUG(N->dumpr(&DAG));
1961e8d8bef9SDimitry Andric     llvm_unreachable("Do not know how to custom type legalize this operation!");
1962e8d8bef9SDimitry Andric   }
1963e8d8bef9SDimitry Andric }
1964e8d8bef9SDimitry Andric 
1965e8d8bef9SDimitry Andric /// JumpTable for VE.
1966e8d8bef9SDimitry Andric ///
1967e8d8bef9SDimitry Andric ///   VE cannot generate relocatable symbol in jump table.  VE cannot
1968e8d8bef9SDimitry Andric ///   generate expressions using symbols in both text segment and data
1969e8d8bef9SDimitry Andric ///   segment like below.
1970e8d8bef9SDimitry Andric ///             .4byte  .LBB0_2-.LJTI0_0
1971e8d8bef9SDimitry Andric ///   So, we generate offset from the top of function like below as
1972e8d8bef9SDimitry Andric ///   a custom label.
1973e8d8bef9SDimitry Andric ///             .4byte  .LBB0_2-<function name>
1974e8d8bef9SDimitry Andric 
getJumpTableEncoding() const1975e8d8bef9SDimitry Andric unsigned VETargetLowering::getJumpTableEncoding() const {
1976e8d8bef9SDimitry Andric   // Use custom label for PIC.
1977e8d8bef9SDimitry Andric   if (isPositionIndependent())
1978e8d8bef9SDimitry Andric     return MachineJumpTableInfo::EK_Custom32;
1979e8d8bef9SDimitry Andric 
1980e8d8bef9SDimitry Andric   // Otherwise, use the normal jump table encoding heuristics.
1981e8d8bef9SDimitry Andric   return TargetLowering::getJumpTableEncoding();
1982e8d8bef9SDimitry Andric }
1983e8d8bef9SDimitry Andric 
LowerCustomJumpTableEntry(const MachineJumpTableInfo * MJTI,const MachineBasicBlock * MBB,unsigned Uid,MCContext & Ctx) const1984e8d8bef9SDimitry Andric const MCExpr *VETargetLowering::LowerCustomJumpTableEntry(
1985e8d8bef9SDimitry Andric     const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB,
1986e8d8bef9SDimitry Andric     unsigned Uid, MCContext &Ctx) const {
1987e8d8bef9SDimitry Andric   assert(isPositionIndependent());
1988e8d8bef9SDimitry Andric 
1989e8d8bef9SDimitry Andric   // Generate custom label for PIC like below.
1990e8d8bef9SDimitry Andric   //    .4bytes  .LBB0_2-<function name>
1991e8d8bef9SDimitry Andric   const auto *Value = MCSymbolRefExpr::create(MBB->getSymbol(), Ctx);
1992e8d8bef9SDimitry Andric   MCSymbol *Sym = Ctx.getOrCreateSymbol(MBB->getParent()->getName().data());
1993e8d8bef9SDimitry Andric   const auto *Base = MCSymbolRefExpr::create(Sym, Ctx);
1994e8d8bef9SDimitry Andric   return MCBinaryExpr::createSub(Value, Base, Ctx);
1995e8d8bef9SDimitry Andric }
1996e8d8bef9SDimitry Andric 
getPICJumpTableRelocBase(SDValue Table,SelectionDAG & DAG) const1997e8d8bef9SDimitry Andric SDValue VETargetLowering::getPICJumpTableRelocBase(SDValue Table,
1998e8d8bef9SDimitry Andric                                                    SelectionDAG &DAG) const {
1999e8d8bef9SDimitry Andric   assert(isPositionIndependent());
2000e8d8bef9SDimitry Andric   SDLoc DL(Table);
2001e8d8bef9SDimitry Andric   Function *Function = &DAG.getMachineFunction().getFunction();
2002e8d8bef9SDimitry Andric   assert(Function != nullptr);
2003e8d8bef9SDimitry Andric   auto PtrTy = getPointerTy(DAG.getDataLayout(), Function->getAddressSpace());
2004e8d8bef9SDimitry Andric 
2005e8d8bef9SDimitry Andric   // In the jump table, we have following values in PIC mode.
2006e8d8bef9SDimitry Andric   //    .4bytes  .LBB0_2-<function name>
2007e8d8bef9SDimitry Andric   // We need to add this value and the address of this function to generate
2008e8d8bef9SDimitry Andric   // .LBB0_2 label correctly under PIC mode.  So, we want to generate following
2009e8d8bef9SDimitry Andric   // instructions:
2010e8d8bef9SDimitry Andric   //     lea %reg, fun@gotoff_lo
2011e8d8bef9SDimitry Andric   //     and %reg, %reg, (32)0
2012e8d8bef9SDimitry Andric   //     lea.sl %reg, fun@gotoff_hi(%reg, %got)
2013e8d8bef9SDimitry Andric   // In order to do so, we need to genarate correctly marked DAG node using
2014e8d8bef9SDimitry Andric   // makeHiLoPair.
2015e8d8bef9SDimitry Andric   SDValue Op = DAG.getGlobalAddress(Function, DL, PtrTy);
2016e8d8bef9SDimitry Andric   SDValue HiLo = makeHiLoPair(Op, VEMCExpr::VK_VE_GOTOFF_HI32,
2017e8d8bef9SDimitry Andric                               VEMCExpr::VK_VE_GOTOFF_LO32, DAG);
2018e8d8bef9SDimitry Andric   SDValue GlobalBase = DAG.getNode(VEISD::GLOBAL_BASE_REG, DL, PtrTy);
2019e8d8bef9SDimitry Andric   return DAG.getNode(ISD::ADD, DL, PtrTy, GlobalBase, HiLo);
2020e8d8bef9SDimitry Andric }
2021e8d8bef9SDimitry Andric 
prepareMBB(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,MachineBasicBlock * TargetBB,const DebugLoc & DL) const2022e8d8bef9SDimitry Andric Register VETargetLowering::prepareMBB(MachineBasicBlock &MBB,
2023e8d8bef9SDimitry Andric                                       MachineBasicBlock::iterator I,
2024e8d8bef9SDimitry Andric                                       MachineBasicBlock *TargetBB,
2025e8d8bef9SDimitry Andric                                       const DebugLoc &DL) const {
2026e8d8bef9SDimitry Andric   MachineFunction *MF = MBB.getParent();
2027e8d8bef9SDimitry Andric   MachineRegisterInfo &MRI = MF->getRegInfo();
2028e8d8bef9SDimitry Andric   const VEInstrInfo *TII = Subtarget->getInstrInfo();
2029e8d8bef9SDimitry Andric 
2030e8d8bef9SDimitry Andric   const TargetRegisterClass *RC = &VE::I64RegClass;
2031e8d8bef9SDimitry Andric   Register Tmp1 = MRI.createVirtualRegister(RC);
2032e8d8bef9SDimitry Andric   Register Tmp2 = MRI.createVirtualRegister(RC);
2033e8d8bef9SDimitry Andric   Register Result = MRI.createVirtualRegister(RC);
2034e8d8bef9SDimitry Andric 
2035e8d8bef9SDimitry Andric   if (isPositionIndependent()) {
2036e8d8bef9SDimitry Andric     // Create following instructions for local linkage PIC code.
2037e8d8bef9SDimitry Andric     //     lea %Tmp1, TargetBB@gotoff_lo
2038e8d8bef9SDimitry Andric     //     and %Tmp2, %Tmp1, (32)0
2039e8d8bef9SDimitry Andric     //     lea.sl %Result, TargetBB@gotoff_hi(%Tmp2, %s15) ; %s15 is GOT
2040e8d8bef9SDimitry Andric     BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1)
2041e8d8bef9SDimitry Andric         .addImm(0)
2042e8d8bef9SDimitry Andric         .addImm(0)
2043e8d8bef9SDimitry Andric         .addMBB(TargetBB, VEMCExpr::VK_VE_GOTOFF_LO32);
2044e8d8bef9SDimitry Andric     BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2)
2045e8d8bef9SDimitry Andric         .addReg(Tmp1, getKillRegState(true))
2046e8d8bef9SDimitry Andric         .addImm(M0(32));
2047e8d8bef9SDimitry Andric     BuildMI(MBB, I, DL, TII->get(VE::LEASLrri), Result)
2048e8d8bef9SDimitry Andric         .addReg(VE::SX15)
2049e8d8bef9SDimitry Andric         .addReg(Tmp2, getKillRegState(true))
2050e8d8bef9SDimitry Andric         .addMBB(TargetBB, VEMCExpr::VK_VE_GOTOFF_HI32);
2051e8d8bef9SDimitry Andric   } else {
2052e8d8bef9SDimitry Andric     // Create following instructions for non-PIC code.
2053e8d8bef9SDimitry Andric     //     lea     %Tmp1, TargetBB@lo
2054e8d8bef9SDimitry Andric     //     and     %Tmp2, %Tmp1, (32)0
2055e8d8bef9SDimitry Andric     //     lea.sl  %Result, TargetBB@hi(%Tmp2)
2056e8d8bef9SDimitry Andric     BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1)
2057e8d8bef9SDimitry Andric         .addImm(0)
2058e8d8bef9SDimitry Andric         .addImm(0)
2059e8d8bef9SDimitry Andric         .addMBB(TargetBB, VEMCExpr::VK_VE_LO32);
2060e8d8bef9SDimitry Andric     BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2)
2061e8d8bef9SDimitry Andric         .addReg(Tmp1, getKillRegState(true))
2062e8d8bef9SDimitry Andric         .addImm(M0(32));
2063e8d8bef9SDimitry Andric     BuildMI(MBB, I, DL, TII->get(VE::LEASLrii), Result)
2064e8d8bef9SDimitry Andric         .addReg(Tmp2, getKillRegState(true))
2065e8d8bef9SDimitry Andric         .addImm(0)
2066e8d8bef9SDimitry Andric         .addMBB(TargetBB, VEMCExpr::VK_VE_HI32);
2067e8d8bef9SDimitry Andric   }
2068e8d8bef9SDimitry Andric   return Result;
2069e8d8bef9SDimitry Andric }
2070e8d8bef9SDimitry Andric 
prepareSymbol(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,StringRef Symbol,const DebugLoc & DL,bool IsLocal=false,bool IsCall=false) const2071e8d8bef9SDimitry Andric Register VETargetLowering::prepareSymbol(MachineBasicBlock &MBB,
2072e8d8bef9SDimitry Andric                                          MachineBasicBlock::iterator I,
2073e8d8bef9SDimitry Andric                                          StringRef Symbol, const DebugLoc &DL,
2074e8d8bef9SDimitry Andric                                          bool IsLocal = false,
2075e8d8bef9SDimitry Andric                                          bool IsCall = false) const {
2076e8d8bef9SDimitry Andric   MachineFunction *MF = MBB.getParent();
2077e8d8bef9SDimitry Andric   MachineRegisterInfo &MRI = MF->getRegInfo();
2078e8d8bef9SDimitry Andric   const VEInstrInfo *TII = Subtarget->getInstrInfo();
2079e8d8bef9SDimitry Andric 
2080e8d8bef9SDimitry Andric   const TargetRegisterClass *RC = &VE::I64RegClass;
2081e8d8bef9SDimitry Andric   Register Result = MRI.createVirtualRegister(RC);
2082e8d8bef9SDimitry Andric 
2083e8d8bef9SDimitry Andric   if (isPositionIndependent()) {
2084e8d8bef9SDimitry Andric     if (IsCall && !IsLocal) {
2085e8d8bef9SDimitry Andric       // Create following instructions for non-local linkage PIC code function
2086e8d8bef9SDimitry Andric       // calls.  These instructions uses IC and magic number -24, so we expand
2087e8d8bef9SDimitry Andric       // them in VEAsmPrinter.cpp from GETFUNPLT pseudo instruction.
2088e8d8bef9SDimitry Andric       //     lea %Reg, Symbol@plt_lo(-24)
2089e8d8bef9SDimitry Andric       //     and %Reg, %Reg, (32)0
2090e8d8bef9SDimitry Andric       //     sic %s16
2091e8d8bef9SDimitry Andric       //     lea.sl %Result, Symbol@plt_hi(%Reg, %s16) ; %s16 is PLT
2092e8d8bef9SDimitry Andric       BuildMI(MBB, I, DL, TII->get(VE::GETFUNPLT), Result)
2093e8d8bef9SDimitry Andric           .addExternalSymbol("abort");
2094e8d8bef9SDimitry Andric     } else if (IsLocal) {
2095e8d8bef9SDimitry Andric       Register Tmp1 = MRI.createVirtualRegister(RC);
2096e8d8bef9SDimitry Andric       Register Tmp2 = MRI.createVirtualRegister(RC);
2097e8d8bef9SDimitry Andric       // Create following instructions for local linkage PIC code.
2098e8d8bef9SDimitry Andric       //     lea %Tmp1, Symbol@gotoff_lo
2099e8d8bef9SDimitry Andric       //     and %Tmp2, %Tmp1, (32)0
2100e8d8bef9SDimitry Andric       //     lea.sl %Result, Symbol@gotoff_hi(%Tmp2, %s15) ; %s15 is GOT
2101e8d8bef9SDimitry Andric       BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1)
2102e8d8bef9SDimitry Andric           .addImm(0)
2103e8d8bef9SDimitry Andric           .addImm(0)
2104e8d8bef9SDimitry Andric           .addExternalSymbol(Symbol.data(), VEMCExpr::VK_VE_GOTOFF_LO32);
2105e8d8bef9SDimitry Andric       BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2)
2106e8d8bef9SDimitry Andric           .addReg(Tmp1, getKillRegState(true))
2107e8d8bef9SDimitry Andric           .addImm(M0(32));
2108e8d8bef9SDimitry Andric       BuildMI(MBB, I, DL, TII->get(VE::LEASLrri), Result)
2109e8d8bef9SDimitry Andric           .addReg(VE::SX15)
2110e8d8bef9SDimitry Andric           .addReg(Tmp2, getKillRegState(true))
2111e8d8bef9SDimitry Andric           .addExternalSymbol(Symbol.data(), VEMCExpr::VK_VE_GOTOFF_HI32);
2112e8d8bef9SDimitry Andric     } else {
2113e8d8bef9SDimitry Andric       Register Tmp1 = MRI.createVirtualRegister(RC);
2114e8d8bef9SDimitry Andric       Register Tmp2 = MRI.createVirtualRegister(RC);
2115e8d8bef9SDimitry Andric       // Create following instructions for not local linkage PIC code.
2116e8d8bef9SDimitry Andric       //     lea %Tmp1, Symbol@got_lo
2117e8d8bef9SDimitry Andric       //     and %Tmp2, %Tmp1, (32)0
2118e8d8bef9SDimitry Andric       //     lea.sl %Tmp3, Symbol@gotoff_hi(%Tmp2, %s15) ; %s15 is GOT
2119e8d8bef9SDimitry Andric       //     ld %Result, 0(%Tmp3)
2120e8d8bef9SDimitry Andric       Register Tmp3 = MRI.createVirtualRegister(RC);
2121e8d8bef9SDimitry Andric       BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1)
2122e8d8bef9SDimitry Andric           .addImm(0)
2123e8d8bef9SDimitry Andric           .addImm(0)
2124e8d8bef9SDimitry Andric           .addExternalSymbol(Symbol.data(), VEMCExpr::VK_VE_GOT_LO32);
2125e8d8bef9SDimitry Andric       BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2)
2126e8d8bef9SDimitry Andric           .addReg(Tmp1, getKillRegState(true))
2127e8d8bef9SDimitry Andric           .addImm(M0(32));
2128e8d8bef9SDimitry Andric       BuildMI(MBB, I, DL, TII->get(VE::LEASLrri), Tmp3)
2129e8d8bef9SDimitry Andric           .addReg(VE::SX15)
2130e8d8bef9SDimitry Andric           .addReg(Tmp2, getKillRegState(true))
2131e8d8bef9SDimitry Andric           .addExternalSymbol(Symbol.data(), VEMCExpr::VK_VE_GOT_HI32);
2132e8d8bef9SDimitry Andric       BuildMI(MBB, I, DL, TII->get(VE::LDrii), Result)
2133e8d8bef9SDimitry Andric           .addReg(Tmp3, getKillRegState(true))
2134e8d8bef9SDimitry Andric           .addImm(0)
2135e8d8bef9SDimitry Andric           .addImm(0);
2136e8d8bef9SDimitry Andric     }
2137e8d8bef9SDimitry Andric   } else {
2138e8d8bef9SDimitry Andric     Register Tmp1 = MRI.createVirtualRegister(RC);
2139e8d8bef9SDimitry Andric     Register Tmp2 = MRI.createVirtualRegister(RC);
2140e8d8bef9SDimitry Andric     // Create following instructions for non-PIC code.
2141e8d8bef9SDimitry Andric     //     lea     %Tmp1, Symbol@lo
2142e8d8bef9SDimitry Andric     //     and     %Tmp2, %Tmp1, (32)0
2143e8d8bef9SDimitry Andric     //     lea.sl  %Result, Symbol@hi(%Tmp2)
2144e8d8bef9SDimitry Andric     BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1)
2145e8d8bef9SDimitry Andric         .addImm(0)
2146e8d8bef9SDimitry Andric         .addImm(0)
2147e8d8bef9SDimitry Andric         .addExternalSymbol(Symbol.data(), VEMCExpr::VK_VE_LO32);
2148e8d8bef9SDimitry Andric     BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2)
2149e8d8bef9SDimitry Andric         .addReg(Tmp1, getKillRegState(true))
2150e8d8bef9SDimitry Andric         .addImm(M0(32));
2151e8d8bef9SDimitry Andric     BuildMI(MBB, I, DL, TII->get(VE::LEASLrii), Result)
2152e8d8bef9SDimitry Andric         .addReg(Tmp2, getKillRegState(true))
2153e8d8bef9SDimitry Andric         .addImm(0)
2154e8d8bef9SDimitry Andric         .addExternalSymbol(Symbol.data(), VEMCExpr::VK_VE_HI32);
2155e8d8bef9SDimitry Andric   }
2156e8d8bef9SDimitry Andric   return Result;
2157e8d8bef9SDimitry Andric }
2158e8d8bef9SDimitry Andric 
setupEntryBlockForSjLj(MachineInstr & MI,MachineBasicBlock * MBB,MachineBasicBlock * DispatchBB,int FI,int Offset) const2159e8d8bef9SDimitry Andric void VETargetLowering::setupEntryBlockForSjLj(MachineInstr &MI,
2160e8d8bef9SDimitry Andric                                               MachineBasicBlock *MBB,
2161e8d8bef9SDimitry Andric                                               MachineBasicBlock *DispatchBB,
2162e8d8bef9SDimitry Andric                                               int FI, int Offset) const {
2163e8d8bef9SDimitry Andric   DebugLoc DL = MI.getDebugLoc();
2164e8d8bef9SDimitry Andric   const VEInstrInfo *TII = Subtarget->getInstrInfo();
2165e8d8bef9SDimitry Andric 
2166e8d8bef9SDimitry Andric   Register LabelReg =
2167e8d8bef9SDimitry Andric       prepareMBB(*MBB, MachineBasicBlock::iterator(MI), DispatchBB, DL);
2168e8d8bef9SDimitry Andric 
2169e8d8bef9SDimitry Andric   // Store an address of DispatchBB to a given jmpbuf[1] where has next IC
2170e8d8bef9SDimitry Andric   // referenced by longjmp (throw) later.
2171e8d8bef9SDimitry Andric   MachineInstrBuilder MIB = BuildMI(*MBB, MI, DL, TII->get(VE::STrii));
2172e8d8bef9SDimitry Andric   addFrameReference(MIB, FI, Offset); // jmpbuf[1]
2173e8d8bef9SDimitry Andric   MIB.addReg(LabelReg, getKillRegState(true));
2174e8d8bef9SDimitry Andric }
2175e8d8bef9SDimitry Andric 
2176e8d8bef9SDimitry Andric MachineBasicBlock *
emitEHSjLjSetJmp(MachineInstr & MI,MachineBasicBlock * MBB) const2177e8d8bef9SDimitry Andric VETargetLowering::emitEHSjLjSetJmp(MachineInstr &MI,
2178e8d8bef9SDimitry Andric                                    MachineBasicBlock *MBB) const {
2179e8d8bef9SDimitry Andric   DebugLoc DL = MI.getDebugLoc();
2180e8d8bef9SDimitry Andric   MachineFunction *MF = MBB->getParent();
2181e8d8bef9SDimitry Andric   const TargetInstrInfo *TII = Subtarget->getInstrInfo();
2182e8d8bef9SDimitry Andric   const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo();
2183e8d8bef9SDimitry Andric   MachineRegisterInfo &MRI = MF->getRegInfo();
2184e8d8bef9SDimitry Andric 
2185e8d8bef9SDimitry Andric   const BasicBlock *BB = MBB->getBasicBlock();
2186e8d8bef9SDimitry Andric   MachineFunction::iterator I = ++MBB->getIterator();
2187e8d8bef9SDimitry Andric 
2188e8d8bef9SDimitry Andric   // Memory Reference.
2189e8d8bef9SDimitry Andric   SmallVector<MachineMemOperand *, 2> MMOs(MI.memoperands_begin(),
2190e8d8bef9SDimitry Andric                                            MI.memoperands_end());
2191e8d8bef9SDimitry Andric   Register BufReg = MI.getOperand(1).getReg();
2192e8d8bef9SDimitry Andric 
2193e8d8bef9SDimitry Andric   Register DstReg;
2194e8d8bef9SDimitry Andric 
2195e8d8bef9SDimitry Andric   DstReg = MI.getOperand(0).getReg();
2196e8d8bef9SDimitry Andric   const TargetRegisterClass *RC = MRI.getRegClass(DstReg);
2197e8d8bef9SDimitry Andric   assert(TRI->isTypeLegalForClass(*RC, MVT::i32) && "Invalid destination!");
2198e8d8bef9SDimitry Andric   (void)TRI;
2199e8d8bef9SDimitry Andric   Register MainDestReg = MRI.createVirtualRegister(RC);
2200e8d8bef9SDimitry Andric   Register RestoreDestReg = MRI.createVirtualRegister(RC);
2201e8d8bef9SDimitry Andric 
2202e8d8bef9SDimitry Andric   // For `v = call @llvm.eh.sjlj.setjmp(buf)`, we generate following
2203e8d8bef9SDimitry Andric   // instructions.  SP/FP must be saved in jmpbuf before `llvm.eh.sjlj.setjmp`.
2204e8d8bef9SDimitry Andric   //
2205e8d8bef9SDimitry Andric   // ThisMBB:
2206e8d8bef9SDimitry Andric   //   buf[3] = %s17 iff %s17 is used as BP
2207e8d8bef9SDimitry Andric   //   buf[1] = RestoreMBB as IC after longjmp
2208e8d8bef9SDimitry Andric   //   # SjLjSetup RestoreMBB
2209e8d8bef9SDimitry Andric   //
2210e8d8bef9SDimitry Andric   // MainMBB:
2211e8d8bef9SDimitry Andric   //   v_main = 0
2212e8d8bef9SDimitry Andric   //
2213e8d8bef9SDimitry Andric   // SinkMBB:
2214e8d8bef9SDimitry Andric   //   v = phi(v_main, MainMBB, v_restore, RestoreMBB)
2215e8d8bef9SDimitry Andric   //   ...
2216e8d8bef9SDimitry Andric   //
2217e8d8bef9SDimitry Andric   // RestoreMBB:
2218e8d8bef9SDimitry Andric   //   %s17 = buf[3] = iff %s17 is used as BP
2219e8d8bef9SDimitry Andric   //   v_restore = 1
2220e8d8bef9SDimitry Andric   //   goto SinkMBB
2221e8d8bef9SDimitry Andric 
2222e8d8bef9SDimitry Andric   MachineBasicBlock *ThisMBB = MBB;
2223e8d8bef9SDimitry Andric   MachineBasicBlock *MainMBB = MF->CreateMachineBasicBlock(BB);
2224e8d8bef9SDimitry Andric   MachineBasicBlock *SinkMBB = MF->CreateMachineBasicBlock(BB);
2225e8d8bef9SDimitry Andric   MachineBasicBlock *RestoreMBB = MF->CreateMachineBasicBlock(BB);
2226e8d8bef9SDimitry Andric   MF->insert(I, MainMBB);
2227e8d8bef9SDimitry Andric   MF->insert(I, SinkMBB);
2228e8d8bef9SDimitry Andric   MF->push_back(RestoreMBB);
2229bdd1243dSDimitry Andric   RestoreMBB->setMachineBlockAddressTaken();
2230e8d8bef9SDimitry Andric 
2231e8d8bef9SDimitry Andric   // Transfer the remainder of BB and its successor edges to SinkMBB.
2232e8d8bef9SDimitry Andric   SinkMBB->splice(SinkMBB->begin(), MBB,
2233e8d8bef9SDimitry Andric                   std::next(MachineBasicBlock::iterator(MI)), MBB->end());
2234e8d8bef9SDimitry Andric   SinkMBB->transferSuccessorsAndUpdatePHIs(MBB);
2235e8d8bef9SDimitry Andric 
2236e8d8bef9SDimitry Andric   // ThisMBB:
2237e8d8bef9SDimitry Andric   Register LabelReg =
2238e8d8bef9SDimitry Andric       prepareMBB(*MBB, MachineBasicBlock::iterator(MI), RestoreMBB, DL);
2239e8d8bef9SDimitry Andric 
2240e8d8bef9SDimitry Andric   // Store BP in buf[3] iff this function is using BP.
2241e8d8bef9SDimitry Andric   const VEFrameLowering *TFI = Subtarget->getFrameLowering();
2242e8d8bef9SDimitry Andric   if (TFI->hasBP(*MF)) {
2243e8d8bef9SDimitry Andric     MachineInstrBuilder MIB = BuildMI(*MBB, MI, DL, TII->get(VE::STrii));
2244e8d8bef9SDimitry Andric     MIB.addReg(BufReg);
2245e8d8bef9SDimitry Andric     MIB.addImm(0);
2246e8d8bef9SDimitry Andric     MIB.addImm(24);
2247e8d8bef9SDimitry Andric     MIB.addReg(VE::SX17);
2248e8d8bef9SDimitry Andric     MIB.setMemRefs(MMOs);
2249e8d8bef9SDimitry Andric   }
2250e8d8bef9SDimitry Andric 
2251e8d8bef9SDimitry Andric   // Store IP in buf[1].
2252e8d8bef9SDimitry Andric   MachineInstrBuilder MIB = BuildMI(*MBB, MI, DL, TII->get(VE::STrii));
2253e8d8bef9SDimitry Andric   MIB.add(MI.getOperand(1)); // we can preserve the kill flags here.
2254e8d8bef9SDimitry Andric   MIB.addImm(0);
2255e8d8bef9SDimitry Andric   MIB.addImm(8);
2256e8d8bef9SDimitry Andric   MIB.addReg(LabelReg, getKillRegState(true));
2257e8d8bef9SDimitry Andric   MIB.setMemRefs(MMOs);
2258e8d8bef9SDimitry Andric 
2259e8d8bef9SDimitry Andric   // SP/FP are already stored in jmpbuf before `llvm.eh.sjlj.setjmp`.
2260e8d8bef9SDimitry Andric 
2261e8d8bef9SDimitry Andric   // Insert setup.
2262e8d8bef9SDimitry Andric   MIB =
2263e8d8bef9SDimitry Andric       BuildMI(*ThisMBB, MI, DL, TII->get(VE::EH_SjLj_Setup)).addMBB(RestoreMBB);
2264e8d8bef9SDimitry Andric 
2265e8d8bef9SDimitry Andric   const VERegisterInfo *RegInfo = Subtarget->getRegisterInfo();
2266e8d8bef9SDimitry Andric   MIB.addRegMask(RegInfo->getNoPreservedMask());
2267e8d8bef9SDimitry Andric   ThisMBB->addSuccessor(MainMBB);
2268e8d8bef9SDimitry Andric   ThisMBB->addSuccessor(RestoreMBB);
2269e8d8bef9SDimitry Andric 
2270e8d8bef9SDimitry Andric   // MainMBB:
2271e8d8bef9SDimitry Andric   BuildMI(MainMBB, DL, TII->get(VE::LEAzii), MainDestReg)
2272e8d8bef9SDimitry Andric       .addImm(0)
2273e8d8bef9SDimitry Andric       .addImm(0)
2274e8d8bef9SDimitry Andric       .addImm(0);
2275e8d8bef9SDimitry Andric   MainMBB->addSuccessor(SinkMBB);
2276e8d8bef9SDimitry Andric 
2277e8d8bef9SDimitry Andric   // SinkMBB:
2278e8d8bef9SDimitry Andric   BuildMI(*SinkMBB, SinkMBB->begin(), DL, TII->get(VE::PHI), DstReg)
2279e8d8bef9SDimitry Andric       .addReg(MainDestReg)
2280e8d8bef9SDimitry Andric       .addMBB(MainMBB)
2281e8d8bef9SDimitry Andric       .addReg(RestoreDestReg)
2282e8d8bef9SDimitry Andric       .addMBB(RestoreMBB);
2283e8d8bef9SDimitry Andric 
2284e8d8bef9SDimitry Andric   // RestoreMBB:
2285e8d8bef9SDimitry Andric   // Restore BP from buf[3] iff this function is using BP.  The address of
2286e8d8bef9SDimitry Andric   // buf is in SX10.
2287e8d8bef9SDimitry Andric   // FIXME: Better to not use SX10 here
2288e8d8bef9SDimitry Andric   if (TFI->hasBP(*MF)) {
2289e8d8bef9SDimitry Andric     MachineInstrBuilder MIB =
2290e8d8bef9SDimitry Andric         BuildMI(RestoreMBB, DL, TII->get(VE::LDrii), VE::SX17);
2291e8d8bef9SDimitry Andric     MIB.addReg(VE::SX10);
2292e8d8bef9SDimitry Andric     MIB.addImm(0);
2293e8d8bef9SDimitry Andric     MIB.addImm(24);
2294e8d8bef9SDimitry Andric     MIB.setMemRefs(MMOs);
2295e8d8bef9SDimitry Andric   }
2296e8d8bef9SDimitry Andric   BuildMI(RestoreMBB, DL, TII->get(VE::LEAzii), RestoreDestReg)
2297e8d8bef9SDimitry Andric       .addImm(0)
2298e8d8bef9SDimitry Andric       .addImm(0)
2299e8d8bef9SDimitry Andric       .addImm(1);
2300e8d8bef9SDimitry Andric   BuildMI(RestoreMBB, DL, TII->get(VE::BRCFLa_t)).addMBB(SinkMBB);
2301e8d8bef9SDimitry Andric   RestoreMBB->addSuccessor(SinkMBB);
2302e8d8bef9SDimitry Andric 
2303e8d8bef9SDimitry Andric   MI.eraseFromParent();
2304e8d8bef9SDimitry Andric   return SinkMBB;
2305e8d8bef9SDimitry Andric }
2306e8d8bef9SDimitry Andric 
2307e8d8bef9SDimitry Andric MachineBasicBlock *
emitEHSjLjLongJmp(MachineInstr & MI,MachineBasicBlock * MBB) const2308e8d8bef9SDimitry Andric VETargetLowering::emitEHSjLjLongJmp(MachineInstr &MI,
2309e8d8bef9SDimitry Andric                                     MachineBasicBlock *MBB) const {
2310e8d8bef9SDimitry Andric   DebugLoc DL = MI.getDebugLoc();
2311e8d8bef9SDimitry Andric   MachineFunction *MF = MBB->getParent();
2312e8d8bef9SDimitry Andric   const TargetInstrInfo *TII = Subtarget->getInstrInfo();
2313e8d8bef9SDimitry Andric   MachineRegisterInfo &MRI = MF->getRegInfo();
2314e8d8bef9SDimitry Andric 
2315e8d8bef9SDimitry Andric   // Memory Reference.
2316e8d8bef9SDimitry Andric   SmallVector<MachineMemOperand *, 2> MMOs(MI.memoperands_begin(),
2317e8d8bef9SDimitry Andric                                            MI.memoperands_end());
2318e8d8bef9SDimitry Andric   Register BufReg = MI.getOperand(0).getReg();
2319e8d8bef9SDimitry Andric 
2320e8d8bef9SDimitry Andric   Register Tmp = MRI.createVirtualRegister(&VE::I64RegClass);
2321e8d8bef9SDimitry Andric   // Since FP is only updated here but NOT referenced, it's treated as GPR.
2322e8d8bef9SDimitry Andric   Register FP = VE::SX9;
2323e8d8bef9SDimitry Andric   Register SP = VE::SX11;
2324e8d8bef9SDimitry Andric 
2325e8d8bef9SDimitry Andric   MachineInstrBuilder MIB;
2326e8d8bef9SDimitry Andric 
2327e8d8bef9SDimitry Andric   MachineBasicBlock *ThisMBB = MBB;
2328e8d8bef9SDimitry Andric 
2329e8d8bef9SDimitry Andric   // For `call @llvm.eh.sjlj.longjmp(buf)`, we generate following instructions.
2330e8d8bef9SDimitry Andric   //
2331e8d8bef9SDimitry Andric   // ThisMBB:
2332e8d8bef9SDimitry Andric   //   %fp = load buf[0]
2333e8d8bef9SDimitry Andric   //   %jmp = load buf[1]
2334e8d8bef9SDimitry Andric   //   %s10 = buf        ; Store an address of buf to SX10 for RestoreMBB
2335e8d8bef9SDimitry Andric   //   %sp = load buf[2] ; generated by llvm.eh.sjlj.setjmp.
2336e8d8bef9SDimitry Andric   //   jmp %jmp
2337e8d8bef9SDimitry Andric 
2338e8d8bef9SDimitry Andric   // Reload FP.
2339e8d8bef9SDimitry Andric   MIB = BuildMI(*ThisMBB, MI, DL, TII->get(VE::LDrii), FP);
2340e8d8bef9SDimitry Andric   MIB.addReg(BufReg);
2341e8d8bef9SDimitry Andric   MIB.addImm(0);
2342e8d8bef9SDimitry Andric   MIB.addImm(0);
2343e8d8bef9SDimitry Andric   MIB.setMemRefs(MMOs);
2344e8d8bef9SDimitry Andric 
2345e8d8bef9SDimitry Andric   // Reload IP.
2346e8d8bef9SDimitry Andric   MIB = BuildMI(*ThisMBB, MI, DL, TII->get(VE::LDrii), Tmp);
2347e8d8bef9SDimitry Andric   MIB.addReg(BufReg);
2348e8d8bef9SDimitry Andric   MIB.addImm(0);
2349e8d8bef9SDimitry Andric   MIB.addImm(8);
2350e8d8bef9SDimitry Andric   MIB.setMemRefs(MMOs);
2351e8d8bef9SDimitry Andric 
2352e8d8bef9SDimitry Andric   // Copy BufReg to SX10 for later use in setjmp.
2353e8d8bef9SDimitry Andric   // FIXME: Better to not use SX10 here
2354e8d8bef9SDimitry Andric   BuildMI(*ThisMBB, MI, DL, TII->get(VE::ORri), VE::SX10)
2355e8d8bef9SDimitry Andric       .addReg(BufReg)
2356e8d8bef9SDimitry Andric       .addImm(0);
2357e8d8bef9SDimitry Andric 
2358e8d8bef9SDimitry Andric   // Reload SP.
2359e8d8bef9SDimitry Andric   MIB = BuildMI(*ThisMBB, MI, DL, TII->get(VE::LDrii), SP);
2360e8d8bef9SDimitry Andric   MIB.add(MI.getOperand(0)); // we can preserve the kill flags here.
2361e8d8bef9SDimitry Andric   MIB.addImm(0);
2362e8d8bef9SDimitry Andric   MIB.addImm(16);
2363e8d8bef9SDimitry Andric   MIB.setMemRefs(MMOs);
2364e8d8bef9SDimitry Andric 
2365e8d8bef9SDimitry Andric   // Jump.
2366e8d8bef9SDimitry Andric   BuildMI(*ThisMBB, MI, DL, TII->get(VE::BCFLari_t))
2367e8d8bef9SDimitry Andric       .addReg(Tmp, getKillRegState(true))
2368e8d8bef9SDimitry Andric       .addImm(0);
2369e8d8bef9SDimitry Andric 
2370e8d8bef9SDimitry Andric   MI.eraseFromParent();
2371e8d8bef9SDimitry Andric   return ThisMBB;
2372e8d8bef9SDimitry Andric }
2373e8d8bef9SDimitry Andric 
2374e8d8bef9SDimitry Andric MachineBasicBlock *
emitSjLjDispatchBlock(MachineInstr & MI,MachineBasicBlock * BB) const2375e8d8bef9SDimitry Andric VETargetLowering::emitSjLjDispatchBlock(MachineInstr &MI,
2376e8d8bef9SDimitry Andric                                         MachineBasicBlock *BB) const {
2377e8d8bef9SDimitry Andric   DebugLoc DL = MI.getDebugLoc();
2378e8d8bef9SDimitry Andric   MachineFunction *MF = BB->getParent();
2379e8d8bef9SDimitry Andric   MachineFrameInfo &MFI = MF->getFrameInfo();
2380e8d8bef9SDimitry Andric   MachineRegisterInfo &MRI = MF->getRegInfo();
2381e8d8bef9SDimitry Andric   const VEInstrInfo *TII = Subtarget->getInstrInfo();
2382e8d8bef9SDimitry Andric   int FI = MFI.getFunctionContextIndex();
2383e8d8bef9SDimitry Andric 
2384e8d8bef9SDimitry Andric   // Get a mapping of the call site numbers to all of the landing pads they're
2385e8d8bef9SDimitry Andric   // associated with.
2386e8d8bef9SDimitry Andric   DenseMap<unsigned, SmallVector<MachineBasicBlock *, 2>> CallSiteNumToLPad;
2387e8d8bef9SDimitry Andric   unsigned MaxCSNum = 0;
2388e8d8bef9SDimitry Andric   for (auto &MBB : *MF) {
2389e8d8bef9SDimitry Andric     if (!MBB.isEHPad())
2390e8d8bef9SDimitry Andric       continue;
2391e8d8bef9SDimitry Andric 
2392e8d8bef9SDimitry Andric     MCSymbol *Sym = nullptr;
2393e8d8bef9SDimitry Andric     for (const auto &MI : MBB) {
2394e8d8bef9SDimitry Andric       if (MI.isDebugInstr())
2395e8d8bef9SDimitry Andric         continue;
2396e8d8bef9SDimitry Andric 
2397e8d8bef9SDimitry Andric       assert(MI.isEHLabel() && "expected EH_LABEL");
2398e8d8bef9SDimitry Andric       Sym = MI.getOperand(0).getMCSymbol();
2399e8d8bef9SDimitry Andric       break;
2400e8d8bef9SDimitry Andric     }
2401e8d8bef9SDimitry Andric 
2402e8d8bef9SDimitry Andric     if (!MF->hasCallSiteLandingPad(Sym))
2403e8d8bef9SDimitry Andric       continue;
2404e8d8bef9SDimitry Andric 
2405e8d8bef9SDimitry Andric     for (unsigned CSI : MF->getCallSiteLandingPad(Sym)) {
2406e8d8bef9SDimitry Andric       CallSiteNumToLPad[CSI].push_back(&MBB);
2407e8d8bef9SDimitry Andric       MaxCSNum = std::max(MaxCSNum, CSI);
2408e8d8bef9SDimitry Andric     }
2409e8d8bef9SDimitry Andric   }
2410e8d8bef9SDimitry Andric 
2411e8d8bef9SDimitry Andric   // Get an ordered list of the machine basic blocks for the jump table.
2412e8d8bef9SDimitry Andric   std::vector<MachineBasicBlock *> LPadList;
2413e8d8bef9SDimitry Andric   SmallPtrSet<MachineBasicBlock *, 32> InvokeBBs;
2414e8d8bef9SDimitry Andric   LPadList.reserve(CallSiteNumToLPad.size());
2415e8d8bef9SDimitry Andric 
2416e8d8bef9SDimitry Andric   for (unsigned CSI = 1; CSI <= MaxCSNum; ++CSI) {
2417e8d8bef9SDimitry Andric     for (auto &LP : CallSiteNumToLPad[CSI]) {
2418e8d8bef9SDimitry Andric       LPadList.push_back(LP);
2419e8d8bef9SDimitry Andric       InvokeBBs.insert(LP->pred_begin(), LP->pred_end());
2420e8d8bef9SDimitry Andric     }
2421e8d8bef9SDimitry Andric   }
2422e8d8bef9SDimitry Andric 
2423e8d8bef9SDimitry Andric   assert(!LPadList.empty() &&
2424e8d8bef9SDimitry Andric          "No landing pad destinations for the dispatch jump table!");
2425e8d8bef9SDimitry Andric 
2426e8d8bef9SDimitry Andric   // The %fn_context is allocated like below (from --print-after=sjljehprepare):
2427e8d8bef9SDimitry Andric   //   %fn_context = alloca { i8*, i64, [4 x i64], i8*, i8*, [5 x i8*] }
2428e8d8bef9SDimitry Andric   //
2429e8d8bef9SDimitry Andric   // This `[5 x i8*]` is jmpbuf, so jmpbuf[1] is FI+72.
2430e8d8bef9SDimitry Andric   // First `i64` is callsite, so callsite is FI+8.
2431e8d8bef9SDimitry Andric   static const int OffsetIC = 72;
2432e8d8bef9SDimitry Andric   static const int OffsetCS = 8;
2433e8d8bef9SDimitry Andric 
2434e8d8bef9SDimitry Andric   // Create the MBBs for the dispatch code like following:
2435e8d8bef9SDimitry Andric   //
2436e8d8bef9SDimitry Andric   // ThisMBB:
2437e8d8bef9SDimitry Andric   //   Prepare DispatchBB address and store it to buf[1].
2438e8d8bef9SDimitry Andric   //   ...
2439e8d8bef9SDimitry Andric   //
2440e8d8bef9SDimitry Andric   // DispatchBB:
2441e8d8bef9SDimitry Andric   //   %s15 = GETGOT iff isPositionIndependent
2442e8d8bef9SDimitry Andric   //   %callsite = load callsite
2443e8d8bef9SDimitry Andric   //   brgt.l.t #size of callsites, %callsite, DispContBB
2444e8d8bef9SDimitry Andric   //
2445e8d8bef9SDimitry Andric   // TrapBB:
2446e8d8bef9SDimitry Andric   //   Call abort.
2447e8d8bef9SDimitry Andric   //
2448e8d8bef9SDimitry Andric   // DispContBB:
2449e8d8bef9SDimitry Andric   //   %breg = address of jump table
2450e8d8bef9SDimitry Andric   //   %pc = load and calculate next pc from %breg and %callsite
2451e8d8bef9SDimitry Andric   //   jmp %pc
2452e8d8bef9SDimitry Andric 
2453e8d8bef9SDimitry Andric   // Shove the dispatch's address into the return slot in the function context.
2454e8d8bef9SDimitry Andric   MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
2455e8d8bef9SDimitry Andric   DispatchBB->setIsEHPad(true);
2456e8d8bef9SDimitry Andric 
2457e8d8bef9SDimitry Andric   // Trap BB will causes trap like `assert(0)`.
2458e8d8bef9SDimitry Andric   MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
2459e8d8bef9SDimitry Andric   DispatchBB->addSuccessor(TrapBB);
2460e8d8bef9SDimitry Andric 
2461e8d8bef9SDimitry Andric   MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
2462e8d8bef9SDimitry Andric   DispatchBB->addSuccessor(DispContBB);
2463e8d8bef9SDimitry Andric 
2464e8d8bef9SDimitry Andric   // Insert MBBs.
2465e8d8bef9SDimitry Andric   MF->push_back(DispatchBB);
2466e8d8bef9SDimitry Andric   MF->push_back(DispContBB);
2467e8d8bef9SDimitry Andric   MF->push_back(TrapBB);
2468e8d8bef9SDimitry Andric 
2469e8d8bef9SDimitry Andric   // Insert code to call abort in the TrapBB.
2470e8d8bef9SDimitry Andric   Register Abort = prepareSymbol(*TrapBB, TrapBB->end(), "abort", DL,
2471e8d8bef9SDimitry Andric                                  /* Local */ false, /* Call */ true);
2472e8d8bef9SDimitry Andric   BuildMI(TrapBB, DL, TII->get(VE::BSICrii), VE::SX10)
2473e8d8bef9SDimitry Andric       .addReg(Abort, getKillRegState(true))
2474e8d8bef9SDimitry Andric       .addImm(0)
2475e8d8bef9SDimitry Andric       .addImm(0);
2476e8d8bef9SDimitry Andric 
2477e8d8bef9SDimitry Andric   // Insert code into the entry block that creates and registers the function
2478e8d8bef9SDimitry Andric   // context.
2479e8d8bef9SDimitry Andric   setupEntryBlockForSjLj(MI, BB, DispatchBB, FI, OffsetIC);
2480e8d8bef9SDimitry Andric 
2481e8d8bef9SDimitry Andric   // Create the jump table and associated information
2482e8d8bef9SDimitry Andric   unsigned JTE = getJumpTableEncoding();
2483e8d8bef9SDimitry Andric   MachineJumpTableInfo *JTI = MF->getOrCreateJumpTableInfo(JTE);
2484e8d8bef9SDimitry Andric   unsigned MJTI = JTI->createJumpTableIndex(LPadList);
2485e8d8bef9SDimitry Andric 
2486e8d8bef9SDimitry Andric   const VERegisterInfo &RI = TII->getRegisterInfo();
2487e8d8bef9SDimitry Andric   // Add a register mask with no preserved registers.  This results in all
2488e8d8bef9SDimitry Andric   // registers being marked as clobbered.
2489e8d8bef9SDimitry Andric   BuildMI(DispatchBB, DL, TII->get(VE::NOP))
2490e8d8bef9SDimitry Andric       .addRegMask(RI.getNoPreservedMask());
2491e8d8bef9SDimitry Andric 
2492e8d8bef9SDimitry Andric   if (isPositionIndependent()) {
2493e8d8bef9SDimitry Andric     // Force to generate GETGOT, since current implementation doesn't store GOT
2494e8d8bef9SDimitry Andric     // register.
2495e8d8bef9SDimitry Andric     BuildMI(DispatchBB, DL, TII->get(VE::GETGOT), VE::SX15);
2496e8d8bef9SDimitry Andric   }
2497e8d8bef9SDimitry Andric 
2498e8d8bef9SDimitry Andric   // IReg is used as an index in a memory operand and therefore can't be SP
2499e8d8bef9SDimitry Andric   const TargetRegisterClass *RC = &VE::I64RegClass;
2500e8d8bef9SDimitry Andric   Register IReg = MRI.createVirtualRegister(RC);
2501e8d8bef9SDimitry Andric   addFrameReference(BuildMI(DispatchBB, DL, TII->get(VE::LDLZXrii), IReg), FI,
2502e8d8bef9SDimitry Andric                     OffsetCS);
2503e8d8bef9SDimitry Andric   if (LPadList.size() < 64) {
2504e8d8bef9SDimitry Andric     BuildMI(DispatchBB, DL, TII->get(VE::BRCFLir_t))
2505e8d8bef9SDimitry Andric         .addImm(VECC::CC_ILE)
2506e8d8bef9SDimitry Andric         .addImm(LPadList.size())
2507e8d8bef9SDimitry Andric         .addReg(IReg)
2508e8d8bef9SDimitry Andric         .addMBB(TrapBB);
2509e8d8bef9SDimitry Andric   } else {
2510e8d8bef9SDimitry Andric     assert(LPadList.size() <= 0x7FFFFFFF && "Too large Landing Pad!");
2511e8d8bef9SDimitry Andric     Register TmpReg = MRI.createVirtualRegister(RC);
2512e8d8bef9SDimitry Andric     BuildMI(DispatchBB, DL, TII->get(VE::LEAzii), TmpReg)
2513e8d8bef9SDimitry Andric         .addImm(0)
2514e8d8bef9SDimitry Andric         .addImm(0)
2515e8d8bef9SDimitry Andric         .addImm(LPadList.size());
2516e8d8bef9SDimitry Andric     BuildMI(DispatchBB, DL, TII->get(VE::BRCFLrr_t))
2517e8d8bef9SDimitry Andric         .addImm(VECC::CC_ILE)
2518e8d8bef9SDimitry Andric         .addReg(TmpReg, getKillRegState(true))
2519e8d8bef9SDimitry Andric         .addReg(IReg)
2520e8d8bef9SDimitry Andric         .addMBB(TrapBB);
2521e8d8bef9SDimitry Andric   }
2522e8d8bef9SDimitry Andric 
2523e8d8bef9SDimitry Andric   Register BReg = MRI.createVirtualRegister(RC);
2524e8d8bef9SDimitry Andric   Register Tmp1 = MRI.createVirtualRegister(RC);
2525e8d8bef9SDimitry Andric   Register Tmp2 = MRI.createVirtualRegister(RC);
2526e8d8bef9SDimitry Andric 
2527e8d8bef9SDimitry Andric   if (isPositionIndependent()) {
2528e8d8bef9SDimitry Andric     // Create following instructions for local linkage PIC code.
2529e8d8bef9SDimitry Andric     //     lea    %Tmp1, .LJTI0_0@gotoff_lo
2530e8d8bef9SDimitry Andric     //     and    %Tmp2, %Tmp1, (32)0
2531e8d8bef9SDimitry Andric     //     lea.sl %BReg, .LJTI0_0@gotoff_hi(%Tmp2, %s15) ; %s15 is GOT
2532e8d8bef9SDimitry Andric     BuildMI(DispContBB, DL, TII->get(VE::LEAzii), Tmp1)
2533e8d8bef9SDimitry Andric         .addImm(0)
2534e8d8bef9SDimitry Andric         .addImm(0)
2535e8d8bef9SDimitry Andric         .addJumpTableIndex(MJTI, VEMCExpr::VK_VE_GOTOFF_LO32);
2536e8d8bef9SDimitry Andric     BuildMI(DispContBB, DL, TII->get(VE::ANDrm), Tmp2)
2537e8d8bef9SDimitry Andric         .addReg(Tmp1, getKillRegState(true))
2538e8d8bef9SDimitry Andric         .addImm(M0(32));
2539e8d8bef9SDimitry Andric     BuildMI(DispContBB, DL, TII->get(VE::LEASLrri), BReg)
2540e8d8bef9SDimitry Andric         .addReg(VE::SX15)
2541e8d8bef9SDimitry Andric         .addReg(Tmp2, getKillRegState(true))
2542e8d8bef9SDimitry Andric         .addJumpTableIndex(MJTI, VEMCExpr::VK_VE_GOTOFF_HI32);
2543e8d8bef9SDimitry Andric   } else {
2544e8d8bef9SDimitry Andric     // Create following instructions for non-PIC code.
2545e8d8bef9SDimitry Andric     //     lea     %Tmp1, .LJTI0_0@lo
2546e8d8bef9SDimitry Andric     //     and     %Tmp2, %Tmp1, (32)0
2547e8d8bef9SDimitry Andric     //     lea.sl  %BReg, .LJTI0_0@hi(%Tmp2)
2548e8d8bef9SDimitry Andric     BuildMI(DispContBB, DL, TII->get(VE::LEAzii), Tmp1)
2549e8d8bef9SDimitry Andric         .addImm(0)
2550e8d8bef9SDimitry Andric         .addImm(0)
2551e8d8bef9SDimitry Andric         .addJumpTableIndex(MJTI, VEMCExpr::VK_VE_LO32);
2552e8d8bef9SDimitry Andric     BuildMI(DispContBB, DL, TII->get(VE::ANDrm), Tmp2)
2553e8d8bef9SDimitry Andric         .addReg(Tmp1, getKillRegState(true))
2554e8d8bef9SDimitry Andric         .addImm(M0(32));
2555e8d8bef9SDimitry Andric     BuildMI(DispContBB, DL, TII->get(VE::LEASLrii), BReg)
2556e8d8bef9SDimitry Andric         .addReg(Tmp2, getKillRegState(true))
2557e8d8bef9SDimitry Andric         .addImm(0)
2558e8d8bef9SDimitry Andric         .addJumpTableIndex(MJTI, VEMCExpr::VK_VE_HI32);
2559e8d8bef9SDimitry Andric   }
2560e8d8bef9SDimitry Andric 
2561e8d8bef9SDimitry Andric   switch (JTE) {
2562e8d8bef9SDimitry Andric   case MachineJumpTableInfo::EK_BlockAddress: {
2563e8d8bef9SDimitry Andric     // Generate simple block address code for no-PIC model.
2564e8d8bef9SDimitry Andric     //     sll %Tmp1, %IReg, 3
2565e8d8bef9SDimitry Andric     //     lds %TReg, 0(%Tmp1, %BReg)
2566e8d8bef9SDimitry Andric     //     bcfla %TReg
2567e8d8bef9SDimitry Andric 
2568e8d8bef9SDimitry Andric     Register TReg = MRI.createVirtualRegister(RC);
2569e8d8bef9SDimitry Andric     Register Tmp1 = MRI.createVirtualRegister(RC);
2570e8d8bef9SDimitry Andric 
2571e8d8bef9SDimitry Andric     BuildMI(DispContBB, DL, TII->get(VE::SLLri), Tmp1)
2572e8d8bef9SDimitry Andric         .addReg(IReg, getKillRegState(true))
2573e8d8bef9SDimitry Andric         .addImm(3);
2574e8d8bef9SDimitry Andric     BuildMI(DispContBB, DL, TII->get(VE::LDrri), TReg)
2575e8d8bef9SDimitry Andric         .addReg(BReg, getKillRegState(true))
2576e8d8bef9SDimitry Andric         .addReg(Tmp1, getKillRegState(true))
2577e8d8bef9SDimitry Andric         .addImm(0);
2578e8d8bef9SDimitry Andric     BuildMI(DispContBB, DL, TII->get(VE::BCFLari_t))
2579e8d8bef9SDimitry Andric         .addReg(TReg, getKillRegState(true))
2580e8d8bef9SDimitry Andric         .addImm(0);
2581e8d8bef9SDimitry Andric     break;
2582e8d8bef9SDimitry Andric   }
2583e8d8bef9SDimitry Andric   case MachineJumpTableInfo::EK_Custom32: {
2584e8d8bef9SDimitry Andric     // Generate block address code using differences from the function pointer
2585e8d8bef9SDimitry Andric     // for PIC model.
2586e8d8bef9SDimitry Andric     //     sll %Tmp1, %IReg, 2
2587e8d8bef9SDimitry Andric     //     ldl.zx %OReg, 0(%Tmp1, %BReg)
2588e8d8bef9SDimitry Andric     //     Prepare function address in BReg2.
2589e8d8bef9SDimitry Andric     //     adds.l %TReg, %BReg2, %OReg
2590e8d8bef9SDimitry Andric     //     bcfla %TReg
2591e8d8bef9SDimitry Andric 
2592e8d8bef9SDimitry Andric     assert(isPositionIndependent());
2593e8d8bef9SDimitry Andric     Register OReg = MRI.createVirtualRegister(RC);
2594e8d8bef9SDimitry Andric     Register TReg = MRI.createVirtualRegister(RC);
2595e8d8bef9SDimitry Andric     Register Tmp1 = MRI.createVirtualRegister(RC);
2596e8d8bef9SDimitry Andric 
2597e8d8bef9SDimitry Andric     BuildMI(DispContBB, DL, TII->get(VE::SLLri), Tmp1)
2598e8d8bef9SDimitry Andric         .addReg(IReg, getKillRegState(true))
2599e8d8bef9SDimitry Andric         .addImm(2);
2600e8d8bef9SDimitry Andric     BuildMI(DispContBB, DL, TII->get(VE::LDLZXrri), OReg)
2601e8d8bef9SDimitry Andric         .addReg(BReg, getKillRegState(true))
2602e8d8bef9SDimitry Andric         .addReg(Tmp1, getKillRegState(true))
2603e8d8bef9SDimitry Andric         .addImm(0);
2604e8d8bef9SDimitry Andric     Register BReg2 =
2605e8d8bef9SDimitry Andric         prepareSymbol(*DispContBB, DispContBB->end(),
2606e8d8bef9SDimitry Andric                       DispContBB->getParent()->getName(), DL, /* Local */ true);
2607e8d8bef9SDimitry Andric     BuildMI(DispContBB, DL, TII->get(VE::ADDSLrr), TReg)
2608e8d8bef9SDimitry Andric         .addReg(OReg, getKillRegState(true))
2609e8d8bef9SDimitry Andric         .addReg(BReg2, getKillRegState(true));
2610e8d8bef9SDimitry Andric     BuildMI(DispContBB, DL, TII->get(VE::BCFLari_t))
2611e8d8bef9SDimitry Andric         .addReg(TReg, getKillRegState(true))
2612e8d8bef9SDimitry Andric         .addImm(0);
2613e8d8bef9SDimitry Andric     break;
2614e8d8bef9SDimitry Andric   }
2615e8d8bef9SDimitry Andric   default:
2616e8d8bef9SDimitry Andric     llvm_unreachable("Unexpected jump table encoding");
2617e8d8bef9SDimitry Andric   }
2618e8d8bef9SDimitry Andric 
2619e8d8bef9SDimitry Andric   // Add the jump table entries as successors to the MBB.
2620e8d8bef9SDimitry Andric   SmallPtrSet<MachineBasicBlock *, 8> SeenMBBs;
2621e8d8bef9SDimitry Andric   for (auto &LP : LPadList)
2622e8d8bef9SDimitry Andric     if (SeenMBBs.insert(LP).second)
2623e8d8bef9SDimitry Andric       DispContBB->addSuccessor(LP);
2624e8d8bef9SDimitry Andric 
2625e8d8bef9SDimitry Andric   // N.B. the order the invoke BBs are processed in doesn't matter here.
2626e8d8bef9SDimitry Andric   SmallVector<MachineBasicBlock *, 64> MBBLPads;
2627e8d8bef9SDimitry Andric   const MCPhysReg *SavedRegs = MF->getRegInfo().getCalleeSavedRegs();
2628e8d8bef9SDimitry Andric   for (MachineBasicBlock *MBB : InvokeBBs) {
2629e8d8bef9SDimitry Andric     // Remove the landing pad successor from the invoke block and replace it
2630e8d8bef9SDimitry Andric     // with the new dispatch block.
2631e8d8bef9SDimitry Andric     // Keep a copy of Successors since it's modified inside the loop.
2632e8d8bef9SDimitry Andric     SmallVector<MachineBasicBlock *, 8> Successors(MBB->succ_rbegin(),
2633e8d8bef9SDimitry Andric                                                    MBB->succ_rend());
2634e8d8bef9SDimitry Andric     // FIXME: Avoid quadratic complexity.
2635bdd1243dSDimitry Andric     for (auto *MBBS : Successors) {
2636e8d8bef9SDimitry Andric       if (MBBS->isEHPad()) {
2637e8d8bef9SDimitry Andric         MBB->removeSuccessor(MBBS);
2638e8d8bef9SDimitry Andric         MBBLPads.push_back(MBBS);
2639e8d8bef9SDimitry Andric       }
2640e8d8bef9SDimitry Andric     }
2641e8d8bef9SDimitry Andric 
2642e8d8bef9SDimitry Andric     MBB->addSuccessor(DispatchBB);
2643e8d8bef9SDimitry Andric 
2644e8d8bef9SDimitry Andric     // Find the invoke call and mark all of the callee-saved registers as
2645e8d8bef9SDimitry Andric     // 'implicit defined' so that they're spilled.  This prevents code from
2646e8d8bef9SDimitry Andric     // moving instructions to before the EH block, where they will never be
2647e8d8bef9SDimitry Andric     // executed.
2648e8d8bef9SDimitry Andric     for (auto &II : reverse(*MBB)) {
2649e8d8bef9SDimitry Andric       if (!II.isCall())
2650e8d8bef9SDimitry Andric         continue;
2651e8d8bef9SDimitry Andric 
2652e8d8bef9SDimitry Andric       DenseMap<Register, bool> DefRegs;
2653e8d8bef9SDimitry Andric       for (auto &MOp : II.operands())
2654e8d8bef9SDimitry Andric         if (MOp.isReg())
2655e8d8bef9SDimitry Andric           DefRegs[MOp.getReg()] = true;
2656e8d8bef9SDimitry Andric 
2657e8d8bef9SDimitry Andric       MachineInstrBuilder MIB(*MF, &II);
2658e8d8bef9SDimitry Andric       for (unsigned RI = 0; SavedRegs[RI]; ++RI) {
2659e8d8bef9SDimitry Andric         Register Reg = SavedRegs[RI];
2660e8d8bef9SDimitry Andric         if (!DefRegs[Reg])
2661e8d8bef9SDimitry Andric           MIB.addReg(Reg, RegState::ImplicitDefine | RegState::Dead);
2662e8d8bef9SDimitry Andric       }
2663e8d8bef9SDimitry Andric 
2664e8d8bef9SDimitry Andric       break;
2665e8d8bef9SDimitry Andric     }
2666e8d8bef9SDimitry Andric   }
2667e8d8bef9SDimitry Andric 
2668e8d8bef9SDimitry Andric   // Mark all former landing pads as non-landing pads.  The dispatch is the only
2669e8d8bef9SDimitry Andric   // landing pad now.
2670e8d8bef9SDimitry Andric   for (auto &LP : MBBLPads)
2671e8d8bef9SDimitry Andric     LP->setIsEHPad(false);
2672e8d8bef9SDimitry Andric 
2673e8d8bef9SDimitry Andric   // The instruction is gone now.
2674e8d8bef9SDimitry Andric   MI.eraseFromParent();
2675e8d8bef9SDimitry Andric   return BB;
2676e8d8bef9SDimitry Andric }
2677e8d8bef9SDimitry Andric 
2678e8d8bef9SDimitry Andric MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr & MI,MachineBasicBlock * BB) const2679e8d8bef9SDimitry Andric VETargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
2680e8d8bef9SDimitry Andric                                               MachineBasicBlock *BB) const {
2681e8d8bef9SDimitry Andric   switch (MI.getOpcode()) {
2682e8d8bef9SDimitry Andric   default:
2683e8d8bef9SDimitry Andric     llvm_unreachable("Unknown Custom Instruction!");
2684e8d8bef9SDimitry Andric   case VE::EH_SjLj_LongJmp:
2685e8d8bef9SDimitry Andric     return emitEHSjLjLongJmp(MI, BB);
2686e8d8bef9SDimitry Andric   case VE::EH_SjLj_SetJmp:
2687e8d8bef9SDimitry Andric     return emitEHSjLjSetJmp(MI, BB);
2688e8d8bef9SDimitry Andric   case VE::EH_SjLj_Setup_Dispatch:
2689e8d8bef9SDimitry Andric     return emitSjLjDispatchBlock(MI, BB);
2690e8d8bef9SDimitry Andric   }
2691e8d8bef9SDimitry Andric }
2692e8d8bef9SDimitry Andric 
isSimm7(SDValue V)2693bdd1243dSDimitry Andric static bool isSimm7(SDValue V) {
2694bdd1243dSDimitry Andric   EVT VT = V.getValueType();
2695bdd1243dSDimitry Andric   if (VT.isVector())
2696bdd1243dSDimitry Andric     return false;
2697bdd1243dSDimitry Andric 
2698bdd1243dSDimitry Andric   if (VT.isInteger()) {
2699bdd1243dSDimitry Andric     if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(V))
2700bdd1243dSDimitry Andric       return isInt<7>(C->getSExtValue());
2701bdd1243dSDimitry Andric   } else if (VT.isFloatingPoint()) {
2702bdd1243dSDimitry Andric     if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(V)) {
2703bdd1243dSDimitry Andric       if (VT == MVT::f32 || VT == MVT::f64) {
2704bdd1243dSDimitry Andric         const APInt &Imm = C->getValueAPF().bitcastToAPInt();
2705bdd1243dSDimitry Andric         uint64_t Val = Imm.getSExtValue();
2706bdd1243dSDimitry Andric         if (Imm.getBitWidth() == 32)
2707bdd1243dSDimitry Andric           Val <<= 32; // Immediate value of float place at higher bits on VE.
2708bdd1243dSDimitry Andric         return isInt<7>(Val);
2709bdd1243dSDimitry Andric       }
2710bdd1243dSDimitry Andric     }
2711bdd1243dSDimitry Andric   }
2712bdd1243dSDimitry Andric   return false;
2713bdd1243dSDimitry Andric }
2714bdd1243dSDimitry Andric 
isMImm(SDValue V)2715bdd1243dSDimitry Andric static bool isMImm(SDValue V) {
2716bdd1243dSDimitry Andric   EVT VT = V.getValueType();
2717bdd1243dSDimitry Andric   if (VT.isVector())
2718bdd1243dSDimitry Andric     return false;
2719bdd1243dSDimitry Andric 
2720bdd1243dSDimitry Andric   if (VT.isInteger()) {
2721bdd1243dSDimitry Andric     if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(V))
2722bdd1243dSDimitry Andric       return isMImmVal(getImmVal(C));
2723bdd1243dSDimitry Andric   } else if (VT.isFloatingPoint()) {
2724bdd1243dSDimitry Andric     if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(V)) {
2725bdd1243dSDimitry Andric       if (VT == MVT::f32) {
2726bdd1243dSDimitry Andric         // Float value places at higher bits, so ignore lower 32 bits.
2727bdd1243dSDimitry Andric         return isMImm32Val(getFpImmVal(C) >> 32);
2728bdd1243dSDimitry Andric       } else if (VT == MVT::f64) {
2729bdd1243dSDimitry Andric         return isMImmVal(getFpImmVal(C));
2730bdd1243dSDimitry Andric       }
2731bdd1243dSDimitry Andric     }
2732bdd1243dSDimitry Andric   }
2733bdd1243dSDimitry Andric   return false;
2734bdd1243dSDimitry Andric }
2735bdd1243dSDimitry Andric 
decideComp(EVT SrcVT,ISD::CondCode CC)2736bdd1243dSDimitry Andric static unsigned decideComp(EVT SrcVT, ISD::CondCode CC) {
2737bdd1243dSDimitry Andric   if (SrcVT.isFloatingPoint()) {
2738bdd1243dSDimitry Andric     if (SrcVT == MVT::f128)
2739bdd1243dSDimitry Andric       return VEISD::CMPQ;
2740bdd1243dSDimitry Andric     return VEISD::CMPF;
2741bdd1243dSDimitry Andric   }
2742bdd1243dSDimitry Andric   return isSignedIntSetCC(CC) ? VEISD::CMPI : VEISD::CMPU;
2743bdd1243dSDimitry Andric }
2744bdd1243dSDimitry Andric 
decideCompType(EVT SrcVT)2745bdd1243dSDimitry Andric static EVT decideCompType(EVT SrcVT) {
2746bdd1243dSDimitry Andric   if (SrcVT == MVT::f128)
2747bdd1243dSDimitry Andric     return MVT::f64;
2748bdd1243dSDimitry Andric   return SrcVT;
2749bdd1243dSDimitry Andric }
2750bdd1243dSDimitry Andric 
safeWithoutCompWithNull(EVT SrcVT,ISD::CondCode CC,bool WithCMov)2751bdd1243dSDimitry Andric static bool safeWithoutCompWithNull(EVT SrcVT, ISD::CondCode CC,
2752bdd1243dSDimitry Andric                                     bool WithCMov) {
2753bdd1243dSDimitry Andric   if (SrcVT.isFloatingPoint()) {
2754bdd1243dSDimitry Andric     // For the case of floating point setcc, only unordered comparison
2755bdd1243dSDimitry Andric     // or general comparison with -enable-no-nans-fp-math option reach
2756bdd1243dSDimitry Andric     // here, so it is safe even if values are NaN.  Only f128 doesn't
2757bdd1243dSDimitry Andric     // safe since VE uses f64 result of f128 comparison.
2758bdd1243dSDimitry Andric     return SrcVT != MVT::f128;
2759bdd1243dSDimitry Andric   }
2760bdd1243dSDimitry Andric   if (isIntEqualitySetCC(CC)) {
2761bdd1243dSDimitry Andric     // For the case of equal or not equal, it is safe without comparison with 0.
2762bdd1243dSDimitry Andric     return true;
2763bdd1243dSDimitry Andric   }
2764bdd1243dSDimitry Andric   if (WithCMov) {
2765bdd1243dSDimitry Andric     // For the case of integer setcc with cmov, all signed comparison with 0
2766bdd1243dSDimitry Andric     // are safe.
2767bdd1243dSDimitry Andric     return isSignedIntSetCC(CC);
2768bdd1243dSDimitry Andric   }
2769bdd1243dSDimitry Andric   // For the case of integer setcc, only signed 64 bits comparison is safe.
2770bdd1243dSDimitry Andric   // For unsigned, "CMPU 0x80000000, 0" has to be greater than 0, but it becomes
2771bdd1243dSDimitry Andric   // less than 0 witout CMPU.  For 32 bits, other half of 32 bits are
2772bdd1243dSDimitry Andric   // uncoditional, so it is not safe too without CMPI..
2773bdd1243dSDimitry Andric   return isSignedIntSetCC(CC) && SrcVT == MVT::i64;
2774bdd1243dSDimitry Andric }
2775bdd1243dSDimitry Andric 
generateComparison(EVT VT,SDValue LHS,SDValue RHS,ISD::CondCode CC,bool WithCMov,const SDLoc & DL,SelectionDAG & DAG)2776bdd1243dSDimitry Andric static SDValue generateComparison(EVT VT, SDValue LHS, SDValue RHS,
2777bdd1243dSDimitry Andric                                   ISD::CondCode CC, bool WithCMov,
2778bdd1243dSDimitry Andric                                   const SDLoc &DL, SelectionDAG &DAG) {
2779bdd1243dSDimitry Andric   // Compare values.  If RHS is 0 and it is safe to calculate without
2780bdd1243dSDimitry Andric   // comparison, we don't generate an instruction for comparison.
2781bdd1243dSDimitry Andric   EVT CompVT = decideCompType(VT);
2782bdd1243dSDimitry Andric   if (CompVT == VT && safeWithoutCompWithNull(VT, CC, WithCMov) &&
2783bdd1243dSDimitry Andric       (isNullConstant(RHS) || isNullFPConstant(RHS))) {
2784bdd1243dSDimitry Andric     return LHS;
2785bdd1243dSDimitry Andric   }
2786bdd1243dSDimitry Andric   return DAG.getNode(decideComp(VT, CC), DL, CompVT, LHS, RHS);
2787bdd1243dSDimitry Andric }
2788bdd1243dSDimitry Andric 
combineSelect(SDNode * N,DAGCombinerInfo & DCI) const2789bdd1243dSDimitry Andric SDValue VETargetLowering::combineSelect(SDNode *N,
2790bdd1243dSDimitry Andric                                         DAGCombinerInfo &DCI) const {
2791bdd1243dSDimitry Andric   assert(N->getOpcode() == ISD::SELECT &&
2792bdd1243dSDimitry Andric          "Should be called with a SELECT node");
2793bdd1243dSDimitry Andric   ISD::CondCode CC = ISD::CondCode::SETNE;
2794bdd1243dSDimitry Andric   SDValue Cond = N->getOperand(0);
2795bdd1243dSDimitry Andric   SDValue True = N->getOperand(1);
2796bdd1243dSDimitry Andric   SDValue False = N->getOperand(2);
2797bdd1243dSDimitry Andric 
2798bdd1243dSDimitry Andric   // We handle only scalar SELECT.
2799bdd1243dSDimitry Andric   EVT VT = N->getValueType(0);
2800bdd1243dSDimitry Andric   if (VT.isVector())
2801bdd1243dSDimitry Andric     return SDValue();
2802bdd1243dSDimitry Andric 
2803bdd1243dSDimitry Andric   // Peform combineSelect after leagalize DAG.
2804bdd1243dSDimitry Andric   if (!DCI.isAfterLegalizeDAG())
2805bdd1243dSDimitry Andric     return SDValue();
2806bdd1243dSDimitry Andric 
2807bdd1243dSDimitry Andric   EVT VT0 = Cond.getValueType();
2808bdd1243dSDimitry Andric   if (isMImm(True)) {
2809bdd1243dSDimitry Andric     // VE's condition move can handle MImm in True clause, so nothing to do.
2810bdd1243dSDimitry Andric   } else if (isMImm(False)) {
2811bdd1243dSDimitry Andric     // VE's condition move can handle MImm in True clause, so swap True and
2812bdd1243dSDimitry Andric     // False clauses if False has MImm value.  And, update condition code.
2813bdd1243dSDimitry Andric     std::swap(True, False);
2814bdd1243dSDimitry Andric     CC = getSetCCInverse(CC, VT0);
2815bdd1243dSDimitry Andric   }
2816bdd1243dSDimitry Andric 
2817bdd1243dSDimitry Andric   SDLoc DL(N);
2818bdd1243dSDimitry Andric   SelectionDAG &DAG = DCI.DAG;
2819bdd1243dSDimitry Andric   VECC::CondCode VECCVal;
2820bdd1243dSDimitry Andric   if (VT0.isFloatingPoint()) {
2821bdd1243dSDimitry Andric     VECCVal = fpCondCode2Fcc(CC);
2822bdd1243dSDimitry Andric   } else {
2823bdd1243dSDimitry Andric     VECCVal = intCondCode2Icc(CC);
2824bdd1243dSDimitry Andric   }
2825bdd1243dSDimitry Andric   SDValue Ops[] = {Cond, True, False,
2826bdd1243dSDimitry Andric                    DAG.getConstant(VECCVal, DL, MVT::i32)};
2827bdd1243dSDimitry Andric   return DAG.getNode(VEISD::CMOV, DL, VT, Ops);
2828bdd1243dSDimitry Andric }
2829bdd1243dSDimitry Andric 
combineSelectCC(SDNode * N,DAGCombinerInfo & DCI) const2830bdd1243dSDimitry Andric SDValue VETargetLowering::combineSelectCC(SDNode *N,
2831bdd1243dSDimitry Andric                                           DAGCombinerInfo &DCI) const {
2832bdd1243dSDimitry Andric   assert(N->getOpcode() == ISD::SELECT_CC &&
2833bdd1243dSDimitry Andric          "Should be called with a SELECT_CC node");
2834bdd1243dSDimitry Andric   ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(4))->get();
2835bdd1243dSDimitry Andric   SDValue LHS = N->getOperand(0);
2836bdd1243dSDimitry Andric   SDValue RHS = N->getOperand(1);
2837bdd1243dSDimitry Andric   SDValue True = N->getOperand(2);
2838bdd1243dSDimitry Andric   SDValue False = N->getOperand(3);
2839bdd1243dSDimitry Andric 
2840bdd1243dSDimitry Andric   // We handle only scalar SELECT_CC.
2841bdd1243dSDimitry Andric   EVT VT = N->getValueType(0);
2842bdd1243dSDimitry Andric   if (VT.isVector())
2843bdd1243dSDimitry Andric     return SDValue();
2844bdd1243dSDimitry Andric 
2845bdd1243dSDimitry Andric   // Peform combineSelectCC after leagalize DAG.
2846bdd1243dSDimitry Andric   if (!DCI.isAfterLegalizeDAG())
2847bdd1243dSDimitry Andric     return SDValue();
2848bdd1243dSDimitry Andric 
2849bdd1243dSDimitry Andric   // We handle only i32/i64/f32/f64/f128 comparisons.
2850bdd1243dSDimitry Andric   EVT LHSVT = LHS.getValueType();
2851bdd1243dSDimitry Andric   assert(LHSVT == RHS.getValueType());
2852bdd1243dSDimitry Andric   switch (LHSVT.getSimpleVT().SimpleTy) {
2853bdd1243dSDimitry Andric   case MVT::i32:
2854bdd1243dSDimitry Andric   case MVT::i64:
2855bdd1243dSDimitry Andric   case MVT::f32:
2856bdd1243dSDimitry Andric   case MVT::f64:
2857bdd1243dSDimitry Andric   case MVT::f128:
2858bdd1243dSDimitry Andric     break;
2859bdd1243dSDimitry Andric   default:
2860bdd1243dSDimitry Andric     // Return SDValue to let llvm handle other types.
2861bdd1243dSDimitry Andric     return SDValue();
2862bdd1243dSDimitry Andric   }
2863bdd1243dSDimitry Andric 
2864bdd1243dSDimitry Andric   if (isMImm(RHS)) {
2865bdd1243dSDimitry Andric     // VE's comparison can handle MImm in RHS, so nothing to do.
2866bdd1243dSDimitry Andric   } else if (isSimm7(RHS)) {
2867bdd1243dSDimitry Andric     // VE's comparison can handle Simm7 in LHS, so swap LHS and RHS, and
2868bdd1243dSDimitry Andric     // update condition code.
2869bdd1243dSDimitry Andric     std::swap(LHS, RHS);
2870bdd1243dSDimitry Andric     CC = getSetCCSwappedOperands(CC);
2871bdd1243dSDimitry Andric   }
2872bdd1243dSDimitry Andric   if (isMImm(True)) {
2873bdd1243dSDimitry Andric     // VE's condition move can handle MImm in True clause, so nothing to do.
2874bdd1243dSDimitry Andric   } else if (isMImm(False)) {
2875bdd1243dSDimitry Andric     // VE's condition move can handle MImm in True clause, so swap True and
2876bdd1243dSDimitry Andric     // False clauses if False has MImm value.  And, update condition code.
2877bdd1243dSDimitry Andric     std::swap(True, False);
2878bdd1243dSDimitry Andric     CC = getSetCCInverse(CC, LHSVT);
2879bdd1243dSDimitry Andric   }
2880bdd1243dSDimitry Andric 
2881bdd1243dSDimitry Andric   SDLoc DL(N);
2882bdd1243dSDimitry Andric   SelectionDAG &DAG = DCI.DAG;
2883bdd1243dSDimitry Andric 
2884bdd1243dSDimitry Andric   bool WithCMov = true;
2885bdd1243dSDimitry Andric   SDValue CompNode = generateComparison(LHSVT, LHS, RHS, CC, WithCMov, DL, DAG);
2886bdd1243dSDimitry Andric 
2887bdd1243dSDimitry Andric   VECC::CondCode VECCVal;
2888bdd1243dSDimitry Andric   if (LHSVT.isFloatingPoint()) {
2889bdd1243dSDimitry Andric     VECCVal = fpCondCode2Fcc(CC);
2890bdd1243dSDimitry Andric   } else {
2891bdd1243dSDimitry Andric     VECCVal = intCondCode2Icc(CC);
2892bdd1243dSDimitry Andric   }
2893bdd1243dSDimitry Andric   SDValue Ops[] = {CompNode, True, False,
2894bdd1243dSDimitry Andric                    DAG.getConstant(VECCVal, DL, MVT::i32)};
2895bdd1243dSDimitry Andric   return DAG.getNode(VEISD::CMOV, DL, VT, Ops);
2896bdd1243dSDimitry Andric }
2897bdd1243dSDimitry Andric 
2898bdd1243dSDimitry Andric static bool isI32InsnAllUses(const SDNode *User, const SDNode *N);
isI32Insn(const SDNode * User,const SDNode * N)2899e8d8bef9SDimitry Andric static bool isI32Insn(const SDNode *User, const SDNode *N) {
2900e8d8bef9SDimitry Andric   switch (User->getOpcode()) {
2901e8d8bef9SDimitry Andric   default:
2902e8d8bef9SDimitry Andric     return false;
2903e8d8bef9SDimitry Andric   case ISD::ADD:
2904e8d8bef9SDimitry Andric   case ISD::SUB:
2905e8d8bef9SDimitry Andric   case ISD::MUL:
2906e8d8bef9SDimitry Andric   case ISD::SDIV:
2907e8d8bef9SDimitry Andric   case ISD::UDIV:
2908e8d8bef9SDimitry Andric   case ISD::SETCC:
2909e8d8bef9SDimitry Andric   case ISD::SMIN:
2910e8d8bef9SDimitry Andric   case ISD::SMAX:
2911e8d8bef9SDimitry Andric   case ISD::SHL:
2912e8d8bef9SDimitry Andric   case ISD::SRA:
2913e8d8bef9SDimitry Andric   case ISD::BSWAP:
2914e8d8bef9SDimitry Andric   case ISD::SINT_TO_FP:
2915e8d8bef9SDimitry Andric   case ISD::UINT_TO_FP:
2916e8d8bef9SDimitry Andric   case ISD::BR_CC:
2917e8d8bef9SDimitry Andric   case ISD::BITCAST:
2918e8d8bef9SDimitry Andric   case ISD::ATOMIC_CMP_SWAP:
2919e8d8bef9SDimitry Andric   case ISD::ATOMIC_SWAP:
2920bdd1243dSDimitry Andric   case VEISD::CMPU:
2921bdd1243dSDimitry Andric   case VEISD::CMPI:
2922e8d8bef9SDimitry Andric     return true;
2923e8d8bef9SDimitry Andric   case ISD::SRL:
2924e8d8bef9SDimitry Andric     if (N->getOperand(0).getOpcode() != ISD::SRL)
2925e8d8bef9SDimitry Andric       return true;
2926e8d8bef9SDimitry Andric     // (srl (trunc (srl ...))) may be optimized by combining srl, so
2927e8d8bef9SDimitry Andric     // doesn't optimize trunc now.
2928e8d8bef9SDimitry Andric     return false;
2929e8d8bef9SDimitry Andric   case ISD::SELECT_CC:
2930e8d8bef9SDimitry Andric     if (User->getOperand(2).getNode() != N &&
2931e8d8bef9SDimitry Andric         User->getOperand(3).getNode() != N)
2932e8d8bef9SDimitry Andric       return true;
2933bdd1243dSDimitry Andric     return isI32InsnAllUses(User, N);
2934bdd1243dSDimitry Andric   case VEISD::CMOV:
2935bdd1243dSDimitry Andric     // CMOV in (cmov (trunc ...), true, false, int-comparison) is safe.
2936bdd1243dSDimitry Andric     // However, trunc in true or false clauses is not safe.
2937bdd1243dSDimitry Andric     if (User->getOperand(1).getNode() != N &&
2938bdd1243dSDimitry Andric         User->getOperand(2).getNode() != N &&
2939bdd1243dSDimitry Andric         isa<ConstantSDNode>(User->getOperand(3))) {
2940*647cbc5dSDimitry Andric       VECC::CondCode VECCVal =
2941*647cbc5dSDimitry Andric           static_cast<VECC::CondCode>(User->getConstantOperandVal(3));
2942bdd1243dSDimitry Andric       return isIntVECondCode(VECCVal);
2943bdd1243dSDimitry Andric     }
2944bdd1243dSDimitry Andric     [[fallthrough]];
2945e8d8bef9SDimitry Andric   case ISD::AND:
2946e8d8bef9SDimitry Andric   case ISD::OR:
2947e8d8bef9SDimitry Andric   case ISD::XOR:
2948e8d8bef9SDimitry Andric   case ISD::SELECT:
2949e8d8bef9SDimitry Andric   case ISD::CopyToReg:
2950e8d8bef9SDimitry Andric     // Check all use of selections, bit operations, and copies.  If all of them
2951e8d8bef9SDimitry Andric     // are safe, optimize truncate to extract_subreg.
2952bdd1243dSDimitry Andric     return isI32InsnAllUses(User, N);
2953bdd1243dSDimitry Andric   }
2954bdd1243dSDimitry Andric }
2955bdd1243dSDimitry Andric 
isI32InsnAllUses(const SDNode * User,const SDNode * N)2956bdd1243dSDimitry Andric static bool isI32InsnAllUses(const SDNode *User, const SDNode *N) {
2957bdd1243dSDimitry Andric   // Check all use of User node.  If all of them are safe, optimize
2958bdd1243dSDimitry Andric   // truncate to extract_subreg.
2959349cc55cSDimitry Andric   for (const SDNode *U : User->uses()) {
2960349cc55cSDimitry Andric     switch (U->getOpcode()) {
2961e8d8bef9SDimitry Andric     default:
2962e8d8bef9SDimitry Andric       // If the use is an instruction which treats the source operand as i32,
2963e8d8bef9SDimitry Andric       // it is safe to avoid truncate here.
2964349cc55cSDimitry Andric       if (isI32Insn(U, N))
2965e8d8bef9SDimitry Andric         continue;
2966e8d8bef9SDimitry Andric       break;
2967e8d8bef9SDimitry Andric     case ISD::ANY_EXTEND:
2968e8d8bef9SDimitry Andric     case ISD::SIGN_EXTEND:
2969e8d8bef9SDimitry Andric     case ISD::ZERO_EXTEND: {
2970e8d8bef9SDimitry Andric       // Special optimizations to the combination of ext and trunc.
2971e8d8bef9SDimitry Andric       // (ext ... (select ... (trunc ...))) is safe to avoid truncate here
2972e8d8bef9SDimitry Andric       // since this truncate instruction clears higher 32 bits which is filled
2973e8d8bef9SDimitry Andric       // by one of ext instructions later.
2974e8d8bef9SDimitry Andric       assert(N->getValueType(0) == MVT::i32 &&
2975e8d8bef9SDimitry Andric              "find truncate to not i32 integer");
2976e8d8bef9SDimitry Andric       if (User->getOpcode() == ISD::SELECT_CC ||
2977bdd1243dSDimitry Andric           User->getOpcode() == ISD::SELECT || User->getOpcode() == VEISD::CMOV)
2978e8d8bef9SDimitry Andric         continue;
2979e8d8bef9SDimitry Andric       break;
2980e8d8bef9SDimitry Andric     }
2981e8d8bef9SDimitry Andric     }
2982e8d8bef9SDimitry Andric     return false;
2983e8d8bef9SDimitry Andric   }
2984e8d8bef9SDimitry Andric   return true;
2985e8d8bef9SDimitry Andric }
2986e8d8bef9SDimitry Andric 
2987e8d8bef9SDimitry Andric // Optimize TRUNCATE in DAG combining.  Optimizing it in CUSTOM lower is
2988e8d8bef9SDimitry Andric // sometime too early.  Optimizing it in DAG pattern matching in VEInstrInfo.td
2989e8d8bef9SDimitry Andric // is sometime too late.  So, doing it at here.
combineTRUNCATE(SDNode * N,DAGCombinerInfo & DCI) const2990e8d8bef9SDimitry Andric SDValue VETargetLowering::combineTRUNCATE(SDNode *N,
2991e8d8bef9SDimitry Andric                                           DAGCombinerInfo &DCI) const {
2992e8d8bef9SDimitry Andric   assert(N->getOpcode() == ISD::TRUNCATE &&
2993e8d8bef9SDimitry Andric          "Should be called with a TRUNCATE node");
2994e8d8bef9SDimitry Andric 
2995e8d8bef9SDimitry Andric   SelectionDAG &DAG = DCI.DAG;
2996e8d8bef9SDimitry Andric   SDLoc DL(N);
2997e8d8bef9SDimitry Andric   EVT VT = N->getValueType(0);
2998e8d8bef9SDimitry Andric 
2999e8d8bef9SDimitry Andric   // We prefer to do this when all types are legal.
3000e8d8bef9SDimitry Andric   if (!DCI.isAfterLegalizeDAG())
3001e8d8bef9SDimitry Andric     return SDValue();
3002e8d8bef9SDimitry Andric 
3003e8d8bef9SDimitry Andric   // Skip combine TRUNCATE atm if the operand of TRUNCATE might be a constant.
3004e8d8bef9SDimitry Andric   if (N->getOperand(0)->getOpcode() == ISD::SELECT_CC &&
3005e8d8bef9SDimitry Andric       isa<ConstantSDNode>(N->getOperand(0)->getOperand(0)) &&
3006e8d8bef9SDimitry Andric       isa<ConstantSDNode>(N->getOperand(0)->getOperand(1)))
3007e8d8bef9SDimitry Andric     return SDValue();
3008e8d8bef9SDimitry Andric 
3009e8d8bef9SDimitry Andric   // Check all use of this TRUNCATE.
3010349cc55cSDimitry Andric   for (const SDNode *User : N->uses()) {
3011e8d8bef9SDimitry Andric     // Make sure that we're not going to replace TRUNCATE for non i32
3012e8d8bef9SDimitry Andric     // instructions.
3013e8d8bef9SDimitry Andric     //
3014e8d8bef9SDimitry Andric     // FIXME: Although we could sometimes handle this, and it does occur in
3015e8d8bef9SDimitry Andric     // practice that one of the condition inputs to the select is also one of
3016e8d8bef9SDimitry Andric     // the outputs, we currently can't deal with this.
3017e8d8bef9SDimitry Andric     if (isI32Insn(User, N))
3018e8d8bef9SDimitry Andric       continue;
3019e8d8bef9SDimitry Andric 
3020e8d8bef9SDimitry Andric     return SDValue();
3021e8d8bef9SDimitry Andric   }
3022e8d8bef9SDimitry Andric 
3023e8d8bef9SDimitry Andric   SDValue SubI32 = DAG.getTargetConstant(VE::sub_i32, DL, MVT::i32);
3024e8d8bef9SDimitry Andric   return SDValue(DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, VT,
3025e8d8bef9SDimitry Andric                                     N->getOperand(0), SubI32),
3026e8d8bef9SDimitry Andric                  0);
3027e8d8bef9SDimitry Andric }
3028e8d8bef9SDimitry Andric 
PerformDAGCombine(SDNode * N,DAGCombinerInfo & DCI) const3029e8d8bef9SDimitry Andric SDValue VETargetLowering::PerformDAGCombine(SDNode *N,
3030e8d8bef9SDimitry Andric                                             DAGCombinerInfo &DCI) const {
3031e8d8bef9SDimitry Andric   switch (N->getOpcode()) {
3032e8d8bef9SDimitry Andric   default:
3033e8d8bef9SDimitry Andric     break;
3034bdd1243dSDimitry Andric   case ISD::SELECT:
3035bdd1243dSDimitry Andric     return combineSelect(N, DCI);
3036bdd1243dSDimitry Andric   case ISD::SELECT_CC:
3037bdd1243dSDimitry Andric     return combineSelectCC(N, DCI);
3038e8d8bef9SDimitry Andric   case ISD::TRUNCATE:
3039e8d8bef9SDimitry Andric     return combineTRUNCATE(N, DCI);
3040e8d8bef9SDimitry Andric   }
3041e8d8bef9SDimitry Andric 
3042e8d8bef9SDimitry Andric   return SDValue();
3043e8d8bef9SDimitry Andric }
3044e8d8bef9SDimitry Andric 
3045e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
3046e8d8bef9SDimitry Andric // VE Inline Assembly Support
3047e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
3048e8d8bef9SDimitry Andric 
3049e8d8bef9SDimitry Andric VETargetLowering::ConstraintType
getConstraintType(StringRef Constraint) const3050e8d8bef9SDimitry Andric VETargetLowering::getConstraintType(StringRef Constraint) const {
3051e8d8bef9SDimitry Andric   if (Constraint.size() == 1) {
3052e8d8bef9SDimitry Andric     switch (Constraint[0]) {
3053e8d8bef9SDimitry Andric     default:
3054e8d8bef9SDimitry Andric       break;
3055e8d8bef9SDimitry Andric     case 'v': // vector registers
3056e8d8bef9SDimitry Andric       return C_RegisterClass;
3057e8d8bef9SDimitry Andric     }
3058e8d8bef9SDimitry Andric   }
3059e8d8bef9SDimitry Andric   return TargetLowering::getConstraintType(Constraint);
3060e8d8bef9SDimitry Andric }
3061e8d8bef9SDimitry Andric 
3062e8d8bef9SDimitry Andric std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo * TRI,StringRef Constraint,MVT VT) const3063e8d8bef9SDimitry Andric VETargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
3064e8d8bef9SDimitry Andric                                                StringRef Constraint,
3065e8d8bef9SDimitry Andric                                                MVT VT) const {
3066e8d8bef9SDimitry Andric   const TargetRegisterClass *RC = nullptr;
3067e8d8bef9SDimitry Andric   if (Constraint.size() == 1) {
3068e8d8bef9SDimitry Andric     switch (Constraint[0]) {
3069e8d8bef9SDimitry Andric     default:
3070e8d8bef9SDimitry Andric       return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
3071e8d8bef9SDimitry Andric     case 'r':
3072e8d8bef9SDimitry Andric       RC = &VE::I64RegClass;
3073e8d8bef9SDimitry Andric       break;
3074e8d8bef9SDimitry Andric     case 'v':
3075e8d8bef9SDimitry Andric       RC = &VE::V64RegClass;
3076e8d8bef9SDimitry Andric       break;
3077e8d8bef9SDimitry Andric     }
3078e8d8bef9SDimitry Andric     return std::make_pair(0U, RC);
3079e8d8bef9SDimitry Andric   }
3080e8d8bef9SDimitry Andric 
3081e8d8bef9SDimitry Andric   return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
3082e8d8bef9SDimitry Andric }
3083e8d8bef9SDimitry Andric 
3084e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
3085e8d8bef9SDimitry Andric // VE Target Optimization Support
3086e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
3087e8d8bef9SDimitry Andric 
getMinimumJumpTableEntries() const3088e8d8bef9SDimitry Andric unsigned VETargetLowering::getMinimumJumpTableEntries() const {
3089e8d8bef9SDimitry Andric   // Specify 8 for PIC model to relieve the impact of PIC load instructions.
3090e8d8bef9SDimitry Andric   if (isJumpTableRelative())
3091e8d8bef9SDimitry Andric     return 8;
3092e8d8bef9SDimitry Andric 
3093e8d8bef9SDimitry Andric   return TargetLowering::getMinimumJumpTableEntries();
3094e8d8bef9SDimitry Andric }
3095e8d8bef9SDimitry Andric 
hasAndNot(SDValue Y) const3096e8d8bef9SDimitry Andric bool VETargetLowering::hasAndNot(SDValue Y) const {
3097e8d8bef9SDimitry Andric   EVT VT = Y.getValueType();
3098e8d8bef9SDimitry Andric 
3099e8d8bef9SDimitry Andric   // VE doesn't have vector and not instruction.
3100e8d8bef9SDimitry Andric   if (VT.isVector())
3101e8d8bef9SDimitry Andric     return false;
3102e8d8bef9SDimitry Andric 
3103e8d8bef9SDimitry Andric   // VE allows different immediate values for X and Y where ~X & Y.
3104e8d8bef9SDimitry Andric   // Only simm7 works for X, and only mimm works for Y on VE.  However, this
3105e8d8bef9SDimitry Andric   // function is used to check whether an immediate value is OK for and-not
3106e8d8bef9SDimitry Andric   // instruction as both X and Y.  Generating additional instruction to
3107e8d8bef9SDimitry Andric   // retrieve an immediate value is no good since the purpose of this
3108e8d8bef9SDimitry Andric   // function is to convert a series of 3 instructions to another series of
3109e8d8bef9SDimitry Andric   // 3 instructions with better parallelism.  Therefore, we return false
3110e8d8bef9SDimitry Andric   // for all immediate values now.
3111e8d8bef9SDimitry Andric   // FIXME: Change hasAndNot function to have two operands to make it work
3112e8d8bef9SDimitry Andric   //        correctly with Aurora VE.
3113e8d8bef9SDimitry Andric   if (isa<ConstantSDNode>(Y))
3114e8d8bef9SDimitry Andric     return false;
3115e8d8bef9SDimitry Andric 
3116e8d8bef9SDimitry Andric   // It's ok for generic registers.
3117e8d8bef9SDimitry Andric   return true;
3118e8d8bef9SDimitry Andric }
3119e8d8bef9SDimitry Andric 
lowerEXTRACT_VECTOR_ELT(SDValue Op,SelectionDAG & DAG) const3120e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerEXTRACT_VECTOR_ELT(SDValue Op,
3121e8d8bef9SDimitry Andric                                                   SelectionDAG &DAG) const {
3122e8d8bef9SDimitry Andric   assert(Op.getOpcode() == ISD::EXTRACT_VECTOR_ELT && "Unknown opcode!");
3123e8d8bef9SDimitry Andric   MVT VT = Op.getOperand(0).getSimpleValueType();
3124e8d8bef9SDimitry Andric 
3125e8d8bef9SDimitry Andric   // Special treatment for packed V64 types.
3126e8d8bef9SDimitry Andric   assert(VT == MVT::v512i32 || VT == MVT::v512f32);
3127fe6060f1SDimitry Andric   (void)VT;
3128e8d8bef9SDimitry Andric   // Example of codes:
3129e8d8bef9SDimitry Andric   //   %packed_v = extractelt %vr, %idx / 2
3130e8d8bef9SDimitry Andric   //   %v = %packed_v >> (%idx % 2 * 32)
3131e8d8bef9SDimitry Andric   //   %res = %v & 0xffffffff
3132e8d8bef9SDimitry Andric 
3133e8d8bef9SDimitry Andric   SDValue Vec = Op.getOperand(0);
3134e8d8bef9SDimitry Andric   SDValue Idx = Op.getOperand(1);
3135e8d8bef9SDimitry Andric   SDLoc DL(Op);
3136e8d8bef9SDimitry Andric   SDValue Result = Op;
313704eeddc0SDimitry Andric   if (false /* Idx->isConstant() */) {
3138e8d8bef9SDimitry Andric     // TODO: optimized implementation using constant values
3139e8d8bef9SDimitry Andric   } else {
3140e8d8bef9SDimitry Andric     SDValue Const1 = DAG.getConstant(1, DL, MVT::i64);
3141e8d8bef9SDimitry Andric     SDValue HalfIdx = DAG.getNode(ISD::SRL, DL, MVT::i64, {Idx, Const1});
3142e8d8bef9SDimitry Andric     SDValue PackedElt =
3143e8d8bef9SDimitry Andric         SDValue(DAG.getMachineNode(VE::LVSvr, DL, MVT::i64, {Vec, HalfIdx}), 0);
3144e8d8bef9SDimitry Andric     SDValue AndIdx = DAG.getNode(ISD::AND, DL, MVT::i64, {Idx, Const1});
3145e8d8bef9SDimitry Andric     SDValue Shift = DAG.getNode(ISD::XOR, DL, MVT::i64, {AndIdx, Const1});
3146e8d8bef9SDimitry Andric     SDValue Const5 = DAG.getConstant(5, DL, MVT::i64);
3147e8d8bef9SDimitry Andric     Shift = DAG.getNode(ISD::SHL, DL, MVT::i64, {Shift, Const5});
3148e8d8bef9SDimitry Andric     PackedElt = DAG.getNode(ISD::SRL, DL, MVT::i64, {PackedElt, Shift});
3149e8d8bef9SDimitry Andric     SDValue Mask = DAG.getConstant(0xFFFFFFFFL, DL, MVT::i64);
3150e8d8bef9SDimitry Andric     PackedElt = DAG.getNode(ISD::AND, DL, MVT::i64, {PackedElt, Mask});
3151e8d8bef9SDimitry Andric     SDValue SubI32 = DAG.getTargetConstant(VE::sub_i32, DL, MVT::i32);
3152e8d8bef9SDimitry Andric     Result = SDValue(DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL,
3153e8d8bef9SDimitry Andric                                         MVT::i32, PackedElt, SubI32),
3154e8d8bef9SDimitry Andric                      0);
3155e8d8bef9SDimitry Andric 
3156e8d8bef9SDimitry Andric     if (Op.getSimpleValueType() == MVT::f32) {
3157e8d8bef9SDimitry Andric       Result = DAG.getBitcast(MVT::f32, Result);
3158e8d8bef9SDimitry Andric     } else {
3159e8d8bef9SDimitry Andric       assert(Op.getSimpleValueType() == MVT::i32);
3160e8d8bef9SDimitry Andric     }
3161e8d8bef9SDimitry Andric   }
3162e8d8bef9SDimitry Andric   return Result;
3163e8d8bef9SDimitry Andric }
3164e8d8bef9SDimitry Andric 
lowerINSERT_VECTOR_ELT(SDValue Op,SelectionDAG & DAG) const3165e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerINSERT_VECTOR_ELT(SDValue Op,
3166e8d8bef9SDimitry Andric                                                  SelectionDAG &DAG) const {
3167e8d8bef9SDimitry Andric   assert(Op.getOpcode() == ISD::INSERT_VECTOR_ELT && "Unknown opcode!");
3168e8d8bef9SDimitry Andric   MVT VT = Op.getOperand(0).getSimpleValueType();
3169e8d8bef9SDimitry Andric 
3170e8d8bef9SDimitry Andric   // Special treatment for packed V64 types.
3171e8d8bef9SDimitry Andric   assert(VT == MVT::v512i32 || VT == MVT::v512f32);
3172fe6060f1SDimitry Andric   (void)VT;
3173e8d8bef9SDimitry Andric   // The v512i32 and v512f32 starts from upper bits (0..31).  This "upper
3174e8d8bef9SDimitry Andric   // bits" required `val << 32` from C implementation's point of view.
3175e8d8bef9SDimitry Andric   //
3176e8d8bef9SDimitry Andric   // Example of codes:
3177e8d8bef9SDimitry Andric   //   %packed_elt = extractelt %vr, (%idx >> 1)
3178e8d8bef9SDimitry Andric   //   %shift = ((%idx & 1) ^ 1) << 5
3179e8d8bef9SDimitry Andric   //   %packed_elt &= 0xffffffff00000000 >> shift
3180e8d8bef9SDimitry Andric   //   %packed_elt |= (zext %val) << shift
3181e8d8bef9SDimitry Andric   //   %vr = insertelt %vr, %packed_elt, (%idx >> 1)
3182e8d8bef9SDimitry Andric 
3183e8d8bef9SDimitry Andric   SDLoc DL(Op);
3184e8d8bef9SDimitry Andric   SDValue Vec = Op.getOperand(0);
3185e8d8bef9SDimitry Andric   SDValue Val = Op.getOperand(1);
3186e8d8bef9SDimitry Andric   SDValue Idx = Op.getOperand(2);
3187e8d8bef9SDimitry Andric   if (Idx.getSimpleValueType() == MVT::i32)
3188e8d8bef9SDimitry Andric     Idx = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, Idx);
3189e8d8bef9SDimitry Andric   if (Val.getSimpleValueType() == MVT::f32)
3190e8d8bef9SDimitry Andric     Val = DAG.getBitcast(MVT::i32, Val);
3191e8d8bef9SDimitry Andric   assert(Val.getSimpleValueType() == MVT::i32);
3192e8d8bef9SDimitry Andric   Val = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, Val);
3193e8d8bef9SDimitry Andric 
3194e8d8bef9SDimitry Andric   SDValue Result = Op;
319504eeddc0SDimitry Andric   if (false /* Idx->isConstant()*/) {
3196e8d8bef9SDimitry Andric     // TODO: optimized implementation using constant values
3197e8d8bef9SDimitry Andric   } else {
3198e8d8bef9SDimitry Andric     SDValue Const1 = DAG.getConstant(1, DL, MVT::i64);
3199e8d8bef9SDimitry Andric     SDValue HalfIdx = DAG.getNode(ISD::SRL, DL, MVT::i64, {Idx, Const1});
3200e8d8bef9SDimitry Andric     SDValue PackedElt =
3201e8d8bef9SDimitry Andric         SDValue(DAG.getMachineNode(VE::LVSvr, DL, MVT::i64, {Vec, HalfIdx}), 0);
3202e8d8bef9SDimitry Andric     SDValue AndIdx = DAG.getNode(ISD::AND, DL, MVT::i64, {Idx, Const1});
3203e8d8bef9SDimitry Andric     SDValue Shift = DAG.getNode(ISD::XOR, DL, MVT::i64, {AndIdx, Const1});
3204e8d8bef9SDimitry Andric     SDValue Const5 = DAG.getConstant(5, DL, MVT::i64);
3205e8d8bef9SDimitry Andric     Shift = DAG.getNode(ISD::SHL, DL, MVT::i64, {Shift, Const5});
3206e8d8bef9SDimitry Andric     SDValue Mask = DAG.getConstant(0xFFFFFFFF00000000L, DL, MVT::i64);
3207e8d8bef9SDimitry Andric     Mask = DAG.getNode(ISD::SRL, DL, MVT::i64, {Mask, Shift});
3208e8d8bef9SDimitry Andric     PackedElt = DAG.getNode(ISD::AND, DL, MVT::i64, {PackedElt, Mask});
3209e8d8bef9SDimitry Andric     Val = DAG.getNode(ISD::SHL, DL, MVT::i64, {Val, Shift});
3210e8d8bef9SDimitry Andric     PackedElt = DAG.getNode(ISD::OR, DL, MVT::i64, {PackedElt, Val});
3211e8d8bef9SDimitry Andric     Result =
3212e8d8bef9SDimitry Andric         SDValue(DAG.getMachineNode(VE::LSVrr_v, DL, Vec.getSimpleValueType(),
3213e8d8bef9SDimitry Andric                                    {HalfIdx, PackedElt, Vec}),
3214e8d8bef9SDimitry Andric                 0);
3215e8d8bef9SDimitry Andric   }
3216e8d8bef9SDimitry Andric   return Result;
3217e8d8bef9SDimitry Andric }
3218