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 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 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 67480093f4SDimitry 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 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 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 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 367480093f4SDimitry 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 441480093f4SDimitry 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 462*0fca6ea1SDimitry Andric for (const CCValAssign &VA : ArgLocs) { 463e8d8bef9SDimitry Andric assert(!VA.needsCustom() && "Unexpected custom lowering"); 4645ffd83dbSDimitry Andric if (VA.isRegLoc()) { 4655ffd83dbSDimitry Andric // This argument is passed in a register. 4665ffd83dbSDimitry Andric // All integer register arguments are promoted by the caller to i64. 4675ffd83dbSDimitry Andric 4685ffd83dbSDimitry Andric // Create a virtual register for the promoted live-in value. 46904eeddc0SDimitry Andric Register VReg = 4705ffd83dbSDimitry Andric MF.addLiveIn(VA.getLocReg(), getRegClassFor(VA.getLocVT())); 4715ffd83dbSDimitry Andric SDValue Arg = DAG.getCopyFromReg(Chain, DL, VReg, VA.getLocVT()); 4725ffd83dbSDimitry Andric 4735ffd83dbSDimitry Andric // The caller promoted the argument, so insert an Assert?ext SDNode so we 4745ffd83dbSDimitry Andric // won't promote the value again in this function. 4755ffd83dbSDimitry Andric switch (VA.getLocInfo()) { 4765ffd83dbSDimitry Andric case CCValAssign::SExt: 4775ffd83dbSDimitry Andric Arg = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Arg, 4785ffd83dbSDimitry Andric DAG.getValueType(VA.getValVT())); 4795ffd83dbSDimitry Andric break; 4805ffd83dbSDimitry Andric case CCValAssign::ZExt: 4815ffd83dbSDimitry Andric Arg = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Arg, 4825ffd83dbSDimitry Andric DAG.getValueType(VA.getValVT())); 4835ffd83dbSDimitry Andric break; 484e8d8bef9SDimitry Andric case CCValAssign::BCvt: { 485e8d8bef9SDimitry Andric // Extract a float argument from i64 with padding. 486e8d8bef9SDimitry Andric // 63 31 0 487e8d8bef9SDimitry Andric // +------+------+ 488e8d8bef9SDimitry Andric // | float| 0 | 489e8d8bef9SDimitry Andric // +------+------+ 490e8d8bef9SDimitry Andric assert(VA.getLocVT() == MVT::i64); 491e8d8bef9SDimitry Andric assert(VA.getValVT() == MVT::f32); 492e8d8bef9SDimitry Andric SDValue Sub_f32 = DAG.getTargetConstant(VE::sub_f32, DL, MVT::i32); 493e8d8bef9SDimitry Andric Arg = SDValue(DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, 494e8d8bef9SDimitry Andric MVT::f32, Arg, Sub_f32), 495e8d8bef9SDimitry Andric 0); 496e8d8bef9SDimitry Andric break; 497e8d8bef9SDimitry Andric } 4985ffd83dbSDimitry Andric default: 4995ffd83dbSDimitry Andric break; 5005ffd83dbSDimitry Andric } 5015ffd83dbSDimitry Andric 5025ffd83dbSDimitry Andric // Truncate the register down to the argument type. 5035ffd83dbSDimitry Andric if (VA.isExtInLoc()) 5045ffd83dbSDimitry Andric Arg = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Arg); 5055ffd83dbSDimitry Andric 5065ffd83dbSDimitry Andric InVals.push_back(Arg); 5075ffd83dbSDimitry Andric continue; 5085ffd83dbSDimitry Andric } 5095ffd83dbSDimitry Andric 5105ffd83dbSDimitry Andric // The registers are exhausted. This argument was passed on the stack. 5115ffd83dbSDimitry Andric assert(VA.isMemLoc()); 5125ffd83dbSDimitry Andric // The CC_VE_Full/Half functions compute stack offsets relative to the 513e8d8bef9SDimitry Andric // beginning of the arguments area at %fp + the size of reserved area. 5145ffd83dbSDimitry Andric unsigned Offset = VA.getLocMemOffset() + ArgsBaseOffset; 5155ffd83dbSDimitry Andric unsigned ValSize = VA.getValVT().getSizeInBits() / 8; 516e8d8bef9SDimitry Andric 517e8d8bef9SDimitry Andric // Adjust offset for a float argument by adding 4 since the argument is 518e8d8bef9SDimitry Andric // stored in 8 bytes buffer with offset like below. LLVM generates 519e8d8bef9SDimitry Andric // 4 bytes load instruction, so need to adjust offset here. This 520e8d8bef9SDimitry Andric // adjustment is required in only LowerFormalArguments. In LowerCall, 521e8d8bef9SDimitry Andric // a float argument is converted to i64 first, and stored as 8 bytes 522e8d8bef9SDimitry Andric // data, which is required by ABI, so no need for adjustment. 523e8d8bef9SDimitry Andric // 0 4 524e8d8bef9SDimitry Andric // +------+------+ 525e8d8bef9SDimitry Andric // | empty| float| 526e8d8bef9SDimitry Andric // +------+------+ 527e8d8bef9SDimitry Andric if (VA.getValVT() == MVT::f32) 528e8d8bef9SDimitry Andric Offset += 4; 529e8d8bef9SDimitry Andric 5305ffd83dbSDimitry Andric int FI = MF.getFrameInfo().CreateFixedObject(ValSize, Offset, true); 5315ffd83dbSDimitry Andric InVals.push_back( 5325ffd83dbSDimitry Andric DAG.getLoad(VA.getValVT(), DL, Chain, 5335ffd83dbSDimitry Andric DAG.getFrameIndex(FI, getPointerTy(MF.getDataLayout())), 5345ffd83dbSDimitry Andric MachinePointerInfo::getFixedStack(MF, FI))); 5355ffd83dbSDimitry Andric } 5365ffd83dbSDimitry Andric 5375ffd83dbSDimitry Andric if (!IsVarArg) 5385ffd83dbSDimitry Andric return Chain; 5395ffd83dbSDimitry Andric 5405ffd83dbSDimitry Andric // This function takes variable arguments, some of which may have been passed 5415ffd83dbSDimitry Andric // in registers %s0-%s8. 5425ffd83dbSDimitry Andric // 5435ffd83dbSDimitry Andric // The va_start intrinsic needs to know the offset to the first variable 5445ffd83dbSDimitry Andric // argument. 5455ffd83dbSDimitry Andric // TODO: need to calculate offset correctly once we support f128. 5465ffd83dbSDimitry Andric unsigned ArgOffset = ArgLocs.size() * 8; 5475ffd83dbSDimitry Andric VEMachineFunctionInfo *FuncInfo = MF.getInfo<VEMachineFunctionInfo>(); 548e8d8bef9SDimitry Andric // Skip the reserved area at the top of stack. 5495ffd83dbSDimitry Andric FuncInfo->setVarArgsFrameOffset(ArgOffset + ArgsBaseOffset); 5505ffd83dbSDimitry Andric 551480093f4SDimitry Andric return Chain; 552480093f4SDimitry Andric } 553480093f4SDimitry Andric 554480093f4SDimitry Andric // FIXME? Maybe this could be a TableGen attribute on some registers and 555480093f4SDimitry Andric // this table could be generated automatically from RegInfo. 556480093f4SDimitry Andric Register VETargetLowering::getRegisterByName(const char *RegName, LLT VT, 557480093f4SDimitry Andric const MachineFunction &MF) const { 558480093f4SDimitry Andric Register Reg = StringSwitch<Register>(RegName) 559480093f4SDimitry Andric .Case("sp", VE::SX11) // Stack pointer 560480093f4SDimitry Andric .Case("fp", VE::SX9) // Frame pointer 561480093f4SDimitry Andric .Case("sl", VE::SX8) // Stack limit 5625ffd83dbSDimitry Andric .Case("lr", VE::SX10) // Link register 563480093f4SDimitry Andric .Case("tp", VE::SX14) // Thread pointer 564480093f4SDimitry Andric .Case("outer", VE::SX12) // Outer regiser 565480093f4SDimitry Andric .Case("info", VE::SX17) // Info area register 566480093f4SDimitry Andric .Case("got", VE::SX15) // Global offset table register 567480093f4SDimitry Andric .Case("plt", VE::SX16) // Procedure linkage table register 568480093f4SDimitry Andric .Default(0); 569480093f4SDimitry Andric 570480093f4SDimitry Andric if (Reg) 571480093f4SDimitry Andric return Reg; 572480093f4SDimitry Andric 573480093f4SDimitry Andric report_fatal_error("Invalid register name global variable"); 574480093f4SDimitry Andric } 575480093f4SDimitry Andric 576480093f4SDimitry Andric //===----------------------------------------------------------------------===// 577480093f4SDimitry Andric // TargetLowering Implementation 578480093f4SDimitry Andric //===----------------------------------------------------------------------===// 579480093f4SDimitry Andric 5805ffd83dbSDimitry Andric SDValue VETargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, 5815ffd83dbSDimitry Andric SmallVectorImpl<SDValue> &InVals) const { 5825ffd83dbSDimitry Andric SelectionDAG &DAG = CLI.DAG; 5835ffd83dbSDimitry Andric SDLoc DL = CLI.DL; 5845ffd83dbSDimitry Andric SDValue Chain = CLI.Chain; 5855ffd83dbSDimitry Andric auto PtrVT = getPointerTy(DAG.getDataLayout()); 5865ffd83dbSDimitry Andric 5875ffd83dbSDimitry Andric // VE target does not yet support tail call optimization. 5885ffd83dbSDimitry Andric CLI.IsTailCall = false; 5895ffd83dbSDimitry Andric 5905ffd83dbSDimitry Andric // Get the base offset of the outgoing arguments stack space. 591e8d8bef9SDimitry Andric unsigned ArgsBaseOffset = Subtarget->getRsaSize(); 5925ffd83dbSDimitry Andric // Get the size of the preserved arguments area 5935ffd83dbSDimitry Andric unsigned ArgsPreserved = 8 * 8u; 5945ffd83dbSDimitry Andric 5955ffd83dbSDimitry Andric // Analyze operands of the call, assigning locations to each operand. 5965ffd83dbSDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 5975ffd83dbSDimitry Andric CCState CCInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), ArgLocs, 5985ffd83dbSDimitry Andric *DAG.getContext()); 5995ffd83dbSDimitry Andric // Allocate the preserved area first. 6005ffd83dbSDimitry Andric CCInfo.AllocateStack(ArgsPreserved, Align(8)); 6015ffd83dbSDimitry Andric // We already allocated the preserved area, so the stack offset computed 6025ffd83dbSDimitry Andric // by CC_VE would be correct now. 603e8d8bef9SDimitry Andric CCInfo.AnalyzeCallOperands(CLI.Outs, getParamCC(CLI.CallConv, false)); 6045ffd83dbSDimitry Andric 6055ffd83dbSDimitry Andric // VE requires to use both register and stack for varargs or no-prototyped 6065ffd83dbSDimitry Andric // functions. 6075ffd83dbSDimitry Andric bool UseBoth = CLI.IsVarArg; 6085ffd83dbSDimitry Andric 6095ffd83dbSDimitry Andric // Analyze operands again if it is required to store BOTH. 6105ffd83dbSDimitry Andric SmallVector<CCValAssign, 16> ArgLocs2; 6115ffd83dbSDimitry Andric CCState CCInfo2(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), 6125ffd83dbSDimitry Andric ArgLocs2, *DAG.getContext()); 6135ffd83dbSDimitry Andric if (UseBoth) 614e8d8bef9SDimitry Andric CCInfo2.AnalyzeCallOperands(CLI.Outs, getParamCC(CLI.CallConv, true)); 6155ffd83dbSDimitry Andric 6165ffd83dbSDimitry Andric // Get the size of the outgoing arguments stack space requirement. 61706c3fb27SDimitry Andric unsigned ArgsSize = CCInfo.getStackSize(); 6185ffd83dbSDimitry Andric 6195ffd83dbSDimitry Andric // Keep stack frames 16-byte aligned. 6205ffd83dbSDimitry Andric ArgsSize = alignTo(ArgsSize, 16); 6215ffd83dbSDimitry Andric 6225ffd83dbSDimitry Andric // Adjust the stack pointer to make room for the arguments. 6235ffd83dbSDimitry Andric // FIXME: Use hasReservedCallFrame to avoid %sp adjustments around all calls 6245ffd83dbSDimitry Andric // with more than 6 arguments. 6255ffd83dbSDimitry Andric Chain = DAG.getCALLSEQ_START(Chain, ArgsSize, 0, DL); 6265ffd83dbSDimitry Andric 6275ffd83dbSDimitry Andric // Collect the set of registers to pass to the function and their values. 6285ffd83dbSDimitry Andric // This will be emitted as a sequence of CopyToReg nodes glued to the call 6295ffd83dbSDimitry Andric // instruction. 6305ffd83dbSDimitry Andric SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; 6315ffd83dbSDimitry Andric 6325ffd83dbSDimitry Andric // Collect chains from all the memory opeations that copy arguments to the 6335ffd83dbSDimitry Andric // stack. They must follow the stack pointer adjustment above and precede the 6345ffd83dbSDimitry Andric // call instruction itself. 6355ffd83dbSDimitry Andric SmallVector<SDValue, 8> MemOpChains; 6365ffd83dbSDimitry Andric 6375ffd83dbSDimitry Andric // VE needs to get address of callee function in a register 6385ffd83dbSDimitry Andric // So, prepare to copy it to SX12 here. 6395ffd83dbSDimitry Andric 6405ffd83dbSDimitry Andric // If the callee is a GlobalAddress node (quite common, every direct call is) 6415ffd83dbSDimitry Andric // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. 6425ffd83dbSDimitry Andric // Likewise ExternalSymbol -> TargetExternalSymbol. 6435ffd83dbSDimitry Andric SDValue Callee = CLI.Callee; 6445ffd83dbSDimitry Andric 6455ffd83dbSDimitry Andric bool IsPICCall = isPositionIndependent(); 6465ffd83dbSDimitry Andric 6475ffd83dbSDimitry Andric // PC-relative references to external symbols should go through $stub. 6485ffd83dbSDimitry Andric // If so, we need to prepare GlobalBaseReg first. 6495ffd83dbSDimitry Andric const TargetMachine &TM = DAG.getTarget(); 6505ffd83dbSDimitry Andric const GlobalValue *GV = nullptr; 6515ffd83dbSDimitry Andric auto *CalleeG = dyn_cast<GlobalAddressSDNode>(Callee); 6525ffd83dbSDimitry Andric if (CalleeG) 6535ffd83dbSDimitry Andric GV = CalleeG->getGlobal(); 654*0fca6ea1SDimitry Andric bool Local = TM.shouldAssumeDSOLocal(GV); 6555ffd83dbSDimitry Andric bool UsePlt = !Local; 6565ffd83dbSDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 6575ffd83dbSDimitry Andric 6585ffd83dbSDimitry Andric // Turn GlobalAddress/ExternalSymbol node into a value node 6595ffd83dbSDimitry Andric // containing the address of them here. 6605ffd83dbSDimitry Andric if (CalleeG) { 6615ffd83dbSDimitry Andric if (IsPICCall) { 6625ffd83dbSDimitry Andric if (UsePlt) 6635ffd83dbSDimitry Andric Subtarget->getInstrInfo()->getGlobalBaseReg(&MF); 6645ffd83dbSDimitry Andric Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, 0); 6655ffd83dbSDimitry Andric Callee = DAG.getNode(VEISD::GETFUNPLT, DL, PtrVT, Callee); 6665ffd83dbSDimitry Andric } else { 6675ffd83dbSDimitry Andric Callee = 6685ffd83dbSDimitry Andric makeHiLoPair(Callee, VEMCExpr::VK_VE_HI32, VEMCExpr::VK_VE_LO32, DAG); 6695ffd83dbSDimitry Andric } 6705ffd83dbSDimitry Andric } else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) { 6715ffd83dbSDimitry Andric if (IsPICCall) { 6725ffd83dbSDimitry Andric if (UsePlt) 6735ffd83dbSDimitry Andric Subtarget->getInstrInfo()->getGlobalBaseReg(&MF); 6745ffd83dbSDimitry Andric Callee = DAG.getTargetExternalSymbol(E->getSymbol(), PtrVT, 0); 6755ffd83dbSDimitry Andric Callee = DAG.getNode(VEISD::GETFUNPLT, DL, PtrVT, Callee); 6765ffd83dbSDimitry Andric } else { 6775ffd83dbSDimitry Andric Callee = 6785ffd83dbSDimitry Andric makeHiLoPair(Callee, VEMCExpr::VK_VE_HI32, VEMCExpr::VK_VE_LO32, DAG); 6795ffd83dbSDimitry Andric } 6805ffd83dbSDimitry Andric } 6815ffd83dbSDimitry Andric 6825ffd83dbSDimitry Andric RegsToPass.push_back(std::make_pair(VE::SX12, Callee)); 6835ffd83dbSDimitry Andric 6845ffd83dbSDimitry Andric for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 6855ffd83dbSDimitry Andric CCValAssign &VA = ArgLocs[i]; 6865ffd83dbSDimitry Andric SDValue Arg = CLI.OutVals[i]; 6875ffd83dbSDimitry Andric 6885ffd83dbSDimitry Andric // Promote the value if needed. 6895ffd83dbSDimitry Andric switch (VA.getLocInfo()) { 6905ffd83dbSDimitry Andric default: 6915ffd83dbSDimitry Andric llvm_unreachable("Unknown location info!"); 6925ffd83dbSDimitry Andric case CCValAssign::Full: 6935ffd83dbSDimitry Andric break; 6945ffd83dbSDimitry Andric case CCValAssign::SExt: 6955ffd83dbSDimitry Andric Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg); 6965ffd83dbSDimitry Andric break; 6975ffd83dbSDimitry Andric case CCValAssign::ZExt: 6985ffd83dbSDimitry Andric Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg); 6995ffd83dbSDimitry Andric break; 7005ffd83dbSDimitry Andric case CCValAssign::AExt: 7015ffd83dbSDimitry Andric Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg); 7025ffd83dbSDimitry Andric break; 703e8d8bef9SDimitry Andric case CCValAssign::BCvt: { 704e8d8bef9SDimitry Andric // Convert a float argument to i64 with padding. 705e8d8bef9SDimitry Andric // 63 31 0 706e8d8bef9SDimitry Andric // +------+------+ 707e8d8bef9SDimitry Andric // | float| 0 | 708e8d8bef9SDimitry Andric // +------+------+ 709e8d8bef9SDimitry Andric assert(VA.getLocVT() == MVT::i64); 710e8d8bef9SDimitry Andric assert(VA.getValVT() == MVT::f32); 711e8d8bef9SDimitry Andric SDValue Undef = SDValue( 712e8d8bef9SDimitry Andric DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MVT::i64), 0); 713e8d8bef9SDimitry Andric SDValue Sub_f32 = DAG.getTargetConstant(VE::sub_f32, DL, MVT::i32); 714e8d8bef9SDimitry Andric Arg = SDValue(DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, DL, 715e8d8bef9SDimitry Andric MVT::i64, Undef, Arg, Sub_f32), 716e8d8bef9SDimitry Andric 0); 717e8d8bef9SDimitry Andric break; 718e8d8bef9SDimitry Andric } 7195ffd83dbSDimitry Andric } 7205ffd83dbSDimitry Andric 7215ffd83dbSDimitry Andric if (VA.isRegLoc()) { 7225ffd83dbSDimitry Andric RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); 7235ffd83dbSDimitry Andric if (!UseBoth) 7245ffd83dbSDimitry Andric continue; 7255ffd83dbSDimitry Andric VA = ArgLocs2[i]; 7265ffd83dbSDimitry Andric } 7275ffd83dbSDimitry Andric 7285ffd83dbSDimitry Andric assert(VA.isMemLoc()); 7295ffd83dbSDimitry Andric 7305ffd83dbSDimitry Andric // Create a store off the stack pointer for this argument. 7315ffd83dbSDimitry Andric SDValue StackPtr = DAG.getRegister(VE::SX11, PtrVT); 732e8d8bef9SDimitry Andric // The argument area starts at %fp/%sp + the size of reserved area. 7335ffd83dbSDimitry Andric SDValue PtrOff = 7345ffd83dbSDimitry Andric DAG.getIntPtrConstant(VA.getLocMemOffset() + ArgsBaseOffset, DL); 7355ffd83dbSDimitry Andric PtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, PtrOff); 7365ffd83dbSDimitry Andric MemOpChains.push_back( 7375ffd83dbSDimitry Andric DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo())); 7385ffd83dbSDimitry Andric } 7395ffd83dbSDimitry Andric 7405ffd83dbSDimitry Andric // Emit all stores, make sure they occur before the call. 7415ffd83dbSDimitry Andric if (!MemOpChains.empty()) 7425ffd83dbSDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains); 7435ffd83dbSDimitry Andric 7445ffd83dbSDimitry Andric // Build a sequence of CopyToReg nodes glued together with token chain and 7455ffd83dbSDimitry Andric // glue operands which copy the outgoing args into registers. The InGlue is 7465ffd83dbSDimitry Andric // necessary since all emitted instructions must be stuck together in order 7475ffd83dbSDimitry Andric // to pass the live physical registers. 7485ffd83dbSDimitry Andric SDValue InGlue; 7495ffd83dbSDimitry Andric for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { 7505ffd83dbSDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, RegsToPass[i].first, 7515ffd83dbSDimitry Andric RegsToPass[i].second, InGlue); 7525ffd83dbSDimitry Andric InGlue = Chain.getValue(1); 7535ffd83dbSDimitry Andric } 7545ffd83dbSDimitry Andric 7555ffd83dbSDimitry Andric // Build the operands for the call instruction itself. 7565ffd83dbSDimitry Andric SmallVector<SDValue, 8> Ops; 7575ffd83dbSDimitry Andric Ops.push_back(Chain); 7585ffd83dbSDimitry Andric for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) 7595ffd83dbSDimitry Andric Ops.push_back(DAG.getRegister(RegsToPass[i].first, 7605ffd83dbSDimitry Andric RegsToPass[i].second.getValueType())); 7615ffd83dbSDimitry Andric 7625ffd83dbSDimitry Andric // Add a register mask operand representing the call-preserved registers. 7635ffd83dbSDimitry Andric const VERegisterInfo *TRI = Subtarget->getRegisterInfo(); 7645ffd83dbSDimitry Andric const uint32_t *Mask = 7655ffd83dbSDimitry Andric TRI->getCallPreservedMask(DAG.getMachineFunction(), CLI.CallConv); 7665ffd83dbSDimitry Andric assert(Mask && "Missing call preserved mask for calling convention"); 7675ffd83dbSDimitry Andric Ops.push_back(DAG.getRegisterMask(Mask)); 7685ffd83dbSDimitry Andric 7695ffd83dbSDimitry Andric // Make sure the CopyToReg nodes are glued to the call instruction which 7705ffd83dbSDimitry Andric // consumes the registers. 7715ffd83dbSDimitry Andric if (InGlue.getNode()) 7725ffd83dbSDimitry Andric Ops.push_back(InGlue); 7735ffd83dbSDimitry Andric 7745ffd83dbSDimitry Andric // Now the call itself. 7755ffd83dbSDimitry Andric SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 7765ffd83dbSDimitry Andric Chain = DAG.getNode(VEISD::CALL, DL, NodeTys, Ops); 7775ffd83dbSDimitry Andric InGlue = Chain.getValue(1); 7785ffd83dbSDimitry Andric 7795ffd83dbSDimitry Andric // Revert the stack pointer immediately after the call. 780bdd1243dSDimitry Andric Chain = DAG.getCALLSEQ_END(Chain, ArgsSize, 0, InGlue, DL); 7815ffd83dbSDimitry Andric InGlue = Chain.getValue(1); 7825ffd83dbSDimitry Andric 7835ffd83dbSDimitry Andric // Now extract the return values. This is more or less the same as 7845ffd83dbSDimitry Andric // LowerFormalArguments. 7855ffd83dbSDimitry Andric 7865ffd83dbSDimitry Andric // Assign locations to each value returned by this call. 7875ffd83dbSDimitry Andric SmallVector<CCValAssign, 16> RVLocs; 7885ffd83dbSDimitry Andric CCState RVInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), RVLocs, 7895ffd83dbSDimitry Andric *DAG.getContext()); 7905ffd83dbSDimitry Andric 7915ffd83dbSDimitry Andric // Set inreg flag manually for codegen generated library calls that 7925ffd83dbSDimitry Andric // return float. 7935ffd83dbSDimitry Andric if (CLI.Ins.size() == 1 && CLI.Ins[0].VT == MVT::f32 && !CLI.CB) 7945ffd83dbSDimitry Andric CLI.Ins[0].Flags.setInReg(); 7955ffd83dbSDimitry Andric 796e8d8bef9SDimitry Andric RVInfo.AnalyzeCallResult(CLI.Ins, getReturnCC(CLI.CallConv)); 7975ffd83dbSDimitry Andric 7985ffd83dbSDimitry Andric // Copy all of the result registers out of their specified physreg. 7995ffd83dbSDimitry Andric for (unsigned i = 0; i != RVLocs.size(); ++i) { 8005ffd83dbSDimitry Andric CCValAssign &VA = RVLocs[i]; 801e8d8bef9SDimitry Andric assert(!VA.needsCustom() && "Unexpected custom lowering"); 80204eeddc0SDimitry Andric Register Reg = VA.getLocReg(); 8035ffd83dbSDimitry Andric 8045ffd83dbSDimitry Andric // When returning 'inreg {i32, i32 }', two consecutive i32 arguments can 8055ffd83dbSDimitry Andric // reside in the same register in the high and low bits. Reuse the 8065ffd83dbSDimitry Andric // CopyFromReg previous node to avoid duplicate copies. 8075ffd83dbSDimitry Andric SDValue RV; 8085ffd83dbSDimitry Andric if (RegisterSDNode *SrcReg = dyn_cast<RegisterSDNode>(Chain.getOperand(1))) 8095ffd83dbSDimitry Andric if (SrcReg->getReg() == Reg && Chain->getOpcode() == ISD::CopyFromReg) 8105ffd83dbSDimitry Andric RV = Chain.getValue(0); 8115ffd83dbSDimitry Andric 8125ffd83dbSDimitry Andric // But usually we'll create a new CopyFromReg for a different register. 8135ffd83dbSDimitry Andric if (!RV.getNode()) { 8145ffd83dbSDimitry Andric RV = DAG.getCopyFromReg(Chain, DL, Reg, RVLocs[i].getLocVT(), InGlue); 8155ffd83dbSDimitry Andric Chain = RV.getValue(1); 8165ffd83dbSDimitry Andric InGlue = Chain.getValue(2); 8175ffd83dbSDimitry Andric } 8185ffd83dbSDimitry Andric 8195ffd83dbSDimitry Andric // The callee promoted the return value, so insert an Assert?ext SDNode so 8205ffd83dbSDimitry Andric // we won't promote the value again in this function. 8215ffd83dbSDimitry Andric switch (VA.getLocInfo()) { 8225ffd83dbSDimitry Andric case CCValAssign::SExt: 8235ffd83dbSDimitry Andric RV = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), RV, 8245ffd83dbSDimitry Andric DAG.getValueType(VA.getValVT())); 8255ffd83dbSDimitry Andric break; 8265ffd83dbSDimitry Andric case CCValAssign::ZExt: 8275ffd83dbSDimitry Andric RV = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), RV, 8285ffd83dbSDimitry Andric DAG.getValueType(VA.getValVT())); 8295ffd83dbSDimitry Andric break; 830e8d8bef9SDimitry Andric case CCValAssign::BCvt: { 831e8d8bef9SDimitry Andric // Extract a float return value from i64 with padding. 832e8d8bef9SDimitry Andric // 63 31 0 833e8d8bef9SDimitry Andric // +------+------+ 834e8d8bef9SDimitry Andric // | float| 0 | 835e8d8bef9SDimitry Andric // +------+------+ 836e8d8bef9SDimitry Andric assert(VA.getLocVT() == MVT::i64); 837e8d8bef9SDimitry Andric assert(VA.getValVT() == MVT::f32); 838e8d8bef9SDimitry Andric SDValue Sub_f32 = DAG.getTargetConstant(VE::sub_f32, DL, MVT::i32); 839e8d8bef9SDimitry Andric RV = SDValue(DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, 840e8d8bef9SDimitry Andric MVT::f32, RV, Sub_f32), 841e8d8bef9SDimitry Andric 0); 842e8d8bef9SDimitry Andric break; 843e8d8bef9SDimitry Andric } 8445ffd83dbSDimitry Andric default: 8455ffd83dbSDimitry Andric break; 8465ffd83dbSDimitry Andric } 8475ffd83dbSDimitry Andric 8485ffd83dbSDimitry Andric // Truncate the register down to the return value type. 8495ffd83dbSDimitry Andric if (VA.isExtInLoc()) 8505ffd83dbSDimitry Andric RV = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), RV); 8515ffd83dbSDimitry Andric 8525ffd83dbSDimitry Andric InVals.push_back(RV); 8535ffd83dbSDimitry Andric } 8545ffd83dbSDimitry Andric 8555ffd83dbSDimitry Andric return Chain; 8565ffd83dbSDimitry Andric } 8575ffd83dbSDimitry Andric 858e8d8bef9SDimitry Andric bool VETargetLowering::isOffsetFoldingLegal( 859e8d8bef9SDimitry Andric const GlobalAddressSDNode *GA) const { 860e8d8bef9SDimitry Andric // VE uses 64 bit addressing, so we need multiple instructions to generate 861e8d8bef9SDimitry Andric // an address. Folding address with offset increases the number of 862e8d8bef9SDimitry Andric // instructions, so that we disable it here. Offsets will be folded in 863e8d8bef9SDimitry Andric // the DAG combine later if it worth to do so. 864e8d8bef9SDimitry Andric return false; 865e8d8bef9SDimitry Andric } 866e8d8bef9SDimitry Andric 8675ffd83dbSDimitry Andric /// isFPImmLegal - Returns true if the target can instruction select the 8685ffd83dbSDimitry Andric /// specified FP immediate natively. If false, the legalizer will 8695ffd83dbSDimitry Andric /// materialize the FP immediate as a load from a constant pool. 8705ffd83dbSDimitry Andric bool VETargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT, 8715ffd83dbSDimitry Andric bool ForCodeSize) const { 8725ffd83dbSDimitry Andric return VT == MVT::f32 || VT == MVT::f64; 8735ffd83dbSDimitry Andric } 8745ffd83dbSDimitry Andric 8755ffd83dbSDimitry Andric /// Determine if the target supports unaligned memory accesses. 8765ffd83dbSDimitry Andric /// 8775ffd83dbSDimitry Andric /// This function returns true if the target allows unaligned memory accesses 8785ffd83dbSDimitry Andric /// of the specified type in the given address space. If true, it also returns 8795ffd83dbSDimitry Andric /// whether the unaligned memory access is "fast" in the last argument by 8805ffd83dbSDimitry Andric /// reference. This is used, for example, in situations where an array 8815ffd83dbSDimitry Andric /// copy/move/set is converted to a sequence of store operations. Its use 8825ffd83dbSDimitry Andric /// helps to ensure that such replacements don't generate code that causes an 8835ffd83dbSDimitry Andric /// alignment error (trap) on the target machine. 8845ffd83dbSDimitry Andric bool VETargetLowering::allowsMisalignedMemoryAccesses(EVT VT, 8855ffd83dbSDimitry Andric unsigned AddrSpace, 886fe6060f1SDimitry Andric Align A, 8875ffd83dbSDimitry Andric MachineMemOperand::Flags, 888bdd1243dSDimitry Andric unsigned *Fast) const { 8895ffd83dbSDimitry Andric if (Fast) { 8905ffd83dbSDimitry Andric // It's fast anytime on VE 891bdd1243dSDimitry Andric *Fast = 1; 8925ffd83dbSDimitry Andric } 8935ffd83dbSDimitry Andric return true; 8945ffd83dbSDimitry Andric } 8955ffd83dbSDimitry Andric 896480093f4SDimitry Andric VETargetLowering::VETargetLowering(const TargetMachine &TM, 897480093f4SDimitry Andric const VESubtarget &STI) 898480093f4SDimitry Andric : TargetLowering(TM), Subtarget(&STI) { 899480093f4SDimitry Andric // Instructions which use registers as conditionals examine all the 900480093f4SDimitry Andric // bits (as does the pseudo SELECT_CC expansion). I don't think it 901480093f4SDimitry Andric // matters much whether it's ZeroOrOneBooleanContent, or 902480093f4SDimitry Andric // ZeroOrNegativeOneBooleanContent, so, arbitrarily choose the 903480093f4SDimitry Andric // former. 904480093f4SDimitry Andric setBooleanContents(ZeroOrOneBooleanContent); 905480093f4SDimitry Andric setBooleanVectorContents(ZeroOrOneBooleanContent); 906480093f4SDimitry Andric 907e8d8bef9SDimitry Andric initRegisterClasses(); 908e8d8bef9SDimitry Andric initSPUActions(); 909e8d8bef9SDimitry Andric initVPUActions(); 910480093f4SDimitry Andric 911480093f4SDimitry Andric setStackPointerRegisterToSaveRestore(VE::SX11); 912480093f4SDimitry Andric 913e8d8bef9SDimitry Andric // We have target-specific dag combine patterns for the following nodes: 914e8d8bef9SDimitry Andric setTargetDAGCombine(ISD::TRUNCATE); 915bdd1243dSDimitry Andric setTargetDAGCombine(ISD::SELECT); 916bdd1243dSDimitry Andric setTargetDAGCombine(ISD::SELECT_CC); 917e8d8bef9SDimitry Andric 918480093f4SDimitry Andric // Set function alignment to 16 bytes 919480093f4SDimitry Andric setMinFunctionAlignment(Align(16)); 920480093f4SDimitry Andric 921480093f4SDimitry Andric // VE stores all argument by 8 bytes alignment 922480093f4SDimitry Andric setMinStackArgumentAlignment(Align(8)); 923480093f4SDimitry Andric 924480093f4SDimitry Andric computeRegisterProperties(Subtarget->getRegisterInfo()); 925480093f4SDimitry Andric } 926480093f4SDimitry Andric 927480093f4SDimitry Andric const char *VETargetLowering::getTargetNodeName(unsigned Opcode) const { 9285ffd83dbSDimitry Andric #define TARGET_NODE_CASE(NAME) \ 9295ffd83dbSDimitry Andric case VEISD::NAME: \ 9305ffd83dbSDimitry Andric return "VEISD::" #NAME; 931480093f4SDimitry Andric switch ((VEISD::NodeType)Opcode) { 932480093f4SDimitry Andric case VEISD::FIRST_NUMBER: 933480093f4SDimitry Andric break; 934bdd1243dSDimitry Andric TARGET_NODE_CASE(CMPI) 935bdd1243dSDimitry Andric TARGET_NODE_CASE(CMPU) 936bdd1243dSDimitry Andric TARGET_NODE_CASE(CMPF) 937bdd1243dSDimitry Andric TARGET_NODE_CASE(CMPQ) 938bdd1243dSDimitry Andric TARGET_NODE_CASE(CMOV) 939e8d8bef9SDimitry Andric TARGET_NODE_CASE(CALL) 940e8d8bef9SDimitry Andric TARGET_NODE_CASE(EH_SJLJ_LONGJMP) 941e8d8bef9SDimitry Andric TARGET_NODE_CASE(EH_SJLJ_SETJMP) 942e8d8bef9SDimitry Andric TARGET_NODE_CASE(EH_SJLJ_SETUP_DISPATCH) 9435ffd83dbSDimitry Andric TARGET_NODE_CASE(GETFUNPLT) 9445ffd83dbSDimitry Andric TARGET_NODE_CASE(GETSTACKTOP) 9455ffd83dbSDimitry Andric TARGET_NODE_CASE(GETTLSADDR) 9465ffd83dbSDimitry Andric TARGET_NODE_CASE(GLOBAL_BASE_REG) 947e8d8bef9SDimitry Andric TARGET_NODE_CASE(Hi) 948e8d8bef9SDimitry Andric TARGET_NODE_CASE(Lo) 94906c3fb27SDimitry Andric TARGET_NODE_CASE(RET_GLUE) 950e8d8bef9SDimitry Andric TARGET_NODE_CASE(TS1AM) 95181ad6265SDimitry Andric TARGET_NODE_CASE(VEC_UNPACK_LO) 95281ad6265SDimitry Andric TARGET_NODE_CASE(VEC_UNPACK_HI) 95381ad6265SDimitry Andric TARGET_NODE_CASE(VEC_PACK) 954e8d8bef9SDimitry Andric TARGET_NODE_CASE(VEC_BROADCAST) 95504eeddc0SDimitry Andric TARGET_NODE_CASE(REPL_I32) 95604eeddc0SDimitry Andric TARGET_NODE_CASE(REPL_F32) 957e8d8bef9SDimitry Andric 95881ad6265SDimitry Andric TARGET_NODE_CASE(LEGALAVL) 95981ad6265SDimitry Andric 960e8d8bef9SDimitry Andric // Register the VVP_* SDNodes. 961e8d8bef9SDimitry Andric #define ADD_VVP_OP(VVP_NAME, ...) TARGET_NODE_CASE(VVP_NAME) 962e8d8bef9SDimitry Andric #include "VVPNodes.def" 963480093f4SDimitry Andric } 9645ffd83dbSDimitry Andric #undef TARGET_NODE_CASE 965480093f4SDimitry Andric return nullptr; 966480093f4SDimitry Andric } 967480093f4SDimitry Andric 968480093f4SDimitry Andric EVT VETargetLowering::getSetCCResultType(const DataLayout &, LLVMContext &, 969480093f4SDimitry Andric EVT VT) const { 9705ffd83dbSDimitry Andric return MVT::i32; 971480093f4SDimitry Andric } 9725ffd83dbSDimitry Andric 9735ffd83dbSDimitry Andric // Convert to a target node and set target flags. 9745ffd83dbSDimitry Andric SDValue VETargetLowering::withTargetFlags(SDValue Op, unsigned TF, 9755ffd83dbSDimitry Andric SelectionDAG &DAG) const { 9765ffd83dbSDimitry Andric if (const GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op)) 9775ffd83dbSDimitry Andric return DAG.getTargetGlobalAddress(GA->getGlobal(), SDLoc(GA), 9785ffd83dbSDimitry Andric GA->getValueType(0), GA->getOffset(), TF); 9795ffd83dbSDimitry Andric 9805ffd83dbSDimitry Andric if (const BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op)) 9815ffd83dbSDimitry Andric return DAG.getTargetBlockAddress(BA->getBlockAddress(), Op.getValueType(), 9825ffd83dbSDimitry Andric 0, TF); 9835ffd83dbSDimitry Andric 984e8d8bef9SDimitry Andric if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Op)) 985e8d8bef9SDimitry Andric return DAG.getTargetConstantPool(CP->getConstVal(), CP->getValueType(0), 986e8d8bef9SDimitry Andric CP->getAlign(), CP->getOffset(), TF); 987e8d8bef9SDimitry Andric 9885ffd83dbSDimitry Andric if (const ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op)) 9895ffd83dbSDimitry Andric return DAG.getTargetExternalSymbol(ES->getSymbol(), ES->getValueType(0), 9905ffd83dbSDimitry Andric TF); 9915ffd83dbSDimitry Andric 992e8d8bef9SDimitry Andric if (const JumpTableSDNode *JT = dyn_cast<JumpTableSDNode>(Op)) 993e8d8bef9SDimitry Andric return DAG.getTargetJumpTable(JT->getIndex(), JT->getValueType(0), TF); 994e8d8bef9SDimitry Andric 9955ffd83dbSDimitry Andric llvm_unreachable("Unhandled address SDNode"); 9965ffd83dbSDimitry Andric } 9975ffd83dbSDimitry Andric 9985ffd83dbSDimitry Andric // Split Op into high and low parts according to HiTF and LoTF. 9995ffd83dbSDimitry Andric // Return an ADD node combining the parts. 10005ffd83dbSDimitry Andric SDValue VETargetLowering::makeHiLoPair(SDValue Op, unsigned HiTF, unsigned LoTF, 10015ffd83dbSDimitry Andric SelectionDAG &DAG) const { 10025ffd83dbSDimitry Andric SDLoc DL(Op); 10035ffd83dbSDimitry Andric EVT VT = Op.getValueType(); 10045ffd83dbSDimitry Andric SDValue Hi = DAG.getNode(VEISD::Hi, DL, VT, withTargetFlags(Op, HiTF, DAG)); 10055ffd83dbSDimitry Andric SDValue Lo = DAG.getNode(VEISD::Lo, DL, VT, withTargetFlags(Op, LoTF, DAG)); 10065ffd83dbSDimitry Andric return DAG.getNode(ISD::ADD, DL, VT, Hi, Lo); 10075ffd83dbSDimitry Andric } 10085ffd83dbSDimitry Andric 10095ffd83dbSDimitry Andric // Build SDNodes for producing an address from a GlobalAddress, ConstantPool, 10105ffd83dbSDimitry Andric // or ExternalSymbol SDNode. 10115ffd83dbSDimitry Andric SDValue VETargetLowering::makeAddress(SDValue Op, SelectionDAG &DAG) const { 10125ffd83dbSDimitry Andric SDLoc DL(Op); 10135ffd83dbSDimitry Andric EVT PtrVT = Op.getValueType(); 10145ffd83dbSDimitry Andric 10155ffd83dbSDimitry Andric // Handle PIC mode first. VE needs a got load for every variable! 10165ffd83dbSDimitry Andric if (isPositionIndependent()) { 10175ffd83dbSDimitry Andric auto GlobalN = dyn_cast<GlobalAddressSDNode>(Op); 10185ffd83dbSDimitry Andric 1019e8d8bef9SDimitry Andric if (isa<ConstantPoolSDNode>(Op) || isa<JumpTableSDNode>(Op) || 10205ffd83dbSDimitry Andric (GlobalN && GlobalN->getGlobal()->hasLocalLinkage())) { 10215ffd83dbSDimitry Andric // Create following instructions for local linkage PIC code. 1022e8d8bef9SDimitry Andric // lea %reg, label@gotoff_lo 1023e8d8bef9SDimitry Andric // and %reg, %reg, (32)0 1024e8d8bef9SDimitry Andric // lea.sl %reg, label@gotoff_hi(%reg, %got) 10255ffd83dbSDimitry Andric SDValue HiLo = makeHiLoPair(Op, VEMCExpr::VK_VE_GOTOFF_HI32, 10265ffd83dbSDimitry Andric VEMCExpr::VK_VE_GOTOFF_LO32, DAG); 10275ffd83dbSDimitry Andric SDValue GlobalBase = DAG.getNode(VEISD::GLOBAL_BASE_REG, DL, PtrVT); 10285ffd83dbSDimitry Andric return DAG.getNode(ISD::ADD, DL, PtrVT, GlobalBase, HiLo); 10295ffd83dbSDimitry Andric } 10305ffd83dbSDimitry Andric // Create following instructions for not local linkage PIC code. 1031e8d8bef9SDimitry Andric // lea %reg, label@got_lo 1032e8d8bef9SDimitry Andric // and %reg, %reg, (32)0 1033e8d8bef9SDimitry Andric // lea.sl %reg, label@got_hi(%reg) 1034e8d8bef9SDimitry Andric // ld %reg, (%reg, %got) 10355ffd83dbSDimitry Andric SDValue HiLo = makeHiLoPair(Op, VEMCExpr::VK_VE_GOT_HI32, 10365ffd83dbSDimitry Andric VEMCExpr::VK_VE_GOT_LO32, DAG); 10375ffd83dbSDimitry Andric SDValue GlobalBase = DAG.getNode(VEISD::GLOBAL_BASE_REG, DL, PtrVT); 10385ffd83dbSDimitry Andric SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, PtrVT, GlobalBase, HiLo); 10395ffd83dbSDimitry Andric return DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), AbsAddr, 10405ffd83dbSDimitry Andric MachinePointerInfo::getGOT(DAG.getMachineFunction())); 10415ffd83dbSDimitry Andric } 10425ffd83dbSDimitry Andric 10435ffd83dbSDimitry Andric // This is one of the absolute code models. 10445ffd83dbSDimitry Andric switch (getTargetMachine().getCodeModel()) { 10455ffd83dbSDimitry Andric default: 10465ffd83dbSDimitry Andric llvm_unreachable("Unsupported absolute code model"); 10475ffd83dbSDimitry Andric case CodeModel::Small: 10485ffd83dbSDimitry Andric case CodeModel::Medium: 10495ffd83dbSDimitry Andric case CodeModel::Large: 10505ffd83dbSDimitry Andric // abs64. 10515ffd83dbSDimitry Andric return makeHiLoPair(Op, VEMCExpr::VK_VE_HI32, VEMCExpr::VK_VE_LO32, DAG); 10525ffd83dbSDimitry Andric } 10535ffd83dbSDimitry Andric } 10545ffd83dbSDimitry Andric 10555ffd83dbSDimitry Andric /// Custom Lower { 10565ffd83dbSDimitry Andric 1057e8d8bef9SDimitry Andric // The mappings for emitLeading/TrailingFence for VE is designed by following 1058e8d8bef9SDimitry Andric // http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html 1059fe6060f1SDimitry Andric Instruction *VETargetLowering::emitLeadingFence(IRBuilderBase &Builder, 1060e8d8bef9SDimitry Andric Instruction *Inst, 1061e8d8bef9SDimitry Andric AtomicOrdering Ord) const { 1062e8d8bef9SDimitry Andric switch (Ord) { 1063e8d8bef9SDimitry Andric case AtomicOrdering::NotAtomic: 1064e8d8bef9SDimitry Andric case AtomicOrdering::Unordered: 1065e8d8bef9SDimitry Andric llvm_unreachable("Invalid fence: unordered/non-atomic"); 1066e8d8bef9SDimitry Andric case AtomicOrdering::Monotonic: 1067e8d8bef9SDimitry Andric case AtomicOrdering::Acquire: 1068e8d8bef9SDimitry Andric return nullptr; // Nothing to do 1069e8d8bef9SDimitry Andric case AtomicOrdering::Release: 1070e8d8bef9SDimitry Andric case AtomicOrdering::AcquireRelease: 1071e8d8bef9SDimitry Andric return Builder.CreateFence(AtomicOrdering::Release); 1072e8d8bef9SDimitry Andric case AtomicOrdering::SequentiallyConsistent: 1073e8d8bef9SDimitry Andric if (!Inst->hasAtomicStore()) 1074e8d8bef9SDimitry Andric return nullptr; // Nothing to do 1075e8d8bef9SDimitry Andric return Builder.CreateFence(AtomicOrdering::SequentiallyConsistent); 1076e8d8bef9SDimitry Andric } 1077e8d8bef9SDimitry Andric llvm_unreachable("Unknown fence ordering in emitLeadingFence"); 1078e8d8bef9SDimitry Andric } 1079e8d8bef9SDimitry Andric 1080fe6060f1SDimitry Andric Instruction *VETargetLowering::emitTrailingFence(IRBuilderBase &Builder, 1081e8d8bef9SDimitry Andric Instruction *Inst, 1082e8d8bef9SDimitry Andric AtomicOrdering Ord) const { 1083e8d8bef9SDimitry Andric switch (Ord) { 1084e8d8bef9SDimitry Andric case AtomicOrdering::NotAtomic: 1085e8d8bef9SDimitry Andric case AtomicOrdering::Unordered: 1086e8d8bef9SDimitry Andric llvm_unreachable("Invalid fence: unordered/not-atomic"); 1087e8d8bef9SDimitry Andric case AtomicOrdering::Monotonic: 1088e8d8bef9SDimitry Andric case AtomicOrdering::Release: 1089e8d8bef9SDimitry Andric return nullptr; // Nothing to do 1090e8d8bef9SDimitry Andric case AtomicOrdering::Acquire: 1091e8d8bef9SDimitry Andric case AtomicOrdering::AcquireRelease: 1092e8d8bef9SDimitry Andric return Builder.CreateFence(AtomicOrdering::Acquire); 1093e8d8bef9SDimitry Andric case AtomicOrdering::SequentiallyConsistent: 1094e8d8bef9SDimitry Andric return Builder.CreateFence(AtomicOrdering::SequentiallyConsistent); 1095e8d8bef9SDimitry Andric } 1096e8d8bef9SDimitry Andric llvm_unreachable("Unknown fence ordering in emitTrailingFence"); 1097e8d8bef9SDimitry Andric } 1098e8d8bef9SDimitry Andric 1099e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerATOMIC_FENCE(SDValue Op, 1100e8d8bef9SDimitry Andric SelectionDAG &DAG) const { 1101e8d8bef9SDimitry Andric SDLoc DL(Op); 1102647cbc5dSDimitry Andric AtomicOrdering FenceOrdering = 1103647cbc5dSDimitry Andric static_cast<AtomicOrdering>(Op.getConstantOperandVal(1)); 1104647cbc5dSDimitry Andric SyncScope::ID FenceSSID = 1105647cbc5dSDimitry Andric static_cast<SyncScope::ID>(Op.getConstantOperandVal(2)); 1106e8d8bef9SDimitry Andric 1107e8d8bef9SDimitry Andric // VE uses Release consistency, so need a fence instruction if it is a 1108e8d8bef9SDimitry Andric // cross-thread fence. 1109e8d8bef9SDimitry Andric if (FenceSSID == SyncScope::System) { 1110e8d8bef9SDimitry Andric switch (FenceOrdering) { 1111e8d8bef9SDimitry Andric case AtomicOrdering::NotAtomic: 1112e8d8bef9SDimitry Andric case AtomicOrdering::Unordered: 1113e8d8bef9SDimitry Andric case AtomicOrdering::Monotonic: 1114e8d8bef9SDimitry Andric // No need to generate fencem instruction here. 1115e8d8bef9SDimitry Andric break; 1116e8d8bef9SDimitry Andric case AtomicOrdering::Acquire: 1117e8d8bef9SDimitry Andric // Generate "fencem 2" as acquire fence. 1118e8d8bef9SDimitry Andric return SDValue(DAG.getMachineNode(VE::FENCEM, DL, MVT::Other, 1119e8d8bef9SDimitry Andric DAG.getTargetConstant(2, DL, MVT::i32), 1120e8d8bef9SDimitry Andric Op.getOperand(0)), 1121e8d8bef9SDimitry Andric 0); 1122e8d8bef9SDimitry Andric case AtomicOrdering::Release: 1123e8d8bef9SDimitry Andric // Generate "fencem 1" as release fence. 1124e8d8bef9SDimitry Andric return SDValue(DAG.getMachineNode(VE::FENCEM, DL, MVT::Other, 1125e8d8bef9SDimitry Andric DAG.getTargetConstant(1, DL, MVT::i32), 1126e8d8bef9SDimitry Andric Op.getOperand(0)), 1127e8d8bef9SDimitry Andric 0); 1128e8d8bef9SDimitry Andric case AtomicOrdering::AcquireRelease: 1129e8d8bef9SDimitry Andric case AtomicOrdering::SequentiallyConsistent: 1130e8d8bef9SDimitry Andric // Generate "fencem 3" as acq_rel and seq_cst fence. 11315f757f3fSDimitry Andric // FIXME: "fencem 3" doesn't wait for PCIe deveices accesses, 1132e8d8bef9SDimitry Andric // so seq_cst may require more instruction for them. 1133e8d8bef9SDimitry Andric return SDValue(DAG.getMachineNode(VE::FENCEM, DL, MVT::Other, 1134e8d8bef9SDimitry Andric DAG.getTargetConstant(3, DL, MVT::i32), 1135e8d8bef9SDimitry Andric Op.getOperand(0)), 1136e8d8bef9SDimitry Andric 0); 1137e8d8bef9SDimitry Andric } 1138e8d8bef9SDimitry Andric } 1139e8d8bef9SDimitry Andric 1140e8d8bef9SDimitry Andric // MEMBARRIER is a compiler barrier; it codegens to a no-op. 1141bdd1243dSDimitry Andric return DAG.getNode(ISD::MEMBARRIER, DL, MVT::Other, Op.getOperand(0)); 1142e8d8bef9SDimitry Andric } 1143e8d8bef9SDimitry Andric 1144e8d8bef9SDimitry Andric TargetLowering::AtomicExpansionKind 1145e8d8bef9SDimitry Andric VETargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const { 1146e8d8bef9SDimitry Andric // We have TS1AM implementation for i8/i16/i32/i64, so use it. 1147e8d8bef9SDimitry Andric if (AI->getOperation() == AtomicRMWInst::Xchg) { 1148e8d8bef9SDimitry Andric return AtomicExpansionKind::None; 1149e8d8bef9SDimitry Andric } 1150e8d8bef9SDimitry Andric // FIXME: Support "ATMAM" instruction for LOAD_ADD/SUB/AND/OR. 1151e8d8bef9SDimitry Andric 1152e8d8bef9SDimitry Andric // Otherwise, expand it using compare and exchange instruction to not call 1153e8d8bef9SDimitry Andric // __sync_fetch_and_* functions. 1154e8d8bef9SDimitry Andric return AtomicExpansionKind::CmpXChg; 1155e8d8bef9SDimitry Andric } 1156e8d8bef9SDimitry Andric 1157e8d8bef9SDimitry Andric static SDValue prepareTS1AM(SDValue Op, SelectionDAG &DAG, SDValue &Flag, 1158e8d8bef9SDimitry Andric SDValue &Bits) { 1159e8d8bef9SDimitry Andric SDLoc DL(Op); 1160e8d8bef9SDimitry Andric AtomicSDNode *N = cast<AtomicSDNode>(Op); 1161e8d8bef9SDimitry Andric SDValue Ptr = N->getOperand(1); 1162e8d8bef9SDimitry Andric SDValue Val = N->getOperand(2); 1163e8d8bef9SDimitry Andric EVT PtrVT = Ptr.getValueType(); 1164e8d8bef9SDimitry Andric bool Byte = N->getMemoryVT() == MVT::i8; 1165e8d8bef9SDimitry Andric // Remainder = AND Ptr, 3 1166e8d8bef9SDimitry Andric // Flag = 1 << Remainder ; If Byte is true (1 byte swap flag) 1167e8d8bef9SDimitry Andric // Flag = 3 << Remainder ; If Byte is false (2 bytes swap flag) 1168e8d8bef9SDimitry Andric // Bits = Remainder << 3 1169e8d8bef9SDimitry Andric // NewVal = Val << Bits 1170e8d8bef9SDimitry Andric SDValue Const3 = DAG.getConstant(3, DL, PtrVT); 1171e8d8bef9SDimitry Andric SDValue Remainder = DAG.getNode(ISD::AND, DL, PtrVT, {Ptr, Const3}); 1172e8d8bef9SDimitry Andric SDValue Mask = Byte ? DAG.getConstant(1, DL, MVT::i32) 1173e8d8bef9SDimitry Andric : DAG.getConstant(3, DL, MVT::i32); 1174e8d8bef9SDimitry Andric Flag = DAG.getNode(ISD::SHL, DL, MVT::i32, {Mask, Remainder}); 1175e8d8bef9SDimitry Andric Bits = DAG.getNode(ISD::SHL, DL, PtrVT, {Remainder, Const3}); 1176e8d8bef9SDimitry Andric return DAG.getNode(ISD::SHL, DL, Val.getValueType(), {Val, Bits}); 1177e8d8bef9SDimitry Andric } 1178e8d8bef9SDimitry Andric 1179e8d8bef9SDimitry Andric static SDValue finalizeTS1AM(SDValue Op, SelectionDAG &DAG, SDValue Data, 1180e8d8bef9SDimitry Andric SDValue Bits) { 1181e8d8bef9SDimitry Andric SDLoc DL(Op); 1182e8d8bef9SDimitry Andric EVT VT = Data.getValueType(); 1183e8d8bef9SDimitry Andric bool Byte = cast<AtomicSDNode>(Op)->getMemoryVT() == MVT::i8; 1184e8d8bef9SDimitry Andric // NewData = Data >> Bits 1185e8d8bef9SDimitry Andric // Result = NewData & 0xff ; If Byte is true (1 byte) 1186e8d8bef9SDimitry Andric // Result = NewData & 0xffff ; If Byte is false (2 bytes) 1187e8d8bef9SDimitry Andric 1188e8d8bef9SDimitry Andric SDValue NewData = DAG.getNode(ISD::SRL, DL, VT, Data, Bits); 1189e8d8bef9SDimitry Andric return DAG.getNode(ISD::AND, DL, VT, 1190e8d8bef9SDimitry Andric {NewData, DAG.getConstant(Byte ? 0xff : 0xffff, DL, VT)}); 1191e8d8bef9SDimitry Andric } 1192e8d8bef9SDimitry Andric 1193e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerATOMIC_SWAP(SDValue Op, 1194e8d8bef9SDimitry Andric SelectionDAG &DAG) const { 1195e8d8bef9SDimitry Andric SDLoc DL(Op); 1196e8d8bef9SDimitry Andric AtomicSDNode *N = cast<AtomicSDNode>(Op); 1197e8d8bef9SDimitry Andric 1198e8d8bef9SDimitry Andric if (N->getMemoryVT() == MVT::i8) { 1199e8d8bef9SDimitry Andric // For i8, use "ts1am" 1200e8d8bef9SDimitry Andric // Input: 1201e8d8bef9SDimitry Andric // ATOMIC_SWAP Ptr, Val, Order 1202e8d8bef9SDimitry Andric // 1203e8d8bef9SDimitry Andric // Output: 1204e8d8bef9SDimitry Andric // Remainder = AND Ptr, 3 1205e8d8bef9SDimitry Andric // Flag = 1 << Remainder ; 1 byte swap flag for TS1AM inst. 1206e8d8bef9SDimitry Andric // Bits = Remainder << 3 1207e8d8bef9SDimitry Andric // NewVal = Val << Bits 1208e8d8bef9SDimitry Andric // 1209e8d8bef9SDimitry Andric // Aligned = AND Ptr, -4 1210e8d8bef9SDimitry Andric // Data = TS1AM Aligned, Flag, NewVal 1211e8d8bef9SDimitry Andric // 1212e8d8bef9SDimitry Andric // NewData = Data >> Bits 1213e8d8bef9SDimitry Andric // Result = NewData & 0xff ; 1 byte result 1214e8d8bef9SDimitry Andric SDValue Flag; 1215e8d8bef9SDimitry Andric SDValue Bits; 1216e8d8bef9SDimitry Andric SDValue NewVal = prepareTS1AM(Op, DAG, Flag, Bits); 1217e8d8bef9SDimitry Andric 1218e8d8bef9SDimitry Andric SDValue Ptr = N->getOperand(1); 1219e8d8bef9SDimitry Andric SDValue Aligned = DAG.getNode(ISD::AND, DL, Ptr.getValueType(), 1220e8d8bef9SDimitry Andric {Ptr, DAG.getConstant(-4, DL, MVT::i64)}); 1221e8d8bef9SDimitry Andric SDValue TS1AM = DAG.getAtomic(VEISD::TS1AM, DL, N->getMemoryVT(), 1222e8d8bef9SDimitry Andric DAG.getVTList(Op.getNode()->getValueType(0), 1223e8d8bef9SDimitry Andric Op.getNode()->getValueType(1)), 1224e8d8bef9SDimitry Andric {N->getChain(), Aligned, Flag, NewVal}, 1225e8d8bef9SDimitry Andric N->getMemOperand()); 1226e8d8bef9SDimitry Andric 1227e8d8bef9SDimitry Andric SDValue Result = finalizeTS1AM(Op, DAG, TS1AM, Bits); 1228e8d8bef9SDimitry Andric SDValue Chain = TS1AM.getValue(1); 1229e8d8bef9SDimitry Andric return DAG.getMergeValues({Result, Chain}, DL); 1230e8d8bef9SDimitry Andric } 1231e8d8bef9SDimitry Andric if (N->getMemoryVT() == MVT::i16) { 1232e8d8bef9SDimitry Andric // For i16, use "ts1am" 1233e8d8bef9SDimitry Andric SDValue Flag; 1234e8d8bef9SDimitry Andric SDValue Bits; 1235e8d8bef9SDimitry Andric SDValue NewVal = prepareTS1AM(Op, DAG, Flag, Bits); 1236e8d8bef9SDimitry Andric 1237e8d8bef9SDimitry Andric SDValue Ptr = N->getOperand(1); 1238e8d8bef9SDimitry Andric SDValue Aligned = DAG.getNode(ISD::AND, DL, Ptr.getValueType(), 1239e8d8bef9SDimitry Andric {Ptr, DAG.getConstant(-4, DL, MVT::i64)}); 1240e8d8bef9SDimitry Andric SDValue TS1AM = DAG.getAtomic(VEISD::TS1AM, DL, N->getMemoryVT(), 1241e8d8bef9SDimitry Andric DAG.getVTList(Op.getNode()->getValueType(0), 1242e8d8bef9SDimitry Andric Op.getNode()->getValueType(1)), 1243e8d8bef9SDimitry Andric {N->getChain(), Aligned, Flag, NewVal}, 1244e8d8bef9SDimitry Andric N->getMemOperand()); 1245e8d8bef9SDimitry Andric 1246e8d8bef9SDimitry Andric SDValue Result = finalizeTS1AM(Op, DAG, TS1AM, Bits); 1247e8d8bef9SDimitry Andric SDValue Chain = TS1AM.getValue(1); 1248e8d8bef9SDimitry Andric return DAG.getMergeValues({Result, Chain}, DL); 1249e8d8bef9SDimitry Andric } 1250e8d8bef9SDimitry Andric // Otherwise, let llvm legalize it. 1251e8d8bef9SDimitry Andric return Op; 1252e8d8bef9SDimitry Andric } 1253e8d8bef9SDimitry Andric 1254e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerGlobalAddress(SDValue Op, 12555ffd83dbSDimitry Andric SelectionDAG &DAG) const { 12565ffd83dbSDimitry Andric return makeAddress(Op, DAG); 12575ffd83dbSDimitry Andric } 12585ffd83dbSDimitry Andric 1259e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerBlockAddress(SDValue Op, 1260e8d8bef9SDimitry Andric SelectionDAG &DAG) const { 1261e8d8bef9SDimitry Andric return makeAddress(Op, DAG); 1262e8d8bef9SDimitry Andric } 1263e8d8bef9SDimitry Andric 1264e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerConstantPool(SDValue Op, 12655ffd83dbSDimitry Andric SelectionDAG &DAG) const { 12665ffd83dbSDimitry Andric return makeAddress(Op, DAG); 12675ffd83dbSDimitry Andric } 12685ffd83dbSDimitry Andric 12695ffd83dbSDimitry Andric SDValue 1270e8d8bef9SDimitry Andric VETargetLowering::lowerToTLSGeneralDynamicModel(SDValue Op, 12715ffd83dbSDimitry Andric SelectionDAG &DAG) const { 1272e8d8bef9SDimitry Andric SDLoc DL(Op); 12735ffd83dbSDimitry Andric 12745ffd83dbSDimitry Andric // Generate the following code: 12755ffd83dbSDimitry Andric // t1: ch,glue = callseq_start t0, 0, 0 12765ffd83dbSDimitry Andric // t2: i64,ch,glue = VEISD::GETTLSADDR t1, label, t1:1 12775ffd83dbSDimitry Andric // t3: ch,glue = callseq_end t2, 0, 0, t2:2 12785ffd83dbSDimitry Andric // t4: i64,ch,glue = CopyFromReg t3, Register:i64 $sx0, t3:1 12795ffd83dbSDimitry Andric SDValue Label = withTargetFlags(Op, 0, DAG); 12805ffd83dbSDimitry Andric EVT PtrVT = Op.getValueType(); 12815ffd83dbSDimitry Andric 12825ffd83dbSDimitry Andric // Lowering the machine isd will make sure everything is in the right 12835ffd83dbSDimitry Andric // location. 12845ffd83dbSDimitry Andric SDValue Chain = DAG.getEntryNode(); 12855ffd83dbSDimitry Andric SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 12865ffd83dbSDimitry Andric const uint32_t *Mask = Subtarget->getRegisterInfo()->getCallPreservedMask( 12875ffd83dbSDimitry Andric DAG.getMachineFunction(), CallingConv::C); 1288e8d8bef9SDimitry Andric Chain = DAG.getCALLSEQ_START(Chain, 64, 0, DL); 12895ffd83dbSDimitry Andric SDValue Args[] = {Chain, Label, DAG.getRegisterMask(Mask), Chain.getValue(1)}; 1290e8d8bef9SDimitry Andric Chain = DAG.getNode(VEISD::GETTLSADDR, DL, NodeTys, Args); 1291bdd1243dSDimitry Andric Chain = DAG.getCALLSEQ_END(Chain, 64, 0, Chain.getValue(1), DL); 1292e8d8bef9SDimitry Andric Chain = DAG.getCopyFromReg(Chain, DL, VE::SX0, PtrVT, Chain.getValue(1)); 12935ffd83dbSDimitry Andric 12945ffd83dbSDimitry Andric // GETTLSADDR will be codegen'ed as call. Inform MFI that function has calls. 12955ffd83dbSDimitry Andric MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); 12965ffd83dbSDimitry Andric MFI.setHasCalls(true); 12975ffd83dbSDimitry Andric 12985ffd83dbSDimitry Andric // Also generate code to prepare a GOT register if it is PIC. 12995ffd83dbSDimitry Andric if (isPositionIndependent()) { 13005ffd83dbSDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 13015ffd83dbSDimitry Andric Subtarget->getInstrInfo()->getGlobalBaseReg(&MF); 13025ffd83dbSDimitry Andric } 13035ffd83dbSDimitry Andric 13045ffd83dbSDimitry Andric return Chain; 13055ffd83dbSDimitry Andric } 13065ffd83dbSDimitry Andric 1307e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerGlobalTLSAddress(SDValue Op, 13085ffd83dbSDimitry Andric SelectionDAG &DAG) const { 13095ffd83dbSDimitry Andric // The current implementation of nld (2.26) doesn't allow local exec model 13105ffd83dbSDimitry Andric // code described in VE-tls_v1.1.pdf (*1) as its input. Instead, we always 13115ffd83dbSDimitry Andric // generate the general dynamic model code sequence. 13125ffd83dbSDimitry Andric // 13135ffd83dbSDimitry Andric // *1: https://www.nec.com/en/global/prod/hpc/aurora/document/VE-tls_v1.1.pdf 1314e8d8bef9SDimitry Andric return lowerToTLSGeneralDynamicModel(Op, DAG); 13155ffd83dbSDimitry Andric } 13165ffd83dbSDimitry Andric 1317e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerJumpTable(SDValue Op, SelectionDAG &DAG) const { 1318e8d8bef9SDimitry Andric return makeAddress(Op, DAG); 1319e8d8bef9SDimitry Andric } 1320e8d8bef9SDimitry Andric 1321e8d8bef9SDimitry Andric // Lower a f128 load into two f64 loads. 1322e8d8bef9SDimitry Andric static SDValue lowerLoadF128(SDValue Op, SelectionDAG &DAG) { 1323e8d8bef9SDimitry Andric SDLoc DL(Op); 1324e8d8bef9SDimitry Andric LoadSDNode *LdNode = dyn_cast<LoadSDNode>(Op.getNode()); 1325e8d8bef9SDimitry Andric assert(LdNode && LdNode->getOffset().isUndef() && "Unexpected node type"); 1326bdd1243dSDimitry Andric Align Alignment = LdNode->getAlign(); 1327e8d8bef9SDimitry Andric if (Alignment > 8) 1328bdd1243dSDimitry Andric Alignment = Align(8); 1329e8d8bef9SDimitry Andric 1330e8d8bef9SDimitry Andric SDValue Lo64 = 1331e8d8bef9SDimitry Andric DAG.getLoad(MVT::f64, DL, LdNode->getChain(), LdNode->getBasePtr(), 1332e8d8bef9SDimitry Andric LdNode->getPointerInfo(), Alignment, 1333e8d8bef9SDimitry Andric LdNode->isVolatile() ? MachineMemOperand::MOVolatile 1334e8d8bef9SDimitry Andric : MachineMemOperand::MONone); 1335e8d8bef9SDimitry Andric EVT AddrVT = LdNode->getBasePtr().getValueType(); 1336e8d8bef9SDimitry Andric SDValue HiPtr = DAG.getNode(ISD::ADD, DL, AddrVT, LdNode->getBasePtr(), 1337e8d8bef9SDimitry Andric DAG.getConstant(8, DL, AddrVT)); 1338e8d8bef9SDimitry Andric SDValue Hi64 = 1339e8d8bef9SDimitry Andric DAG.getLoad(MVT::f64, DL, LdNode->getChain(), HiPtr, 1340e8d8bef9SDimitry Andric LdNode->getPointerInfo(), Alignment, 1341e8d8bef9SDimitry Andric LdNode->isVolatile() ? MachineMemOperand::MOVolatile 1342e8d8bef9SDimitry Andric : MachineMemOperand::MONone); 1343e8d8bef9SDimitry Andric 1344e8d8bef9SDimitry Andric SDValue SubRegEven = DAG.getTargetConstant(VE::sub_even, DL, MVT::i32); 1345e8d8bef9SDimitry Andric SDValue SubRegOdd = DAG.getTargetConstant(VE::sub_odd, DL, MVT::i32); 1346e8d8bef9SDimitry Andric 1347e8d8bef9SDimitry Andric // VE stores Hi64 to 8(addr) and Lo64 to 0(addr) 1348e8d8bef9SDimitry Andric SDNode *InFP128 = 1349e8d8bef9SDimitry Andric DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MVT::f128); 1350e8d8bef9SDimitry Andric InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, DL, MVT::f128, 1351e8d8bef9SDimitry Andric SDValue(InFP128, 0), Hi64, SubRegEven); 1352e8d8bef9SDimitry Andric InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, DL, MVT::f128, 1353e8d8bef9SDimitry Andric SDValue(InFP128, 0), Lo64, SubRegOdd); 1354e8d8bef9SDimitry Andric SDValue OutChains[2] = {SDValue(Lo64.getNode(), 1), 1355e8d8bef9SDimitry Andric SDValue(Hi64.getNode(), 1)}; 1356e8d8bef9SDimitry Andric SDValue OutChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); 1357e8d8bef9SDimitry Andric SDValue Ops[2] = {SDValue(InFP128, 0), OutChain}; 1358e8d8bef9SDimitry Andric return DAG.getMergeValues(Ops, DL); 1359e8d8bef9SDimitry Andric } 1360e8d8bef9SDimitry Andric 136181ad6265SDimitry Andric // Lower a vXi1 load into following instructions 136281ad6265SDimitry Andric // LDrii %1, (,%addr) 136381ad6265SDimitry Andric // LVMxir %vm, 0, %1 136481ad6265SDimitry Andric // LDrii %2, 8(,%addr) 136581ad6265SDimitry Andric // LVMxir %vm, 0, %2 136681ad6265SDimitry Andric // ... 136781ad6265SDimitry Andric static SDValue lowerLoadI1(SDValue Op, SelectionDAG &DAG) { 136881ad6265SDimitry Andric SDLoc DL(Op); 136981ad6265SDimitry Andric LoadSDNode *LdNode = dyn_cast<LoadSDNode>(Op.getNode()); 137081ad6265SDimitry Andric assert(LdNode && LdNode->getOffset().isUndef() && "Unexpected node type"); 137181ad6265SDimitry Andric 137281ad6265SDimitry Andric SDValue BasePtr = LdNode->getBasePtr(); 1373bdd1243dSDimitry Andric Align Alignment = LdNode->getAlign(); 137481ad6265SDimitry Andric if (Alignment > 8) 1375bdd1243dSDimitry Andric Alignment = Align(8); 137681ad6265SDimitry Andric 137781ad6265SDimitry Andric EVT AddrVT = BasePtr.getValueType(); 137881ad6265SDimitry Andric EVT MemVT = LdNode->getMemoryVT(); 137981ad6265SDimitry Andric if (MemVT == MVT::v256i1 || MemVT == MVT::v4i64) { 138081ad6265SDimitry Andric SDValue OutChains[4]; 138181ad6265SDimitry Andric SDNode *VM = DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MemVT); 138281ad6265SDimitry Andric for (int i = 0; i < 4; ++i) { 138381ad6265SDimitry Andric // Generate load dag and prepare chains. 138481ad6265SDimitry Andric SDValue Addr = DAG.getNode(ISD::ADD, DL, AddrVT, BasePtr, 138581ad6265SDimitry Andric DAG.getConstant(8 * i, DL, AddrVT)); 138681ad6265SDimitry Andric SDValue Val = 138781ad6265SDimitry Andric DAG.getLoad(MVT::i64, DL, LdNode->getChain(), Addr, 138881ad6265SDimitry Andric LdNode->getPointerInfo(), Alignment, 138981ad6265SDimitry Andric LdNode->isVolatile() ? MachineMemOperand::MOVolatile 139081ad6265SDimitry Andric : MachineMemOperand::MONone); 139181ad6265SDimitry Andric OutChains[i] = SDValue(Val.getNode(), 1); 139281ad6265SDimitry Andric 139381ad6265SDimitry Andric VM = DAG.getMachineNode(VE::LVMir_m, DL, MVT::i64, 139481ad6265SDimitry Andric DAG.getTargetConstant(i, DL, MVT::i64), Val, 139581ad6265SDimitry Andric SDValue(VM, 0)); 139681ad6265SDimitry Andric } 139781ad6265SDimitry Andric SDValue OutChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); 139881ad6265SDimitry Andric SDValue Ops[2] = {SDValue(VM, 0), OutChain}; 139981ad6265SDimitry Andric return DAG.getMergeValues(Ops, DL); 140081ad6265SDimitry Andric } else if (MemVT == MVT::v512i1 || MemVT == MVT::v8i64) { 140181ad6265SDimitry Andric SDValue OutChains[8]; 140281ad6265SDimitry Andric SDNode *VM = DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MemVT); 140381ad6265SDimitry Andric for (int i = 0; i < 8; ++i) { 140481ad6265SDimitry Andric // Generate load dag and prepare chains. 140581ad6265SDimitry Andric SDValue Addr = DAG.getNode(ISD::ADD, DL, AddrVT, BasePtr, 140681ad6265SDimitry Andric DAG.getConstant(8 * i, DL, AddrVT)); 140781ad6265SDimitry Andric SDValue Val = 140881ad6265SDimitry Andric DAG.getLoad(MVT::i64, DL, LdNode->getChain(), Addr, 140981ad6265SDimitry Andric LdNode->getPointerInfo(), Alignment, 141081ad6265SDimitry Andric LdNode->isVolatile() ? MachineMemOperand::MOVolatile 141181ad6265SDimitry Andric : MachineMemOperand::MONone); 141281ad6265SDimitry Andric OutChains[i] = SDValue(Val.getNode(), 1); 141381ad6265SDimitry Andric 141481ad6265SDimitry Andric VM = DAG.getMachineNode(VE::LVMyir_y, DL, MVT::i64, 141581ad6265SDimitry Andric DAG.getTargetConstant(i, DL, MVT::i64), Val, 141681ad6265SDimitry Andric SDValue(VM, 0)); 141781ad6265SDimitry Andric } 141881ad6265SDimitry Andric SDValue OutChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); 141981ad6265SDimitry Andric SDValue Ops[2] = {SDValue(VM, 0), OutChain}; 142081ad6265SDimitry Andric return DAG.getMergeValues(Ops, DL); 142181ad6265SDimitry Andric } else { 142281ad6265SDimitry Andric // Otherwise, ask llvm to expand it. 142381ad6265SDimitry Andric return SDValue(); 142481ad6265SDimitry Andric } 142581ad6265SDimitry Andric } 142681ad6265SDimitry Andric 1427e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const { 1428e8d8bef9SDimitry Andric LoadSDNode *LdNode = cast<LoadSDNode>(Op.getNode()); 142981ad6265SDimitry Andric EVT MemVT = LdNode->getMemoryVT(); 143081ad6265SDimitry Andric 14315f757f3fSDimitry Andric // If VPU is enabled, always expand non-mask vector loads to VVP 14325f757f3fSDimitry Andric if (Subtarget->enableVPU() && MemVT.isVector() && !isMaskType(MemVT)) 143381ad6265SDimitry Andric return lowerToVVP(Op, DAG); 143481ad6265SDimitry Andric 1435e8d8bef9SDimitry Andric SDValue BasePtr = LdNode->getBasePtr(); 1436e8d8bef9SDimitry Andric if (isa<FrameIndexSDNode>(BasePtr.getNode())) { 1437e8d8bef9SDimitry Andric // Do not expand store instruction with frame index here because of 1438e8d8bef9SDimitry Andric // dependency problems. We expand it later in eliminateFrameIndex(). 1439e8d8bef9SDimitry Andric return Op; 1440e8d8bef9SDimitry Andric } 1441e8d8bef9SDimitry Andric 1442e8d8bef9SDimitry Andric if (MemVT == MVT::f128) 1443e8d8bef9SDimitry Andric return lowerLoadF128(Op, DAG); 144481ad6265SDimitry Andric if (isMaskType(MemVT)) 144581ad6265SDimitry Andric return lowerLoadI1(Op, DAG); 1446e8d8bef9SDimitry Andric 1447e8d8bef9SDimitry Andric return Op; 1448e8d8bef9SDimitry Andric } 1449e8d8bef9SDimitry Andric 1450e8d8bef9SDimitry Andric // Lower a f128 store into two f64 stores. 1451e8d8bef9SDimitry Andric static SDValue lowerStoreF128(SDValue Op, SelectionDAG &DAG) { 1452e8d8bef9SDimitry Andric SDLoc DL(Op); 1453e8d8bef9SDimitry Andric StoreSDNode *StNode = dyn_cast<StoreSDNode>(Op.getNode()); 1454e8d8bef9SDimitry Andric assert(StNode && StNode->getOffset().isUndef() && "Unexpected node type"); 1455e8d8bef9SDimitry Andric 1456e8d8bef9SDimitry Andric SDValue SubRegEven = DAG.getTargetConstant(VE::sub_even, DL, MVT::i32); 1457e8d8bef9SDimitry Andric SDValue SubRegOdd = DAG.getTargetConstant(VE::sub_odd, DL, MVT::i32); 1458e8d8bef9SDimitry Andric 1459e8d8bef9SDimitry Andric SDNode *Hi64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, MVT::i64, 1460e8d8bef9SDimitry Andric StNode->getValue(), SubRegEven); 1461e8d8bef9SDimitry Andric SDNode *Lo64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, MVT::i64, 1462e8d8bef9SDimitry Andric StNode->getValue(), SubRegOdd); 1463e8d8bef9SDimitry Andric 1464bdd1243dSDimitry Andric Align Alignment = StNode->getAlign(); 1465e8d8bef9SDimitry Andric if (Alignment > 8) 1466bdd1243dSDimitry Andric Alignment = Align(8); 1467e8d8bef9SDimitry Andric 1468e8d8bef9SDimitry Andric // VE stores Hi64 to 8(addr) and Lo64 to 0(addr) 1469e8d8bef9SDimitry Andric SDValue OutChains[2]; 1470e8d8bef9SDimitry Andric OutChains[0] = 1471e8d8bef9SDimitry Andric DAG.getStore(StNode->getChain(), DL, SDValue(Lo64, 0), 1472e8d8bef9SDimitry Andric StNode->getBasePtr(), MachinePointerInfo(), Alignment, 1473e8d8bef9SDimitry Andric StNode->isVolatile() ? MachineMemOperand::MOVolatile 1474e8d8bef9SDimitry Andric : MachineMemOperand::MONone); 1475e8d8bef9SDimitry Andric EVT AddrVT = StNode->getBasePtr().getValueType(); 1476e8d8bef9SDimitry Andric SDValue HiPtr = DAG.getNode(ISD::ADD, DL, AddrVT, StNode->getBasePtr(), 1477e8d8bef9SDimitry Andric DAG.getConstant(8, DL, AddrVT)); 1478e8d8bef9SDimitry Andric OutChains[1] = 1479e8d8bef9SDimitry Andric DAG.getStore(StNode->getChain(), DL, SDValue(Hi64, 0), HiPtr, 1480e8d8bef9SDimitry Andric MachinePointerInfo(), Alignment, 1481e8d8bef9SDimitry Andric StNode->isVolatile() ? MachineMemOperand::MOVolatile 1482e8d8bef9SDimitry Andric : MachineMemOperand::MONone); 1483e8d8bef9SDimitry Andric return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); 1484e8d8bef9SDimitry Andric } 1485e8d8bef9SDimitry Andric 148681ad6265SDimitry Andric // Lower a vXi1 store into following instructions 148781ad6265SDimitry Andric // SVMi %1, %vm, 0 148881ad6265SDimitry Andric // STrii %1, (,%addr) 148981ad6265SDimitry Andric // SVMi %2, %vm, 1 149081ad6265SDimitry Andric // STrii %2, 8(,%addr) 149181ad6265SDimitry Andric // ... 149281ad6265SDimitry Andric static SDValue lowerStoreI1(SDValue Op, SelectionDAG &DAG) { 149381ad6265SDimitry Andric SDLoc DL(Op); 149481ad6265SDimitry Andric StoreSDNode *StNode = dyn_cast<StoreSDNode>(Op.getNode()); 149581ad6265SDimitry Andric assert(StNode && StNode->getOffset().isUndef() && "Unexpected node type"); 149681ad6265SDimitry Andric 149781ad6265SDimitry Andric SDValue BasePtr = StNode->getBasePtr(); 1498bdd1243dSDimitry Andric Align Alignment = StNode->getAlign(); 149981ad6265SDimitry Andric if (Alignment > 8) 1500bdd1243dSDimitry Andric Alignment = Align(8); 150181ad6265SDimitry Andric EVT AddrVT = BasePtr.getValueType(); 150281ad6265SDimitry Andric EVT MemVT = StNode->getMemoryVT(); 150381ad6265SDimitry Andric if (MemVT == MVT::v256i1 || MemVT == MVT::v4i64) { 150481ad6265SDimitry Andric SDValue OutChains[4]; 150581ad6265SDimitry Andric for (int i = 0; i < 4; ++i) { 150681ad6265SDimitry Andric SDNode *V = 150781ad6265SDimitry Andric DAG.getMachineNode(VE::SVMmi, DL, MVT::i64, StNode->getValue(), 150881ad6265SDimitry Andric DAG.getTargetConstant(i, DL, MVT::i64)); 150981ad6265SDimitry Andric SDValue Addr = DAG.getNode(ISD::ADD, DL, AddrVT, BasePtr, 151081ad6265SDimitry Andric DAG.getConstant(8 * i, DL, AddrVT)); 151181ad6265SDimitry Andric OutChains[i] = 151281ad6265SDimitry Andric DAG.getStore(StNode->getChain(), DL, SDValue(V, 0), Addr, 151381ad6265SDimitry Andric MachinePointerInfo(), Alignment, 151481ad6265SDimitry Andric StNode->isVolatile() ? MachineMemOperand::MOVolatile 151581ad6265SDimitry Andric : MachineMemOperand::MONone); 151681ad6265SDimitry Andric } 151781ad6265SDimitry Andric return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); 151881ad6265SDimitry Andric } else if (MemVT == MVT::v512i1 || MemVT == MVT::v8i64) { 151981ad6265SDimitry Andric SDValue OutChains[8]; 152081ad6265SDimitry Andric for (int i = 0; i < 8; ++i) { 152181ad6265SDimitry Andric SDNode *V = 152281ad6265SDimitry Andric DAG.getMachineNode(VE::SVMyi, DL, MVT::i64, StNode->getValue(), 152381ad6265SDimitry Andric DAG.getTargetConstant(i, DL, MVT::i64)); 152481ad6265SDimitry Andric SDValue Addr = DAG.getNode(ISD::ADD, DL, AddrVT, BasePtr, 152581ad6265SDimitry Andric DAG.getConstant(8 * i, DL, AddrVT)); 152681ad6265SDimitry Andric OutChains[i] = 152781ad6265SDimitry Andric DAG.getStore(StNode->getChain(), DL, SDValue(V, 0), Addr, 152881ad6265SDimitry Andric MachinePointerInfo(), Alignment, 152981ad6265SDimitry Andric StNode->isVolatile() ? MachineMemOperand::MOVolatile 153081ad6265SDimitry Andric : MachineMemOperand::MONone); 153181ad6265SDimitry Andric } 153281ad6265SDimitry Andric return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); 153381ad6265SDimitry Andric } else { 153481ad6265SDimitry Andric // Otherwise, ask llvm to expand it. 153581ad6265SDimitry Andric return SDValue(); 153681ad6265SDimitry Andric } 153781ad6265SDimitry Andric } 153881ad6265SDimitry Andric 1539e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const { 1540e8d8bef9SDimitry Andric StoreSDNode *StNode = cast<StoreSDNode>(Op.getNode()); 1541e8d8bef9SDimitry Andric assert(StNode && StNode->getOffset().isUndef() && "Unexpected node type"); 154281ad6265SDimitry Andric EVT MemVT = StNode->getMemoryVT(); 15435f757f3fSDimitry Andric 15445f757f3fSDimitry Andric // If VPU is enabled, always expand non-mask vector stores to VVP 15455f757f3fSDimitry Andric if (Subtarget->enableVPU() && MemVT.isVector() && !isMaskType(MemVT)) 154681ad6265SDimitry Andric return lowerToVVP(Op, DAG); 154781ad6265SDimitry Andric 1548e8d8bef9SDimitry Andric SDValue BasePtr = StNode->getBasePtr(); 1549e8d8bef9SDimitry Andric if (isa<FrameIndexSDNode>(BasePtr.getNode())) { 1550e8d8bef9SDimitry Andric // Do not expand store instruction with frame index here because of 1551e8d8bef9SDimitry Andric // dependency problems. We expand it later in eliminateFrameIndex(). 1552e8d8bef9SDimitry Andric return Op; 1553e8d8bef9SDimitry Andric } 1554e8d8bef9SDimitry Andric 1555e8d8bef9SDimitry Andric if (MemVT == MVT::f128) 1556e8d8bef9SDimitry Andric return lowerStoreF128(Op, DAG); 155781ad6265SDimitry Andric if (isMaskType(MemVT)) 155881ad6265SDimitry Andric return lowerStoreI1(Op, DAG); 1559e8d8bef9SDimitry Andric 1560e8d8bef9SDimitry Andric // Otherwise, ask llvm to expand it. 1561e8d8bef9SDimitry Andric return SDValue(); 1562e8d8bef9SDimitry Andric } 1563e8d8bef9SDimitry Andric 1564e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const { 15655ffd83dbSDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 15665ffd83dbSDimitry Andric VEMachineFunctionInfo *FuncInfo = MF.getInfo<VEMachineFunctionInfo>(); 15675ffd83dbSDimitry Andric auto PtrVT = getPointerTy(DAG.getDataLayout()); 15685ffd83dbSDimitry Andric 15695ffd83dbSDimitry Andric // Need frame address to find the address of VarArgsFrameIndex. 15705ffd83dbSDimitry Andric MF.getFrameInfo().setFrameAddressIsTaken(true); 15715ffd83dbSDimitry Andric 15725ffd83dbSDimitry Andric // vastart just stores the address of the VarArgsFrameIndex slot into the 15735ffd83dbSDimitry Andric // memory location argument. 15745ffd83dbSDimitry Andric SDLoc DL(Op); 15755ffd83dbSDimitry Andric SDValue Offset = 15765ffd83dbSDimitry Andric DAG.getNode(ISD::ADD, DL, PtrVT, DAG.getRegister(VE::SX9, PtrVT), 15775ffd83dbSDimitry Andric DAG.getIntPtrConstant(FuncInfo->getVarArgsFrameOffset(), DL)); 15785ffd83dbSDimitry Andric const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); 15795ffd83dbSDimitry Andric return DAG.getStore(Op.getOperand(0), DL, Offset, Op.getOperand(1), 15805ffd83dbSDimitry Andric MachinePointerInfo(SV)); 15815ffd83dbSDimitry Andric } 15825ffd83dbSDimitry Andric 1583e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const { 15845ffd83dbSDimitry Andric SDNode *Node = Op.getNode(); 15855ffd83dbSDimitry Andric EVT VT = Node->getValueType(0); 15865ffd83dbSDimitry Andric SDValue InChain = Node->getOperand(0); 15875ffd83dbSDimitry Andric SDValue VAListPtr = Node->getOperand(1); 15885ffd83dbSDimitry Andric EVT PtrVT = VAListPtr.getValueType(); 15895ffd83dbSDimitry Andric const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue(); 15905ffd83dbSDimitry Andric SDLoc DL(Node); 15915ffd83dbSDimitry Andric SDValue VAList = 15925ffd83dbSDimitry Andric DAG.getLoad(PtrVT, DL, InChain, VAListPtr, MachinePointerInfo(SV)); 15935ffd83dbSDimitry Andric SDValue Chain = VAList.getValue(1); 15945ffd83dbSDimitry Andric SDValue NextPtr; 15955ffd83dbSDimitry Andric 1596e8d8bef9SDimitry Andric if (VT == MVT::f128) { 159781ad6265SDimitry Andric // VE f128 values must be stored with 16 bytes alignment. We don't 1598e8d8bef9SDimitry Andric // know the actual alignment of VAList, so we take alignment of it 159981ad6265SDimitry Andric // dynamically. 1600e8d8bef9SDimitry Andric int Align = 16; 1601e8d8bef9SDimitry Andric VAList = DAG.getNode(ISD::ADD, DL, PtrVT, VAList, 1602e8d8bef9SDimitry Andric DAG.getConstant(Align - 1, DL, PtrVT)); 1603e8d8bef9SDimitry Andric VAList = DAG.getNode(ISD::AND, DL, PtrVT, VAList, 1604e8d8bef9SDimitry Andric DAG.getConstant(-Align, DL, PtrVT)); 1605e8d8bef9SDimitry Andric // Increment the pointer, VAList, by 16 to the next vaarg. 1606e8d8bef9SDimitry Andric NextPtr = 1607e8d8bef9SDimitry Andric DAG.getNode(ISD::ADD, DL, PtrVT, VAList, DAG.getIntPtrConstant(16, DL)); 1608e8d8bef9SDimitry Andric } else if (VT == MVT::f32) { 16095ffd83dbSDimitry Andric // float --> need special handling like below. 16105ffd83dbSDimitry Andric // 0 4 16115ffd83dbSDimitry Andric // +------+------+ 16125ffd83dbSDimitry Andric // | empty| float| 16135ffd83dbSDimitry Andric // +------+------+ 16145ffd83dbSDimitry Andric // Increment the pointer, VAList, by 8 to the next vaarg. 16155ffd83dbSDimitry Andric NextPtr = 16165ffd83dbSDimitry Andric DAG.getNode(ISD::ADD, DL, PtrVT, VAList, DAG.getIntPtrConstant(8, DL)); 16175ffd83dbSDimitry Andric // Then, adjust VAList. 16185ffd83dbSDimitry Andric unsigned InternalOffset = 4; 16195ffd83dbSDimitry Andric VAList = DAG.getNode(ISD::ADD, DL, PtrVT, VAList, 16205ffd83dbSDimitry Andric DAG.getConstant(InternalOffset, DL, PtrVT)); 16215ffd83dbSDimitry Andric } else { 16225ffd83dbSDimitry Andric // Increment the pointer, VAList, by 8 to the next vaarg. 16235ffd83dbSDimitry Andric NextPtr = 16245ffd83dbSDimitry Andric DAG.getNode(ISD::ADD, DL, PtrVT, VAList, DAG.getIntPtrConstant(8, DL)); 16255ffd83dbSDimitry Andric } 16265ffd83dbSDimitry Andric 16275ffd83dbSDimitry Andric // Store the incremented VAList to the legalized pointer. 16285ffd83dbSDimitry Andric InChain = DAG.getStore(Chain, DL, NextPtr, VAListPtr, MachinePointerInfo(SV)); 16295ffd83dbSDimitry Andric 16305ffd83dbSDimitry Andric // Load the actual argument out of the pointer VAList. 16315ffd83dbSDimitry Andric // We can't count on greater alignment than the word size. 1632bdd1243dSDimitry Andric return DAG.getLoad( 1633bdd1243dSDimitry Andric VT, DL, InChain, VAList, MachinePointerInfo(), 1634bdd1243dSDimitry Andric Align(std::min(PtrVT.getSizeInBits(), VT.getSizeInBits()) / 8)); 16355ffd83dbSDimitry Andric } 16365ffd83dbSDimitry Andric 16375ffd83dbSDimitry Andric SDValue VETargetLowering::lowerDYNAMIC_STACKALLOC(SDValue Op, 16385ffd83dbSDimitry Andric SelectionDAG &DAG) const { 16395ffd83dbSDimitry Andric // Generate following code. 16405ffd83dbSDimitry Andric // (void)__llvm_grow_stack(size); 16415ffd83dbSDimitry Andric // ret = GETSTACKTOP; // pseudo instruction 16425ffd83dbSDimitry Andric SDLoc DL(Op); 16435ffd83dbSDimitry Andric 16445ffd83dbSDimitry Andric // Get the inputs. 16455ffd83dbSDimitry Andric SDNode *Node = Op.getNode(); 16465ffd83dbSDimitry Andric SDValue Chain = Op.getOperand(0); 16475ffd83dbSDimitry Andric SDValue Size = Op.getOperand(1); 16485ffd83dbSDimitry Andric MaybeAlign Alignment(Op.getConstantOperandVal(2)); 16495ffd83dbSDimitry Andric EVT VT = Node->getValueType(0); 16505ffd83dbSDimitry Andric 16515ffd83dbSDimitry Andric // Chain the dynamic stack allocation so that it doesn't modify the stack 16525ffd83dbSDimitry Andric // pointer when other instructions are using the stack. 16535ffd83dbSDimitry Andric Chain = DAG.getCALLSEQ_START(Chain, 0, 0, DL); 16545ffd83dbSDimitry Andric 16555ffd83dbSDimitry Andric const TargetFrameLowering &TFI = *Subtarget->getFrameLowering(); 16565ffd83dbSDimitry Andric Align StackAlign = TFI.getStackAlign(); 16575ffd83dbSDimitry Andric bool NeedsAlign = Alignment.valueOrOne() > StackAlign; 16585ffd83dbSDimitry Andric 16595ffd83dbSDimitry Andric // Prepare arguments 16605ffd83dbSDimitry Andric TargetLowering::ArgListTy Args; 16615ffd83dbSDimitry Andric TargetLowering::ArgListEntry Entry; 16625ffd83dbSDimitry Andric Entry.Node = Size; 16635ffd83dbSDimitry Andric Entry.Ty = Entry.Node.getValueType().getTypeForEVT(*DAG.getContext()); 16645ffd83dbSDimitry Andric Args.push_back(Entry); 16655ffd83dbSDimitry Andric if (NeedsAlign) { 16665ffd83dbSDimitry Andric Entry.Node = DAG.getConstant(~(Alignment->value() - 1ULL), DL, VT); 16675ffd83dbSDimitry Andric Entry.Ty = Entry.Node.getValueType().getTypeForEVT(*DAG.getContext()); 16685ffd83dbSDimitry Andric Args.push_back(Entry); 16695ffd83dbSDimitry Andric } 16705ffd83dbSDimitry Andric Type *RetTy = Type::getVoidTy(*DAG.getContext()); 16715ffd83dbSDimitry Andric 16725ffd83dbSDimitry Andric EVT PtrVT = Op.getValueType(); 16735ffd83dbSDimitry Andric SDValue Callee; 16745ffd83dbSDimitry Andric if (NeedsAlign) { 16755ffd83dbSDimitry Andric Callee = DAG.getTargetExternalSymbol("__ve_grow_stack_align", PtrVT, 0); 16765ffd83dbSDimitry Andric } else { 16775ffd83dbSDimitry Andric Callee = DAG.getTargetExternalSymbol("__ve_grow_stack", PtrVT, 0); 16785ffd83dbSDimitry Andric } 16795ffd83dbSDimitry Andric 16805ffd83dbSDimitry Andric TargetLowering::CallLoweringInfo CLI(DAG); 16815ffd83dbSDimitry Andric CLI.setDebugLoc(DL) 16825ffd83dbSDimitry Andric .setChain(Chain) 16835ffd83dbSDimitry Andric .setCallee(CallingConv::PreserveAll, RetTy, Callee, std::move(Args)) 16845ffd83dbSDimitry Andric .setDiscardResult(true); 16855ffd83dbSDimitry Andric std::pair<SDValue, SDValue> pair = LowerCallTo(CLI); 16865ffd83dbSDimitry Andric Chain = pair.second; 16875ffd83dbSDimitry Andric SDValue Result = DAG.getNode(VEISD::GETSTACKTOP, DL, VT, Chain); 16885ffd83dbSDimitry Andric if (NeedsAlign) { 16895ffd83dbSDimitry Andric Result = DAG.getNode(ISD::ADD, DL, VT, Result, 16905ffd83dbSDimitry Andric DAG.getConstant((Alignment->value() - 1ULL), DL, VT)); 16915ffd83dbSDimitry Andric Result = DAG.getNode(ISD::AND, DL, VT, Result, 16925ffd83dbSDimitry Andric DAG.getConstant(~(Alignment->value() - 1ULL), DL, VT)); 16935ffd83dbSDimitry Andric } 16945ffd83dbSDimitry Andric // Chain = Result.getValue(1); 1695bdd1243dSDimitry Andric Chain = DAG.getCALLSEQ_END(Chain, 0, 0, SDValue(), DL); 16965ffd83dbSDimitry Andric 16975ffd83dbSDimitry Andric SDValue Ops[2] = {Result, Chain}; 16985ffd83dbSDimitry Andric return DAG.getMergeValues(Ops, DL); 16995ffd83dbSDimitry Andric } 17005ffd83dbSDimitry Andric 1701e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerEH_SJLJ_LONGJMP(SDValue Op, 1702e8d8bef9SDimitry Andric SelectionDAG &DAG) const { 1703e8d8bef9SDimitry Andric SDLoc DL(Op); 1704e8d8bef9SDimitry Andric return DAG.getNode(VEISD::EH_SJLJ_LONGJMP, DL, MVT::Other, Op.getOperand(0), 1705e8d8bef9SDimitry Andric Op.getOperand(1)); 1706e8d8bef9SDimitry Andric } 1707e8d8bef9SDimitry Andric 1708e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerEH_SJLJ_SETJMP(SDValue Op, 1709e8d8bef9SDimitry Andric SelectionDAG &DAG) const { 1710e8d8bef9SDimitry Andric SDLoc DL(Op); 1711e8d8bef9SDimitry Andric return DAG.getNode(VEISD::EH_SJLJ_SETJMP, DL, 1712e8d8bef9SDimitry Andric DAG.getVTList(MVT::i32, MVT::Other), Op.getOperand(0), 1713e8d8bef9SDimitry Andric Op.getOperand(1)); 1714e8d8bef9SDimitry Andric } 1715e8d8bef9SDimitry Andric 1716e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerEH_SJLJ_SETUP_DISPATCH(SDValue Op, 1717e8d8bef9SDimitry Andric SelectionDAG &DAG) const { 1718e8d8bef9SDimitry Andric SDLoc DL(Op); 1719e8d8bef9SDimitry Andric return DAG.getNode(VEISD::EH_SJLJ_SETUP_DISPATCH, DL, MVT::Other, 1720e8d8bef9SDimitry Andric Op.getOperand(0)); 1721e8d8bef9SDimitry Andric } 1722e8d8bef9SDimitry Andric 1723e8d8bef9SDimitry Andric static SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG, 1724e8d8bef9SDimitry Andric const VETargetLowering &TLI, 1725e8d8bef9SDimitry Andric const VESubtarget *Subtarget) { 1726e8d8bef9SDimitry Andric SDLoc DL(Op); 1727e8d8bef9SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 1728e8d8bef9SDimitry Andric EVT PtrVT = TLI.getPointerTy(MF.getDataLayout()); 1729e8d8bef9SDimitry Andric 1730e8d8bef9SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 1731e8d8bef9SDimitry Andric MFI.setFrameAddressIsTaken(true); 1732e8d8bef9SDimitry Andric 1733e8d8bef9SDimitry Andric unsigned Depth = Op.getConstantOperandVal(0); 1734e8d8bef9SDimitry Andric const VERegisterInfo *RegInfo = Subtarget->getRegisterInfo(); 173504eeddc0SDimitry Andric Register FrameReg = RegInfo->getFrameRegister(MF); 1736e8d8bef9SDimitry Andric SDValue FrameAddr = 1737e8d8bef9SDimitry Andric DAG.getCopyFromReg(DAG.getEntryNode(), DL, FrameReg, PtrVT); 1738e8d8bef9SDimitry Andric while (Depth--) 1739e8d8bef9SDimitry Andric FrameAddr = DAG.getLoad(Op.getValueType(), DL, DAG.getEntryNode(), 1740e8d8bef9SDimitry Andric FrameAddr, MachinePointerInfo()); 1741e8d8bef9SDimitry Andric return FrameAddr; 1742e8d8bef9SDimitry Andric } 1743e8d8bef9SDimitry Andric 1744e8d8bef9SDimitry Andric static SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG, 1745e8d8bef9SDimitry Andric const VETargetLowering &TLI, 1746e8d8bef9SDimitry Andric const VESubtarget *Subtarget) { 1747e8d8bef9SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 1748e8d8bef9SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 1749e8d8bef9SDimitry Andric MFI.setReturnAddressIsTaken(true); 1750e8d8bef9SDimitry Andric 1751e8d8bef9SDimitry Andric if (TLI.verifyReturnAddressArgumentIsConstant(Op, DAG)) 1752e8d8bef9SDimitry Andric return SDValue(); 1753e8d8bef9SDimitry Andric 1754e8d8bef9SDimitry Andric SDValue FrameAddr = lowerFRAMEADDR(Op, DAG, TLI, Subtarget); 1755e8d8bef9SDimitry Andric 1756e8d8bef9SDimitry Andric SDLoc DL(Op); 1757e8d8bef9SDimitry Andric EVT VT = Op.getValueType(); 1758e8d8bef9SDimitry Andric SDValue Offset = DAG.getConstant(8, DL, VT); 1759e8d8bef9SDimitry Andric return DAG.getLoad(VT, DL, DAG.getEntryNode(), 1760e8d8bef9SDimitry Andric DAG.getNode(ISD::ADD, DL, VT, FrameAddr, Offset), 1761e8d8bef9SDimitry Andric MachinePointerInfo()); 1762e8d8bef9SDimitry Andric } 1763e8d8bef9SDimitry Andric 1764e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, 1765e8d8bef9SDimitry Andric SelectionDAG &DAG) const { 1766e8d8bef9SDimitry Andric SDLoc DL(Op); 1767647cbc5dSDimitry Andric unsigned IntNo = Op.getConstantOperandVal(0); 1768e8d8bef9SDimitry Andric switch (IntNo) { 1769e8d8bef9SDimitry Andric default: // Don't custom lower most intrinsics. 1770e8d8bef9SDimitry Andric return SDValue(); 1771e8d8bef9SDimitry Andric case Intrinsic::eh_sjlj_lsda: { 1772e8d8bef9SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 1773e8d8bef9SDimitry Andric MVT VT = Op.getSimpleValueType(); 1774e8d8bef9SDimitry Andric const VETargetMachine *TM = 1775e8d8bef9SDimitry Andric static_cast<const VETargetMachine *>(&DAG.getTarget()); 1776e8d8bef9SDimitry Andric 1777e8d8bef9SDimitry Andric // Create GCC_except_tableXX string. The real symbol for that will be 1778e8d8bef9SDimitry Andric // generated in EHStreamer::emitExceptionTable() later. So, we just 1779e8d8bef9SDimitry Andric // borrow it's name here. 1780e8d8bef9SDimitry Andric TM->getStrList()->push_back(std::string( 1781e8d8bef9SDimitry Andric (Twine("GCC_except_table") + Twine(MF.getFunctionNumber())).str())); 1782e8d8bef9SDimitry Andric SDValue Addr = 1783e8d8bef9SDimitry Andric DAG.getTargetExternalSymbol(TM->getStrList()->back().c_str(), VT, 0); 1784e8d8bef9SDimitry Andric if (isPositionIndependent()) { 1785e8d8bef9SDimitry Andric Addr = makeHiLoPair(Addr, VEMCExpr::VK_VE_GOTOFF_HI32, 1786e8d8bef9SDimitry Andric VEMCExpr::VK_VE_GOTOFF_LO32, DAG); 1787e8d8bef9SDimitry Andric SDValue GlobalBase = DAG.getNode(VEISD::GLOBAL_BASE_REG, DL, VT); 1788e8d8bef9SDimitry Andric return DAG.getNode(ISD::ADD, DL, VT, GlobalBase, Addr); 1789e8d8bef9SDimitry Andric } 1790e8d8bef9SDimitry Andric return makeHiLoPair(Addr, VEMCExpr::VK_VE_HI32, VEMCExpr::VK_VE_LO32, DAG); 1791e8d8bef9SDimitry Andric } 1792e8d8bef9SDimitry Andric } 1793e8d8bef9SDimitry Andric } 1794e8d8bef9SDimitry Andric 1795e8d8bef9SDimitry Andric static bool getUniqueInsertion(SDNode *N, unsigned &UniqueIdx) { 1796e8d8bef9SDimitry Andric if (!isa<BuildVectorSDNode>(N)) 1797e8d8bef9SDimitry Andric return false; 1798e8d8bef9SDimitry Andric const auto *BVN = cast<BuildVectorSDNode>(N); 1799e8d8bef9SDimitry Andric 1800e8d8bef9SDimitry Andric // Find first non-undef insertion. 1801e8d8bef9SDimitry Andric unsigned Idx; 1802e8d8bef9SDimitry Andric for (Idx = 0; Idx < BVN->getNumOperands(); ++Idx) { 1803e8d8bef9SDimitry Andric auto ElemV = BVN->getOperand(Idx); 1804e8d8bef9SDimitry Andric if (!ElemV->isUndef()) 1805e8d8bef9SDimitry Andric break; 1806e8d8bef9SDimitry Andric } 1807e8d8bef9SDimitry Andric // Catch the (hypothetical) all-undef case. 1808e8d8bef9SDimitry Andric if (Idx == BVN->getNumOperands()) 1809e8d8bef9SDimitry Andric return false; 1810e8d8bef9SDimitry Andric // Remember insertion. 1811e8d8bef9SDimitry Andric UniqueIdx = Idx++; 1812e8d8bef9SDimitry Andric // Verify that all other insertions are undef. 1813e8d8bef9SDimitry Andric for (; Idx < BVN->getNumOperands(); ++Idx) { 1814e8d8bef9SDimitry Andric auto ElemV = BVN->getOperand(Idx); 1815e8d8bef9SDimitry Andric if (!ElemV->isUndef()) 1816e8d8bef9SDimitry Andric return false; 1817e8d8bef9SDimitry Andric } 1818e8d8bef9SDimitry Andric return true; 1819e8d8bef9SDimitry Andric } 1820e8d8bef9SDimitry Andric 1821e8d8bef9SDimitry Andric static SDValue getSplatValue(SDNode *N) { 1822e8d8bef9SDimitry Andric if (auto *BuildVec = dyn_cast<BuildVectorSDNode>(N)) { 1823e8d8bef9SDimitry Andric return BuildVec->getSplatValue(); 1824e8d8bef9SDimitry Andric } 1825e8d8bef9SDimitry Andric return SDValue(); 1826e8d8bef9SDimitry Andric } 1827e8d8bef9SDimitry Andric 1828e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerBUILD_VECTOR(SDValue Op, 1829e8d8bef9SDimitry Andric SelectionDAG &DAG) const { 183004eeddc0SDimitry Andric VECustomDAG CDAG(DAG, Op); 183104eeddc0SDimitry Andric MVT ResultVT = Op.getSimpleValueType(); 1832e8d8bef9SDimitry Andric 1833e8d8bef9SDimitry Andric // If there is just one element, expand to INSERT_VECTOR_ELT. 1834e8d8bef9SDimitry Andric unsigned UniqueIdx; 1835e8d8bef9SDimitry Andric if (getUniqueInsertion(Op.getNode(), UniqueIdx)) { 183604eeddc0SDimitry Andric SDValue AccuV = CDAG.getUNDEF(Op.getValueType()); 1837e8d8bef9SDimitry Andric auto ElemV = Op->getOperand(UniqueIdx); 183804eeddc0SDimitry Andric SDValue IdxV = CDAG.getConstant(UniqueIdx, MVT::i64); 183904eeddc0SDimitry Andric return CDAG.getNode(ISD::INSERT_VECTOR_ELT, ResultVT, {AccuV, ElemV, IdxV}); 1840e8d8bef9SDimitry Andric } 1841e8d8bef9SDimitry Andric 1842e8d8bef9SDimitry Andric // Else emit a broadcast. 1843e8d8bef9SDimitry Andric if (SDValue ScalarV = getSplatValue(Op.getNode())) { 184404eeddc0SDimitry Andric unsigned NumEls = ResultVT.getVectorNumElements(); 184581ad6265SDimitry Andric auto AVL = CDAG.getConstant(NumEls, MVT::i32); 184681ad6265SDimitry Andric return CDAG.getBroadcast(ResultVT, ScalarV, AVL); 1847e8d8bef9SDimitry Andric } 1848e8d8bef9SDimitry Andric 1849e8d8bef9SDimitry Andric // Expand 1850e8d8bef9SDimitry Andric return SDValue(); 1851e8d8bef9SDimitry Andric } 1852e8d8bef9SDimitry Andric 185381ad6265SDimitry Andric TargetLowering::LegalizeAction 185481ad6265SDimitry Andric VETargetLowering::getCustomOperationAction(SDNode &Op) const { 185581ad6265SDimitry Andric // Custom legalization on VVP_* and VEC_* opcodes is required to pack-legalize 185681ad6265SDimitry Andric // these operations (transform nodes such that their AVL parameter refers to 185781ad6265SDimitry Andric // packs of 64bit, instead of number of elements. 1858e8d8bef9SDimitry Andric 185981ad6265SDimitry Andric // Packing opcodes are created with a pack-legal AVL (LEGALAVL). No need to 186081ad6265SDimitry Andric // re-visit them. 186181ad6265SDimitry Andric if (isPackingSupportOpcode(Op.getOpcode())) 186281ad6265SDimitry Andric return Legal; 186381ad6265SDimitry Andric 186481ad6265SDimitry Andric // Custom lower to legalize AVL for packed mode. 186581ad6265SDimitry Andric if (isVVPOrVEC(Op.getOpcode())) 186681ad6265SDimitry Andric return Custom; 186781ad6265SDimitry Andric return Legal; 186881ad6265SDimitry Andric } 186981ad6265SDimitry Andric 187081ad6265SDimitry Andric SDValue VETargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { 18715f757f3fSDimitry Andric LLVM_DEBUG(dbgs() << "::LowerOperation "; Op.dump(&DAG)); 187281ad6265SDimitry Andric unsigned Opcode = Op.getOpcode(); 187381ad6265SDimitry Andric 187481ad6265SDimitry Andric /// Scalar isel. 1875e8d8bef9SDimitry Andric switch (Opcode) { 1876e8d8bef9SDimitry Andric case ISD::ATOMIC_FENCE: 1877e8d8bef9SDimitry Andric return lowerATOMIC_FENCE(Op, DAG); 1878e8d8bef9SDimitry Andric case ISD::ATOMIC_SWAP: 1879e8d8bef9SDimitry Andric return lowerATOMIC_SWAP(Op, DAG); 18805ffd83dbSDimitry Andric case ISD::BlockAddress: 1881e8d8bef9SDimitry Andric return lowerBlockAddress(Op, DAG); 1882e8d8bef9SDimitry Andric case ISD::ConstantPool: 1883e8d8bef9SDimitry Andric return lowerConstantPool(Op, DAG); 18845ffd83dbSDimitry Andric case ISD::DYNAMIC_STACKALLOC: 18855ffd83dbSDimitry Andric return lowerDYNAMIC_STACKALLOC(Op, DAG); 1886e8d8bef9SDimitry Andric case ISD::EH_SJLJ_LONGJMP: 1887e8d8bef9SDimitry Andric return lowerEH_SJLJ_LONGJMP(Op, DAG); 1888e8d8bef9SDimitry Andric case ISD::EH_SJLJ_SETJMP: 1889e8d8bef9SDimitry Andric return lowerEH_SJLJ_SETJMP(Op, DAG); 1890e8d8bef9SDimitry Andric case ISD::EH_SJLJ_SETUP_DISPATCH: 1891e8d8bef9SDimitry Andric return lowerEH_SJLJ_SETUP_DISPATCH(Op, DAG); 1892e8d8bef9SDimitry Andric case ISD::FRAMEADDR: 1893e8d8bef9SDimitry Andric return lowerFRAMEADDR(Op, DAG, *this, Subtarget); 18945ffd83dbSDimitry Andric case ISD::GlobalAddress: 1895e8d8bef9SDimitry Andric return lowerGlobalAddress(Op, DAG); 18965ffd83dbSDimitry Andric case ISD::GlobalTLSAddress: 1897e8d8bef9SDimitry Andric return lowerGlobalTLSAddress(Op, DAG); 1898e8d8bef9SDimitry Andric case ISD::INTRINSIC_WO_CHAIN: 1899e8d8bef9SDimitry Andric return lowerINTRINSIC_WO_CHAIN(Op, DAG); 1900e8d8bef9SDimitry Andric case ISD::JumpTable: 1901e8d8bef9SDimitry Andric return lowerJumpTable(Op, DAG); 1902e8d8bef9SDimitry Andric case ISD::LOAD: 1903e8d8bef9SDimitry Andric return lowerLOAD(Op, DAG); 1904e8d8bef9SDimitry Andric case ISD::RETURNADDR: 1905e8d8bef9SDimitry Andric return lowerRETURNADDR(Op, DAG, *this, Subtarget); 1906e8d8bef9SDimitry Andric case ISD::BUILD_VECTOR: 1907e8d8bef9SDimitry Andric return lowerBUILD_VECTOR(Op, DAG); 1908e8d8bef9SDimitry Andric case ISD::STORE: 1909e8d8bef9SDimitry Andric return lowerSTORE(Op, DAG); 19105ffd83dbSDimitry Andric case ISD::VASTART: 1911e8d8bef9SDimitry Andric return lowerVASTART(Op, DAG); 19125ffd83dbSDimitry Andric case ISD::VAARG: 1913e8d8bef9SDimitry Andric return lowerVAARG(Op, DAG); 1914e8d8bef9SDimitry Andric 1915e8d8bef9SDimitry Andric case ISD::INSERT_VECTOR_ELT: 1916e8d8bef9SDimitry Andric return lowerINSERT_VECTOR_ELT(Op, DAG); 1917e8d8bef9SDimitry Andric case ISD::EXTRACT_VECTOR_ELT: 1918e8d8bef9SDimitry Andric return lowerEXTRACT_VECTOR_ELT(Op, DAG); 191981ad6265SDimitry Andric } 1920e8d8bef9SDimitry Andric 192181ad6265SDimitry Andric /// Vector isel. 192281ad6265SDimitry Andric if (ISD::isVPOpcode(Opcode)) 192381ad6265SDimitry Andric return lowerToVVP(Op, DAG); 192481ad6265SDimitry Andric 192581ad6265SDimitry Andric switch (Opcode) { 192681ad6265SDimitry Andric default: 192781ad6265SDimitry Andric llvm_unreachable("Should not custom lower this!"); 192881ad6265SDimitry Andric 192981ad6265SDimitry Andric // Legalize the AVL of this internal node. 193081ad6265SDimitry Andric case VEISD::VEC_BROADCAST: 193181ad6265SDimitry Andric #define ADD_VVP_OP(VVP_NAME, ...) case VEISD::VVP_NAME: 193281ad6265SDimitry Andric #include "VVPNodes.def" 193381ad6265SDimitry Andric // AVL already legalized. 193481ad6265SDimitry Andric if (getAnnotatedNodeAVL(Op).second) 193581ad6265SDimitry Andric return Op; 193681ad6265SDimitry Andric return legalizeInternalVectorOp(Op, DAG); 193781ad6265SDimitry Andric 193881ad6265SDimitry Andric // Translate into a VEC_*/VVP_* layer operation. 193981ad6265SDimitry Andric case ISD::MLOAD: 194081ad6265SDimitry Andric case ISD::MSTORE: 194104eeddc0SDimitry Andric #define ADD_VVP_OP(VVP_NAME, ISD_NAME) case ISD::ISD_NAME: 1942e8d8bef9SDimitry Andric #include "VVPNodes.def" 194381ad6265SDimitry Andric if (isMaskArithmetic(Op) && isPackedVectorType(Op.getValueType())) 194481ad6265SDimitry Andric return splitMaskArithmetic(Op, DAG); 1945e8d8bef9SDimitry Andric return lowerToVVP(Op, DAG); 19465ffd83dbSDimitry Andric } 19475ffd83dbSDimitry Andric } 19485ffd83dbSDimitry Andric /// } Custom Lower 1949e8d8bef9SDimitry Andric 1950e8d8bef9SDimitry Andric void VETargetLowering::ReplaceNodeResults(SDNode *N, 1951e8d8bef9SDimitry Andric SmallVectorImpl<SDValue> &Results, 1952e8d8bef9SDimitry Andric SelectionDAG &DAG) const { 1953e8d8bef9SDimitry Andric switch (N->getOpcode()) { 1954e8d8bef9SDimitry Andric case ISD::ATOMIC_SWAP: 1955e8d8bef9SDimitry Andric // Let LLVM expand atomic swap instruction through LowerOperation. 1956e8d8bef9SDimitry Andric return; 1957e8d8bef9SDimitry Andric default: 1958e8d8bef9SDimitry Andric LLVM_DEBUG(N->dumpr(&DAG)); 1959e8d8bef9SDimitry Andric llvm_unreachable("Do not know how to custom type legalize this operation!"); 1960e8d8bef9SDimitry Andric } 1961e8d8bef9SDimitry Andric } 1962e8d8bef9SDimitry Andric 1963e8d8bef9SDimitry Andric /// JumpTable for VE. 1964e8d8bef9SDimitry Andric /// 1965e8d8bef9SDimitry Andric /// VE cannot generate relocatable symbol in jump table. VE cannot 1966e8d8bef9SDimitry Andric /// generate expressions using symbols in both text segment and data 1967e8d8bef9SDimitry Andric /// segment like below. 1968e8d8bef9SDimitry Andric /// .4byte .LBB0_2-.LJTI0_0 1969e8d8bef9SDimitry Andric /// So, we generate offset from the top of function like below as 1970e8d8bef9SDimitry Andric /// a custom label. 1971e8d8bef9SDimitry Andric /// .4byte .LBB0_2-<function name> 1972e8d8bef9SDimitry Andric 1973e8d8bef9SDimitry Andric unsigned VETargetLowering::getJumpTableEncoding() const { 1974e8d8bef9SDimitry Andric // Use custom label for PIC. 1975e8d8bef9SDimitry Andric if (isPositionIndependent()) 1976e8d8bef9SDimitry Andric return MachineJumpTableInfo::EK_Custom32; 1977e8d8bef9SDimitry Andric 1978e8d8bef9SDimitry Andric // Otherwise, use the normal jump table encoding heuristics. 1979e8d8bef9SDimitry Andric return TargetLowering::getJumpTableEncoding(); 1980e8d8bef9SDimitry Andric } 1981e8d8bef9SDimitry Andric 1982e8d8bef9SDimitry Andric const MCExpr *VETargetLowering::LowerCustomJumpTableEntry( 1983e8d8bef9SDimitry Andric const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, 1984e8d8bef9SDimitry Andric unsigned Uid, MCContext &Ctx) const { 1985e8d8bef9SDimitry Andric assert(isPositionIndependent()); 1986e8d8bef9SDimitry Andric 1987e8d8bef9SDimitry Andric // Generate custom label for PIC like below. 1988e8d8bef9SDimitry Andric // .4bytes .LBB0_2-<function name> 1989e8d8bef9SDimitry Andric const auto *Value = MCSymbolRefExpr::create(MBB->getSymbol(), Ctx); 1990e8d8bef9SDimitry Andric MCSymbol *Sym = Ctx.getOrCreateSymbol(MBB->getParent()->getName().data()); 1991e8d8bef9SDimitry Andric const auto *Base = MCSymbolRefExpr::create(Sym, Ctx); 1992e8d8bef9SDimitry Andric return MCBinaryExpr::createSub(Value, Base, Ctx); 1993e8d8bef9SDimitry Andric } 1994e8d8bef9SDimitry Andric 1995e8d8bef9SDimitry Andric SDValue VETargetLowering::getPICJumpTableRelocBase(SDValue Table, 1996e8d8bef9SDimitry Andric SelectionDAG &DAG) const { 1997e8d8bef9SDimitry Andric assert(isPositionIndependent()); 1998e8d8bef9SDimitry Andric SDLoc DL(Table); 1999e8d8bef9SDimitry Andric Function *Function = &DAG.getMachineFunction().getFunction(); 2000e8d8bef9SDimitry Andric assert(Function != nullptr); 2001e8d8bef9SDimitry Andric auto PtrTy = getPointerTy(DAG.getDataLayout(), Function->getAddressSpace()); 2002e8d8bef9SDimitry Andric 2003e8d8bef9SDimitry Andric // In the jump table, we have following values in PIC mode. 2004e8d8bef9SDimitry Andric // .4bytes .LBB0_2-<function name> 2005e8d8bef9SDimitry Andric // We need to add this value and the address of this function to generate 2006e8d8bef9SDimitry Andric // .LBB0_2 label correctly under PIC mode. So, we want to generate following 2007e8d8bef9SDimitry Andric // instructions: 2008e8d8bef9SDimitry Andric // lea %reg, fun@gotoff_lo 2009e8d8bef9SDimitry Andric // and %reg, %reg, (32)0 2010e8d8bef9SDimitry Andric // lea.sl %reg, fun@gotoff_hi(%reg, %got) 2011e8d8bef9SDimitry Andric // In order to do so, we need to genarate correctly marked DAG node using 2012e8d8bef9SDimitry Andric // makeHiLoPair. 2013e8d8bef9SDimitry Andric SDValue Op = DAG.getGlobalAddress(Function, DL, PtrTy); 2014e8d8bef9SDimitry Andric SDValue HiLo = makeHiLoPair(Op, VEMCExpr::VK_VE_GOTOFF_HI32, 2015e8d8bef9SDimitry Andric VEMCExpr::VK_VE_GOTOFF_LO32, DAG); 2016e8d8bef9SDimitry Andric SDValue GlobalBase = DAG.getNode(VEISD::GLOBAL_BASE_REG, DL, PtrTy); 2017e8d8bef9SDimitry Andric return DAG.getNode(ISD::ADD, DL, PtrTy, GlobalBase, HiLo); 2018e8d8bef9SDimitry Andric } 2019e8d8bef9SDimitry Andric 2020e8d8bef9SDimitry Andric Register VETargetLowering::prepareMBB(MachineBasicBlock &MBB, 2021e8d8bef9SDimitry Andric MachineBasicBlock::iterator I, 2022e8d8bef9SDimitry Andric MachineBasicBlock *TargetBB, 2023e8d8bef9SDimitry Andric const DebugLoc &DL) const { 2024e8d8bef9SDimitry Andric MachineFunction *MF = MBB.getParent(); 2025e8d8bef9SDimitry Andric MachineRegisterInfo &MRI = MF->getRegInfo(); 2026e8d8bef9SDimitry Andric const VEInstrInfo *TII = Subtarget->getInstrInfo(); 2027e8d8bef9SDimitry Andric 2028e8d8bef9SDimitry Andric const TargetRegisterClass *RC = &VE::I64RegClass; 2029e8d8bef9SDimitry Andric Register Tmp1 = MRI.createVirtualRegister(RC); 2030e8d8bef9SDimitry Andric Register Tmp2 = MRI.createVirtualRegister(RC); 2031e8d8bef9SDimitry Andric Register Result = MRI.createVirtualRegister(RC); 2032e8d8bef9SDimitry Andric 2033e8d8bef9SDimitry Andric if (isPositionIndependent()) { 2034e8d8bef9SDimitry Andric // Create following instructions for local linkage PIC code. 2035e8d8bef9SDimitry Andric // lea %Tmp1, TargetBB@gotoff_lo 2036e8d8bef9SDimitry Andric // and %Tmp2, %Tmp1, (32)0 2037e8d8bef9SDimitry Andric // lea.sl %Result, TargetBB@gotoff_hi(%Tmp2, %s15) ; %s15 is GOT 2038e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1) 2039e8d8bef9SDimitry Andric .addImm(0) 2040e8d8bef9SDimitry Andric .addImm(0) 2041e8d8bef9SDimitry Andric .addMBB(TargetBB, VEMCExpr::VK_VE_GOTOFF_LO32); 2042e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2) 2043e8d8bef9SDimitry Andric .addReg(Tmp1, getKillRegState(true)) 2044e8d8bef9SDimitry Andric .addImm(M0(32)); 2045e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, TII->get(VE::LEASLrri), Result) 2046e8d8bef9SDimitry Andric .addReg(VE::SX15) 2047e8d8bef9SDimitry Andric .addReg(Tmp2, getKillRegState(true)) 2048e8d8bef9SDimitry Andric .addMBB(TargetBB, VEMCExpr::VK_VE_GOTOFF_HI32); 2049e8d8bef9SDimitry Andric } else { 2050e8d8bef9SDimitry Andric // Create following instructions for non-PIC code. 2051e8d8bef9SDimitry Andric // lea %Tmp1, TargetBB@lo 2052e8d8bef9SDimitry Andric // and %Tmp2, %Tmp1, (32)0 2053e8d8bef9SDimitry Andric // lea.sl %Result, TargetBB@hi(%Tmp2) 2054e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1) 2055e8d8bef9SDimitry Andric .addImm(0) 2056e8d8bef9SDimitry Andric .addImm(0) 2057e8d8bef9SDimitry Andric .addMBB(TargetBB, VEMCExpr::VK_VE_LO32); 2058e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2) 2059e8d8bef9SDimitry Andric .addReg(Tmp1, getKillRegState(true)) 2060e8d8bef9SDimitry Andric .addImm(M0(32)); 2061e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, TII->get(VE::LEASLrii), Result) 2062e8d8bef9SDimitry Andric .addReg(Tmp2, getKillRegState(true)) 2063e8d8bef9SDimitry Andric .addImm(0) 2064e8d8bef9SDimitry Andric .addMBB(TargetBB, VEMCExpr::VK_VE_HI32); 2065e8d8bef9SDimitry Andric } 2066e8d8bef9SDimitry Andric return Result; 2067e8d8bef9SDimitry Andric } 2068e8d8bef9SDimitry Andric 2069e8d8bef9SDimitry Andric Register VETargetLowering::prepareSymbol(MachineBasicBlock &MBB, 2070e8d8bef9SDimitry Andric MachineBasicBlock::iterator I, 2071e8d8bef9SDimitry Andric StringRef Symbol, const DebugLoc &DL, 2072e8d8bef9SDimitry Andric bool IsLocal = false, 2073e8d8bef9SDimitry Andric bool IsCall = false) const { 2074e8d8bef9SDimitry Andric MachineFunction *MF = MBB.getParent(); 2075e8d8bef9SDimitry Andric MachineRegisterInfo &MRI = MF->getRegInfo(); 2076e8d8bef9SDimitry Andric const VEInstrInfo *TII = Subtarget->getInstrInfo(); 2077e8d8bef9SDimitry Andric 2078e8d8bef9SDimitry Andric const TargetRegisterClass *RC = &VE::I64RegClass; 2079e8d8bef9SDimitry Andric Register Result = MRI.createVirtualRegister(RC); 2080e8d8bef9SDimitry Andric 2081e8d8bef9SDimitry Andric if (isPositionIndependent()) { 2082e8d8bef9SDimitry Andric if (IsCall && !IsLocal) { 2083e8d8bef9SDimitry Andric // Create following instructions for non-local linkage PIC code function 2084e8d8bef9SDimitry Andric // calls. These instructions uses IC and magic number -24, so we expand 2085e8d8bef9SDimitry Andric // them in VEAsmPrinter.cpp from GETFUNPLT pseudo instruction. 2086e8d8bef9SDimitry Andric // lea %Reg, Symbol@plt_lo(-24) 2087e8d8bef9SDimitry Andric // and %Reg, %Reg, (32)0 2088e8d8bef9SDimitry Andric // sic %s16 2089e8d8bef9SDimitry Andric // lea.sl %Result, Symbol@plt_hi(%Reg, %s16) ; %s16 is PLT 2090e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, TII->get(VE::GETFUNPLT), Result) 2091e8d8bef9SDimitry Andric .addExternalSymbol("abort"); 2092e8d8bef9SDimitry Andric } else if (IsLocal) { 2093e8d8bef9SDimitry Andric Register Tmp1 = MRI.createVirtualRegister(RC); 2094e8d8bef9SDimitry Andric Register Tmp2 = MRI.createVirtualRegister(RC); 2095e8d8bef9SDimitry Andric // Create following instructions for local linkage PIC code. 2096e8d8bef9SDimitry Andric // lea %Tmp1, Symbol@gotoff_lo 2097e8d8bef9SDimitry Andric // and %Tmp2, %Tmp1, (32)0 2098e8d8bef9SDimitry Andric // lea.sl %Result, Symbol@gotoff_hi(%Tmp2, %s15) ; %s15 is GOT 2099e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1) 2100e8d8bef9SDimitry Andric .addImm(0) 2101e8d8bef9SDimitry Andric .addImm(0) 2102e8d8bef9SDimitry Andric .addExternalSymbol(Symbol.data(), VEMCExpr::VK_VE_GOTOFF_LO32); 2103e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2) 2104e8d8bef9SDimitry Andric .addReg(Tmp1, getKillRegState(true)) 2105e8d8bef9SDimitry Andric .addImm(M0(32)); 2106e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, TII->get(VE::LEASLrri), Result) 2107e8d8bef9SDimitry Andric .addReg(VE::SX15) 2108e8d8bef9SDimitry Andric .addReg(Tmp2, getKillRegState(true)) 2109e8d8bef9SDimitry Andric .addExternalSymbol(Symbol.data(), VEMCExpr::VK_VE_GOTOFF_HI32); 2110e8d8bef9SDimitry Andric } else { 2111e8d8bef9SDimitry Andric Register Tmp1 = MRI.createVirtualRegister(RC); 2112e8d8bef9SDimitry Andric Register Tmp2 = MRI.createVirtualRegister(RC); 2113e8d8bef9SDimitry Andric // Create following instructions for not local linkage PIC code. 2114e8d8bef9SDimitry Andric // lea %Tmp1, Symbol@got_lo 2115e8d8bef9SDimitry Andric // and %Tmp2, %Tmp1, (32)0 2116e8d8bef9SDimitry Andric // lea.sl %Tmp3, Symbol@gotoff_hi(%Tmp2, %s15) ; %s15 is GOT 2117e8d8bef9SDimitry Andric // ld %Result, 0(%Tmp3) 2118e8d8bef9SDimitry Andric Register Tmp3 = MRI.createVirtualRegister(RC); 2119e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1) 2120e8d8bef9SDimitry Andric .addImm(0) 2121e8d8bef9SDimitry Andric .addImm(0) 2122e8d8bef9SDimitry Andric .addExternalSymbol(Symbol.data(), VEMCExpr::VK_VE_GOT_LO32); 2123e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2) 2124e8d8bef9SDimitry Andric .addReg(Tmp1, getKillRegState(true)) 2125e8d8bef9SDimitry Andric .addImm(M0(32)); 2126e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, TII->get(VE::LEASLrri), Tmp3) 2127e8d8bef9SDimitry Andric .addReg(VE::SX15) 2128e8d8bef9SDimitry Andric .addReg(Tmp2, getKillRegState(true)) 2129e8d8bef9SDimitry Andric .addExternalSymbol(Symbol.data(), VEMCExpr::VK_VE_GOT_HI32); 2130e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, TII->get(VE::LDrii), Result) 2131e8d8bef9SDimitry Andric .addReg(Tmp3, getKillRegState(true)) 2132e8d8bef9SDimitry Andric .addImm(0) 2133e8d8bef9SDimitry Andric .addImm(0); 2134e8d8bef9SDimitry Andric } 2135e8d8bef9SDimitry Andric } else { 2136e8d8bef9SDimitry Andric Register Tmp1 = MRI.createVirtualRegister(RC); 2137e8d8bef9SDimitry Andric Register Tmp2 = MRI.createVirtualRegister(RC); 2138e8d8bef9SDimitry Andric // Create following instructions for non-PIC code. 2139e8d8bef9SDimitry Andric // lea %Tmp1, Symbol@lo 2140e8d8bef9SDimitry Andric // and %Tmp2, %Tmp1, (32)0 2141e8d8bef9SDimitry Andric // lea.sl %Result, Symbol@hi(%Tmp2) 2142e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1) 2143e8d8bef9SDimitry Andric .addImm(0) 2144e8d8bef9SDimitry Andric .addImm(0) 2145e8d8bef9SDimitry Andric .addExternalSymbol(Symbol.data(), VEMCExpr::VK_VE_LO32); 2146e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2) 2147e8d8bef9SDimitry Andric .addReg(Tmp1, getKillRegState(true)) 2148e8d8bef9SDimitry Andric .addImm(M0(32)); 2149e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, TII->get(VE::LEASLrii), Result) 2150e8d8bef9SDimitry Andric .addReg(Tmp2, getKillRegState(true)) 2151e8d8bef9SDimitry Andric .addImm(0) 2152e8d8bef9SDimitry Andric .addExternalSymbol(Symbol.data(), VEMCExpr::VK_VE_HI32); 2153e8d8bef9SDimitry Andric } 2154e8d8bef9SDimitry Andric return Result; 2155e8d8bef9SDimitry Andric } 2156e8d8bef9SDimitry Andric 2157e8d8bef9SDimitry Andric void VETargetLowering::setupEntryBlockForSjLj(MachineInstr &MI, 2158e8d8bef9SDimitry Andric MachineBasicBlock *MBB, 2159e8d8bef9SDimitry Andric MachineBasicBlock *DispatchBB, 2160e8d8bef9SDimitry Andric int FI, int Offset) const { 2161e8d8bef9SDimitry Andric DebugLoc DL = MI.getDebugLoc(); 2162e8d8bef9SDimitry Andric const VEInstrInfo *TII = Subtarget->getInstrInfo(); 2163e8d8bef9SDimitry Andric 2164e8d8bef9SDimitry Andric Register LabelReg = 2165e8d8bef9SDimitry Andric prepareMBB(*MBB, MachineBasicBlock::iterator(MI), DispatchBB, DL); 2166e8d8bef9SDimitry Andric 2167e8d8bef9SDimitry Andric // Store an address of DispatchBB to a given jmpbuf[1] where has next IC 2168e8d8bef9SDimitry Andric // referenced by longjmp (throw) later. 2169e8d8bef9SDimitry Andric MachineInstrBuilder MIB = BuildMI(*MBB, MI, DL, TII->get(VE::STrii)); 2170e8d8bef9SDimitry Andric addFrameReference(MIB, FI, Offset); // jmpbuf[1] 2171e8d8bef9SDimitry Andric MIB.addReg(LabelReg, getKillRegState(true)); 2172e8d8bef9SDimitry Andric } 2173e8d8bef9SDimitry Andric 2174e8d8bef9SDimitry Andric MachineBasicBlock * 2175e8d8bef9SDimitry Andric VETargetLowering::emitEHSjLjSetJmp(MachineInstr &MI, 2176e8d8bef9SDimitry Andric MachineBasicBlock *MBB) const { 2177e8d8bef9SDimitry Andric DebugLoc DL = MI.getDebugLoc(); 2178e8d8bef9SDimitry Andric MachineFunction *MF = MBB->getParent(); 2179e8d8bef9SDimitry Andric const TargetInstrInfo *TII = Subtarget->getInstrInfo(); 2180e8d8bef9SDimitry Andric const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo(); 2181e8d8bef9SDimitry Andric MachineRegisterInfo &MRI = MF->getRegInfo(); 2182e8d8bef9SDimitry Andric 2183e8d8bef9SDimitry Andric const BasicBlock *BB = MBB->getBasicBlock(); 2184e8d8bef9SDimitry Andric MachineFunction::iterator I = ++MBB->getIterator(); 2185e8d8bef9SDimitry Andric 2186e8d8bef9SDimitry Andric // Memory Reference. 2187e8d8bef9SDimitry Andric SmallVector<MachineMemOperand *, 2> MMOs(MI.memoperands_begin(), 2188e8d8bef9SDimitry Andric MI.memoperands_end()); 2189e8d8bef9SDimitry Andric Register BufReg = MI.getOperand(1).getReg(); 2190e8d8bef9SDimitry Andric 2191e8d8bef9SDimitry Andric Register DstReg; 2192e8d8bef9SDimitry Andric 2193e8d8bef9SDimitry Andric DstReg = MI.getOperand(0).getReg(); 2194e8d8bef9SDimitry Andric const TargetRegisterClass *RC = MRI.getRegClass(DstReg); 2195e8d8bef9SDimitry Andric assert(TRI->isTypeLegalForClass(*RC, MVT::i32) && "Invalid destination!"); 2196e8d8bef9SDimitry Andric (void)TRI; 2197e8d8bef9SDimitry Andric Register MainDestReg = MRI.createVirtualRegister(RC); 2198e8d8bef9SDimitry Andric Register RestoreDestReg = MRI.createVirtualRegister(RC); 2199e8d8bef9SDimitry Andric 2200e8d8bef9SDimitry Andric // For `v = call @llvm.eh.sjlj.setjmp(buf)`, we generate following 2201e8d8bef9SDimitry Andric // instructions. SP/FP must be saved in jmpbuf before `llvm.eh.sjlj.setjmp`. 2202e8d8bef9SDimitry Andric // 2203e8d8bef9SDimitry Andric // ThisMBB: 2204e8d8bef9SDimitry Andric // buf[3] = %s17 iff %s17 is used as BP 2205e8d8bef9SDimitry Andric // buf[1] = RestoreMBB as IC after longjmp 2206e8d8bef9SDimitry Andric // # SjLjSetup RestoreMBB 2207e8d8bef9SDimitry Andric // 2208e8d8bef9SDimitry Andric // MainMBB: 2209e8d8bef9SDimitry Andric // v_main = 0 2210e8d8bef9SDimitry Andric // 2211e8d8bef9SDimitry Andric // SinkMBB: 2212e8d8bef9SDimitry Andric // v = phi(v_main, MainMBB, v_restore, RestoreMBB) 2213e8d8bef9SDimitry Andric // ... 2214e8d8bef9SDimitry Andric // 2215e8d8bef9SDimitry Andric // RestoreMBB: 2216e8d8bef9SDimitry Andric // %s17 = buf[3] = iff %s17 is used as BP 2217e8d8bef9SDimitry Andric // v_restore = 1 2218e8d8bef9SDimitry Andric // goto SinkMBB 2219e8d8bef9SDimitry Andric 2220e8d8bef9SDimitry Andric MachineBasicBlock *ThisMBB = MBB; 2221e8d8bef9SDimitry Andric MachineBasicBlock *MainMBB = MF->CreateMachineBasicBlock(BB); 2222e8d8bef9SDimitry Andric MachineBasicBlock *SinkMBB = MF->CreateMachineBasicBlock(BB); 2223e8d8bef9SDimitry Andric MachineBasicBlock *RestoreMBB = MF->CreateMachineBasicBlock(BB); 2224e8d8bef9SDimitry Andric MF->insert(I, MainMBB); 2225e8d8bef9SDimitry Andric MF->insert(I, SinkMBB); 2226e8d8bef9SDimitry Andric MF->push_back(RestoreMBB); 2227bdd1243dSDimitry Andric RestoreMBB->setMachineBlockAddressTaken(); 2228e8d8bef9SDimitry Andric 2229e8d8bef9SDimitry Andric // Transfer the remainder of BB and its successor edges to SinkMBB. 2230e8d8bef9SDimitry Andric SinkMBB->splice(SinkMBB->begin(), MBB, 2231e8d8bef9SDimitry Andric std::next(MachineBasicBlock::iterator(MI)), MBB->end()); 2232e8d8bef9SDimitry Andric SinkMBB->transferSuccessorsAndUpdatePHIs(MBB); 2233e8d8bef9SDimitry Andric 2234e8d8bef9SDimitry Andric // ThisMBB: 2235e8d8bef9SDimitry Andric Register LabelReg = 2236e8d8bef9SDimitry Andric prepareMBB(*MBB, MachineBasicBlock::iterator(MI), RestoreMBB, DL); 2237e8d8bef9SDimitry Andric 2238e8d8bef9SDimitry Andric // Store BP in buf[3] iff this function is using BP. 2239e8d8bef9SDimitry Andric const VEFrameLowering *TFI = Subtarget->getFrameLowering(); 2240e8d8bef9SDimitry Andric if (TFI->hasBP(*MF)) { 2241e8d8bef9SDimitry Andric MachineInstrBuilder MIB = BuildMI(*MBB, MI, DL, TII->get(VE::STrii)); 2242e8d8bef9SDimitry Andric MIB.addReg(BufReg); 2243e8d8bef9SDimitry Andric MIB.addImm(0); 2244e8d8bef9SDimitry Andric MIB.addImm(24); 2245e8d8bef9SDimitry Andric MIB.addReg(VE::SX17); 2246e8d8bef9SDimitry Andric MIB.setMemRefs(MMOs); 2247e8d8bef9SDimitry Andric } 2248e8d8bef9SDimitry Andric 2249e8d8bef9SDimitry Andric // Store IP in buf[1]. 2250e8d8bef9SDimitry Andric MachineInstrBuilder MIB = BuildMI(*MBB, MI, DL, TII->get(VE::STrii)); 2251e8d8bef9SDimitry Andric MIB.add(MI.getOperand(1)); // we can preserve the kill flags here. 2252e8d8bef9SDimitry Andric MIB.addImm(0); 2253e8d8bef9SDimitry Andric MIB.addImm(8); 2254e8d8bef9SDimitry Andric MIB.addReg(LabelReg, getKillRegState(true)); 2255e8d8bef9SDimitry Andric MIB.setMemRefs(MMOs); 2256e8d8bef9SDimitry Andric 2257e8d8bef9SDimitry Andric // SP/FP are already stored in jmpbuf before `llvm.eh.sjlj.setjmp`. 2258e8d8bef9SDimitry Andric 2259e8d8bef9SDimitry Andric // Insert setup. 2260e8d8bef9SDimitry Andric MIB = 2261e8d8bef9SDimitry Andric BuildMI(*ThisMBB, MI, DL, TII->get(VE::EH_SjLj_Setup)).addMBB(RestoreMBB); 2262e8d8bef9SDimitry Andric 2263e8d8bef9SDimitry Andric const VERegisterInfo *RegInfo = Subtarget->getRegisterInfo(); 2264e8d8bef9SDimitry Andric MIB.addRegMask(RegInfo->getNoPreservedMask()); 2265e8d8bef9SDimitry Andric ThisMBB->addSuccessor(MainMBB); 2266e8d8bef9SDimitry Andric ThisMBB->addSuccessor(RestoreMBB); 2267e8d8bef9SDimitry Andric 2268e8d8bef9SDimitry Andric // MainMBB: 2269e8d8bef9SDimitry Andric BuildMI(MainMBB, DL, TII->get(VE::LEAzii), MainDestReg) 2270e8d8bef9SDimitry Andric .addImm(0) 2271e8d8bef9SDimitry Andric .addImm(0) 2272e8d8bef9SDimitry Andric .addImm(0); 2273e8d8bef9SDimitry Andric MainMBB->addSuccessor(SinkMBB); 2274e8d8bef9SDimitry Andric 2275e8d8bef9SDimitry Andric // SinkMBB: 2276e8d8bef9SDimitry Andric BuildMI(*SinkMBB, SinkMBB->begin(), DL, TII->get(VE::PHI), DstReg) 2277e8d8bef9SDimitry Andric .addReg(MainDestReg) 2278e8d8bef9SDimitry Andric .addMBB(MainMBB) 2279e8d8bef9SDimitry Andric .addReg(RestoreDestReg) 2280e8d8bef9SDimitry Andric .addMBB(RestoreMBB); 2281e8d8bef9SDimitry Andric 2282e8d8bef9SDimitry Andric // RestoreMBB: 2283e8d8bef9SDimitry Andric // Restore BP from buf[3] iff this function is using BP. The address of 2284e8d8bef9SDimitry Andric // buf is in SX10. 2285e8d8bef9SDimitry Andric // FIXME: Better to not use SX10 here 2286e8d8bef9SDimitry Andric if (TFI->hasBP(*MF)) { 2287e8d8bef9SDimitry Andric MachineInstrBuilder MIB = 2288e8d8bef9SDimitry Andric BuildMI(RestoreMBB, DL, TII->get(VE::LDrii), VE::SX17); 2289e8d8bef9SDimitry Andric MIB.addReg(VE::SX10); 2290e8d8bef9SDimitry Andric MIB.addImm(0); 2291e8d8bef9SDimitry Andric MIB.addImm(24); 2292e8d8bef9SDimitry Andric MIB.setMemRefs(MMOs); 2293e8d8bef9SDimitry Andric } 2294e8d8bef9SDimitry Andric BuildMI(RestoreMBB, DL, TII->get(VE::LEAzii), RestoreDestReg) 2295e8d8bef9SDimitry Andric .addImm(0) 2296e8d8bef9SDimitry Andric .addImm(0) 2297e8d8bef9SDimitry Andric .addImm(1); 2298e8d8bef9SDimitry Andric BuildMI(RestoreMBB, DL, TII->get(VE::BRCFLa_t)).addMBB(SinkMBB); 2299e8d8bef9SDimitry Andric RestoreMBB->addSuccessor(SinkMBB); 2300e8d8bef9SDimitry Andric 2301e8d8bef9SDimitry Andric MI.eraseFromParent(); 2302e8d8bef9SDimitry Andric return SinkMBB; 2303e8d8bef9SDimitry Andric } 2304e8d8bef9SDimitry Andric 2305e8d8bef9SDimitry Andric MachineBasicBlock * 2306e8d8bef9SDimitry Andric VETargetLowering::emitEHSjLjLongJmp(MachineInstr &MI, 2307e8d8bef9SDimitry Andric MachineBasicBlock *MBB) const { 2308e8d8bef9SDimitry Andric DebugLoc DL = MI.getDebugLoc(); 2309e8d8bef9SDimitry Andric MachineFunction *MF = MBB->getParent(); 2310e8d8bef9SDimitry Andric const TargetInstrInfo *TII = Subtarget->getInstrInfo(); 2311e8d8bef9SDimitry Andric MachineRegisterInfo &MRI = MF->getRegInfo(); 2312e8d8bef9SDimitry Andric 2313e8d8bef9SDimitry Andric // Memory Reference. 2314e8d8bef9SDimitry Andric SmallVector<MachineMemOperand *, 2> MMOs(MI.memoperands_begin(), 2315e8d8bef9SDimitry Andric MI.memoperands_end()); 2316e8d8bef9SDimitry Andric Register BufReg = MI.getOperand(0).getReg(); 2317e8d8bef9SDimitry Andric 2318e8d8bef9SDimitry Andric Register Tmp = MRI.createVirtualRegister(&VE::I64RegClass); 2319e8d8bef9SDimitry Andric // Since FP is only updated here but NOT referenced, it's treated as GPR. 2320e8d8bef9SDimitry Andric Register FP = VE::SX9; 2321e8d8bef9SDimitry Andric Register SP = VE::SX11; 2322e8d8bef9SDimitry Andric 2323e8d8bef9SDimitry Andric MachineInstrBuilder MIB; 2324e8d8bef9SDimitry Andric 2325e8d8bef9SDimitry Andric MachineBasicBlock *ThisMBB = MBB; 2326e8d8bef9SDimitry Andric 2327e8d8bef9SDimitry Andric // For `call @llvm.eh.sjlj.longjmp(buf)`, we generate following instructions. 2328e8d8bef9SDimitry Andric // 2329e8d8bef9SDimitry Andric // ThisMBB: 2330e8d8bef9SDimitry Andric // %fp = load buf[0] 2331e8d8bef9SDimitry Andric // %jmp = load buf[1] 2332e8d8bef9SDimitry Andric // %s10 = buf ; Store an address of buf to SX10 for RestoreMBB 2333e8d8bef9SDimitry Andric // %sp = load buf[2] ; generated by llvm.eh.sjlj.setjmp. 2334e8d8bef9SDimitry Andric // jmp %jmp 2335e8d8bef9SDimitry Andric 2336e8d8bef9SDimitry Andric // Reload FP. 2337e8d8bef9SDimitry Andric MIB = BuildMI(*ThisMBB, MI, DL, TII->get(VE::LDrii), FP); 2338e8d8bef9SDimitry Andric MIB.addReg(BufReg); 2339e8d8bef9SDimitry Andric MIB.addImm(0); 2340e8d8bef9SDimitry Andric MIB.addImm(0); 2341e8d8bef9SDimitry Andric MIB.setMemRefs(MMOs); 2342e8d8bef9SDimitry Andric 2343e8d8bef9SDimitry Andric // Reload IP. 2344e8d8bef9SDimitry Andric MIB = BuildMI(*ThisMBB, MI, DL, TII->get(VE::LDrii), Tmp); 2345e8d8bef9SDimitry Andric MIB.addReg(BufReg); 2346e8d8bef9SDimitry Andric MIB.addImm(0); 2347e8d8bef9SDimitry Andric MIB.addImm(8); 2348e8d8bef9SDimitry Andric MIB.setMemRefs(MMOs); 2349e8d8bef9SDimitry Andric 2350e8d8bef9SDimitry Andric // Copy BufReg to SX10 for later use in setjmp. 2351e8d8bef9SDimitry Andric // FIXME: Better to not use SX10 here 2352e8d8bef9SDimitry Andric BuildMI(*ThisMBB, MI, DL, TII->get(VE::ORri), VE::SX10) 2353e8d8bef9SDimitry Andric .addReg(BufReg) 2354e8d8bef9SDimitry Andric .addImm(0); 2355e8d8bef9SDimitry Andric 2356e8d8bef9SDimitry Andric // Reload SP. 2357e8d8bef9SDimitry Andric MIB = BuildMI(*ThisMBB, MI, DL, TII->get(VE::LDrii), SP); 2358e8d8bef9SDimitry Andric MIB.add(MI.getOperand(0)); // we can preserve the kill flags here. 2359e8d8bef9SDimitry Andric MIB.addImm(0); 2360e8d8bef9SDimitry Andric MIB.addImm(16); 2361e8d8bef9SDimitry Andric MIB.setMemRefs(MMOs); 2362e8d8bef9SDimitry Andric 2363e8d8bef9SDimitry Andric // Jump. 2364e8d8bef9SDimitry Andric BuildMI(*ThisMBB, MI, DL, TII->get(VE::BCFLari_t)) 2365e8d8bef9SDimitry Andric .addReg(Tmp, getKillRegState(true)) 2366e8d8bef9SDimitry Andric .addImm(0); 2367e8d8bef9SDimitry Andric 2368e8d8bef9SDimitry Andric MI.eraseFromParent(); 2369e8d8bef9SDimitry Andric return ThisMBB; 2370e8d8bef9SDimitry Andric } 2371e8d8bef9SDimitry Andric 2372e8d8bef9SDimitry Andric MachineBasicBlock * 2373e8d8bef9SDimitry Andric VETargetLowering::emitSjLjDispatchBlock(MachineInstr &MI, 2374e8d8bef9SDimitry Andric MachineBasicBlock *BB) const { 2375e8d8bef9SDimitry Andric DebugLoc DL = MI.getDebugLoc(); 2376e8d8bef9SDimitry Andric MachineFunction *MF = BB->getParent(); 2377e8d8bef9SDimitry Andric MachineFrameInfo &MFI = MF->getFrameInfo(); 2378e8d8bef9SDimitry Andric MachineRegisterInfo &MRI = MF->getRegInfo(); 2379e8d8bef9SDimitry Andric const VEInstrInfo *TII = Subtarget->getInstrInfo(); 2380e8d8bef9SDimitry Andric int FI = MFI.getFunctionContextIndex(); 2381e8d8bef9SDimitry Andric 2382e8d8bef9SDimitry Andric // Get a mapping of the call site numbers to all of the landing pads they're 2383e8d8bef9SDimitry Andric // associated with. 2384e8d8bef9SDimitry Andric DenseMap<unsigned, SmallVector<MachineBasicBlock *, 2>> CallSiteNumToLPad; 2385e8d8bef9SDimitry Andric unsigned MaxCSNum = 0; 2386e8d8bef9SDimitry Andric for (auto &MBB : *MF) { 2387e8d8bef9SDimitry Andric if (!MBB.isEHPad()) 2388e8d8bef9SDimitry Andric continue; 2389e8d8bef9SDimitry Andric 2390e8d8bef9SDimitry Andric MCSymbol *Sym = nullptr; 2391e8d8bef9SDimitry Andric for (const auto &MI : MBB) { 2392e8d8bef9SDimitry Andric if (MI.isDebugInstr()) 2393e8d8bef9SDimitry Andric continue; 2394e8d8bef9SDimitry Andric 2395e8d8bef9SDimitry Andric assert(MI.isEHLabel() && "expected EH_LABEL"); 2396e8d8bef9SDimitry Andric Sym = MI.getOperand(0).getMCSymbol(); 2397e8d8bef9SDimitry Andric break; 2398e8d8bef9SDimitry Andric } 2399e8d8bef9SDimitry Andric 2400e8d8bef9SDimitry Andric if (!MF->hasCallSiteLandingPad(Sym)) 2401e8d8bef9SDimitry Andric continue; 2402e8d8bef9SDimitry Andric 2403e8d8bef9SDimitry Andric for (unsigned CSI : MF->getCallSiteLandingPad(Sym)) { 2404e8d8bef9SDimitry Andric CallSiteNumToLPad[CSI].push_back(&MBB); 2405e8d8bef9SDimitry Andric MaxCSNum = std::max(MaxCSNum, CSI); 2406e8d8bef9SDimitry Andric } 2407e8d8bef9SDimitry Andric } 2408e8d8bef9SDimitry Andric 2409e8d8bef9SDimitry Andric // Get an ordered list of the machine basic blocks for the jump table. 2410e8d8bef9SDimitry Andric std::vector<MachineBasicBlock *> LPadList; 2411e8d8bef9SDimitry Andric SmallPtrSet<MachineBasicBlock *, 32> InvokeBBs; 2412e8d8bef9SDimitry Andric LPadList.reserve(CallSiteNumToLPad.size()); 2413e8d8bef9SDimitry Andric 2414e8d8bef9SDimitry Andric for (unsigned CSI = 1; CSI <= MaxCSNum; ++CSI) { 2415e8d8bef9SDimitry Andric for (auto &LP : CallSiteNumToLPad[CSI]) { 2416e8d8bef9SDimitry Andric LPadList.push_back(LP); 2417e8d8bef9SDimitry Andric InvokeBBs.insert(LP->pred_begin(), LP->pred_end()); 2418e8d8bef9SDimitry Andric } 2419e8d8bef9SDimitry Andric } 2420e8d8bef9SDimitry Andric 2421e8d8bef9SDimitry Andric assert(!LPadList.empty() && 2422e8d8bef9SDimitry Andric "No landing pad destinations for the dispatch jump table!"); 2423e8d8bef9SDimitry Andric 2424e8d8bef9SDimitry Andric // The %fn_context is allocated like below (from --print-after=sjljehprepare): 2425e8d8bef9SDimitry Andric // %fn_context = alloca { i8*, i64, [4 x i64], i8*, i8*, [5 x i8*] } 2426e8d8bef9SDimitry Andric // 2427e8d8bef9SDimitry Andric // This `[5 x i8*]` is jmpbuf, so jmpbuf[1] is FI+72. 2428e8d8bef9SDimitry Andric // First `i64` is callsite, so callsite is FI+8. 2429e8d8bef9SDimitry Andric static const int OffsetIC = 72; 2430e8d8bef9SDimitry Andric static const int OffsetCS = 8; 2431e8d8bef9SDimitry Andric 2432e8d8bef9SDimitry Andric // Create the MBBs for the dispatch code like following: 2433e8d8bef9SDimitry Andric // 2434e8d8bef9SDimitry Andric // ThisMBB: 2435e8d8bef9SDimitry Andric // Prepare DispatchBB address and store it to buf[1]. 2436e8d8bef9SDimitry Andric // ... 2437e8d8bef9SDimitry Andric // 2438e8d8bef9SDimitry Andric // DispatchBB: 2439e8d8bef9SDimitry Andric // %s15 = GETGOT iff isPositionIndependent 2440e8d8bef9SDimitry Andric // %callsite = load callsite 2441e8d8bef9SDimitry Andric // brgt.l.t #size of callsites, %callsite, DispContBB 2442e8d8bef9SDimitry Andric // 2443e8d8bef9SDimitry Andric // TrapBB: 2444e8d8bef9SDimitry Andric // Call abort. 2445e8d8bef9SDimitry Andric // 2446e8d8bef9SDimitry Andric // DispContBB: 2447e8d8bef9SDimitry Andric // %breg = address of jump table 2448e8d8bef9SDimitry Andric // %pc = load and calculate next pc from %breg and %callsite 2449e8d8bef9SDimitry Andric // jmp %pc 2450e8d8bef9SDimitry Andric 2451e8d8bef9SDimitry Andric // Shove the dispatch's address into the return slot in the function context. 2452e8d8bef9SDimitry Andric MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock(); 2453e8d8bef9SDimitry Andric DispatchBB->setIsEHPad(true); 2454e8d8bef9SDimitry Andric 2455e8d8bef9SDimitry Andric // Trap BB will causes trap like `assert(0)`. 2456e8d8bef9SDimitry Andric MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock(); 2457e8d8bef9SDimitry Andric DispatchBB->addSuccessor(TrapBB); 2458e8d8bef9SDimitry Andric 2459e8d8bef9SDimitry Andric MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock(); 2460e8d8bef9SDimitry Andric DispatchBB->addSuccessor(DispContBB); 2461e8d8bef9SDimitry Andric 2462e8d8bef9SDimitry Andric // Insert MBBs. 2463e8d8bef9SDimitry Andric MF->push_back(DispatchBB); 2464e8d8bef9SDimitry Andric MF->push_back(DispContBB); 2465e8d8bef9SDimitry Andric MF->push_back(TrapBB); 2466e8d8bef9SDimitry Andric 2467e8d8bef9SDimitry Andric // Insert code to call abort in the TrapBB. 2468e8d8bef9SDimitry Andric Register Abort = prepareSymbol(*TrapBB, TrapBB->end(), "abort", DL, 2469e8d8bef9SDimitry Andric /* Local */ false, /* Call */ true); 2470e8d8bef9SDimitry Andric BuildMI(TrapBB, DL, TII->get(VE::BSICrii), VE::SX10) 2471e8d8bef9SDimitry Andric .addReg(Abort, getKillRegState(true)) 2472e8d8bef9SDimitry Andric .addImm(0) 2473e8d8bef9SDimitry Andric .addImm(0); 2474e8d8bef9SDimitry Andric 2475e8d8bef9SDimitry Andric // Insert code into the entry block that creates and registers the function 2476e8d8bef9SDimitry Andric // context. 2477e8d8bef9SDimitry Andric setupEntryBlockForSjLj(MI, BB, DispatchBB, FI, OffsetIC); 2478e8d8bef9SDimitry Andric 2479e8d8bef9SDimitry Andric // Create the jump table and associated information 2480e8d8bef9SDimitry Andric unsigned JTE = getJumpTableEncoding(); 2481e8d8bef9SDimitry Andric MachineJumpTableInfo *JTI = MF->getOrCreateJumpTableInfo(JTE); 2482e8d8bef9SDimitry Andric unsigned MJTI = JTI->createJumpTableIndex(LPadList); 2483e8d8bef9SDimitry Andric 2484e8d8bef9SDimitry Andric const VERegisterInfo &RI = TII->getRegisterInfo(); 2485e8d8bef9SDimitry Andric // Add a register mask with no preserved registers. This results in all 2486e8d8bef9SDimitry Andric // registers being marked as clobbered. 2487e8d8bef9SDimitry Andric BuildMI(DispatchBB, DL, TII->get(VE::NOP)) 2488e8d8bef9SDimitry Andric .addRegMask(RI.getNoPreservedMask()); 2489e8d8bef9SDimitry Andric 2490e8d8bef9SDimitry Andric if (isPositionIndependent()) { 2491e8d8bef9SDimitry Andric // Force to generate GETGOT, since current implementation doesn't store GOT 2492e8d8bef9SDimitry Andric // register. 2493e8d8bef9SDimitry Andric BuildMI(DispatchBB, DL, TII->get(VE::GETGOT), VE::SX15); 2494e8d8bef9SDimitry Andric } 2495e8d8bef9SDimitry Andric 2496e8d8bef9SDimitry Andric // IReg is used as an index in a memory operand and therefore can't be SP 2497e8d8bef9SDimitry Andric const TargetRegisterClass *RC = &VE::I64RegClass; 2498e8d8bef9SDimitry Andric Register IReg = MRI.createVirtualRegister(RC); 2499e8d8bef9SDimitry Andric addFrameReference(BuildMI(DispatchBB, DL, TII->get(VE::LDLZXrii), IReg), FI, 2500e8d8bef9SDimitry Andric OffsetCS); 2501e8d8bef9SDimitry Andric if (LPadList.size() < 64) { 2502e8d8bef9SDimitry Andric BuildMI(DispatchBB, DL, TII->get(VE::BRCFLir_t)) 2503e8d8bef9SDimitry Andric .addImm(VECC::CC_ILE) 2504e8d8bef9SDimitry Andric .addImm(LPadList.size()) 2505e8d8bef9SDimitry Andric .addReg(IReg) 2506e8d8bef9SDimitry Andric .addMBB(TrapBB); 2507e8d8bef9SDimitry Andric } else { 2508e8d8bef9SDimitry Andric assert(LPadList.size() <= 0x7FFFFFFF && "Too large Landing Pad!"); 2509e8d8bef9SDimitry Andric Register TmpReg = MRI.createVirtualRegister(RC); 2510e8d8bef9SDimitry Andric BuildMI(DispatchBB, DL, TII->get(VE::LEAzii), TmpReg) 2511e8d8bef9SDimitry Andric .addImm(0) 2512e8d8bef9SDimitry Andric .addImm(0) 2513e8d8bef9SDimitry Andric .addImm(LPadList.size()); 2514e8d8bef9SDimitry Andric BuildMI(DispatchBB, DL, TII->get(VE::BRCFLrr_t)) 2515e8d8bef9SDimitry Andric .addImm(VECC::CC_ILE) 2516e8d8bef9SDimitry Andric .addReg(TmpReg, getKillRegState(true)) 2517e8d8bef9SDimitry Andric .addReg(IReg) 2518e8d8bef9SDimitry Andric .addMBB(TrapBB); 2519e8d8bef9SDimitry Andric } 2520e8d8bef9SDimitry Andric 2521e8d8bef9SDimitry Andric Register BReg = MRI.createVirtualRegister(RC); 2522e8d8bef9SDimitry Andric Register Tmp1 = MRI.createVirtualRegister(RC); 2523e8d8bef9SDimitry Andric Register Tmp2 = MRI.createVirtualRegister(RC); 2524e8d8bef9SDimitry Andric 2525e8d8bef9SDimitry Andric if (isPositionIndependent()) { 2526e8d8bef9SDimitry Andric // Create following instructions for local linkage PIC code. 2527e8d8bef9SDimitry Andric // lea %Tmp1, .LJTI0_0@gotoff_lo 2528e8d8bef9SDimitry Andric // and %Tmp2, %Tmp1, (32)0 2529e8d8bef9SDimitry Andric // lea.sl %BReg, .LJTI0_0@gotoff_hi(%Tmp2, %s15) ; %s15 is GOT 2530e8d8bef9SDimitry Andric BuildMI(DispContBB, DL, TII->get(VE::LEAzii), Tmp1) 2531e8d8bef9SDimitry Andric .addImm(0) 2532e8d8bef9SDimitry Andric .addImm(0) 2533e8d8bef9SDimitry Andric .addJumpTableIndex(MJTI, VEMCExpr::VK_VE_GOTOFF_LO32); 2534e8d8bef9SDimitry Andric BuildMI(DispContBB, DL, TII->get(VE::ANDrm), Tmp2) 2535e8d8bef9SDimitry Andric .addReg(Tmp1, getKillRegState(true)) 2536e8d8bef9SDimitry Andric .addImm(M0(32)); 2537e8d8bef9SDimitry Andric BuildMI(DispContBB, DL, TII->get(VE::LEASLrri), BReg) 2538e8d8bef9SDimitry Andric .addReg(VE::SX15) 2539e8d8bef9SDimitry Andric .addReg(Tmp2, getKillRegState(true)) 2540e8d8bef9SDimitry Andric .addJumpTableIndex(MJTI, VEMCExpr::VK_VE_GOTOFF_HI32); 2541e8d8bef9SDimitry Andric } else { 2542e8d8bef9SDimitry Andric // Create following instructions for non-PIC code. 2543e8d8bef9SDimitry Andric // lea %Tmp1, .LJTI0_0@lo 2544e8d8bef9SDimitry Andric // and %Tmp2, %Tmp1, (32)0 2545e8d8bef9SDimitry Andric // lea.sl %BReg, .LJTI0_0@hi(%Tmp2) 2546e8d8bef9SDimitry Andric BuildMI(DispContBB, DL, TII->get(VE::LEAzii), Tmp1) 2547e8d8bef9SDimitry Andric .addImm(0) 2548e8d8bef9SDimitry Andric .addImm(0) 2549e8d8bef9SDimitry Andric .addJumpTableIndex(MJTI, VEMCExpr::VK_VE_LO32); 2550e8d8bef9SDimitry Andric BuildMI(DispContBB, DL, TII->get(VE::ANDrm), Tmp2) 2551e8d8bef9SDimitry Andric .addReg(Tmp1, getKillRegState(true)) 2552e8d8bef9SDimitry Andric .addImm(M0(32)); 2553e8d8bef9SDimitry Andric BuildMI(DispContBB, DL, TII->get(VE::LEASLrii), BReg) 2554e8d8bef9SDimitry Andric .addReg(Tmp2, getKillRegState(true)) 2555e8d8bef9SDimitry Andric .addImm(0) 2556e8d8bef9SDimitry Andric .addJumpTableIndex(MJTI, VEMCExpr::VK_VE_HI32); 2557e8d8bef9SDimitry Andric } 2558e8d8bef9SDimitry Andric 2559e8d8bef9SDimitry Andric switch (JTE) { 2560e8d8bef9SDimitry Andric case MachineJumpTableInfo::EK_BlockAddress: { 2561e8d8bef9SDimitry Andric // Generate simple block address code for no-PIC model. 2562e8d8bef9SDimitry Andric // sll %Tmp1, %IReg, 3 2563e8d8bef9SDimitry Andric // lds %TReg, 0(%Tmp1, %BReg) 2564e8d8bef9SDimitry Andric // bcfla %TReg 2565e8d8bef9SDimitry Andric 2566e8d8bef9SDimitry Andric Register TReg = MRI.createVirtualRegister(RC); 2567e8d8bef9SDimitry Andric Register Tmp1 = MRI.createVirtualRegister(RC); 2568e8d8bef9SDimitry Andric 2569e8d8bef9SDimitry Andric BuildMI(DispContBB, DL, TII->get(VE::SLLri), Tmp1) 2570e8d8bef9SDimitry Andric .addReg(IReg, getKillRegState(true)) 2571e8d8bef9SDimitry Andric .addImm(3); 2572e8d8bef9SDimitry Andric BuildMI(DispContBB, DL, TII->get(VE::LDrri), TReg) 2573e8d8bef9SDimitry Andric .addReg(BReg, getKillRegState(true)) 2574e8d8bef9SDimitry Andric .addReg(Tmp1, getKillRegState(true)) 2575e8d8bef9SDimitry Andric .addImm(0); 2576e8d8bef9SDimitry Andric BuildMI(DispContBB, DL, TII->get(VE::BCFLari_t)) 2577e8d8bef9SDimitry Andric .addReg(TReg, getKillRegState(true)) 2578e8d8bef9SDimitry Andric .addImm(0); 2579e8d8bef9SDimitry Andric break; 2580e8d8bef9SDimitry Andric } 2581e8d8bef9SDimitry Andric case MachineJumpTableInfo::EK_Custom32: { 2582e8d8bef9SDimitry Andric // Generate block address code using differences from the function pointer 2583e8d8bef9SDimitry Andric // for PIC model. 2584e8d8bef9SDimitry Andric // sll %Tmp1, %IReg, 2 2585e8d8bef9SDimitry Andric // ldl.zx %OReg, 0(%Tmp1, %BReg) 2586e8d8bef9SDimitry Andric // Prepare function address in BReg2. 2587e8d8bef9SDimitry Andric // adds.l %TReg, %BReg2, %OReg 2588e8d8bef9SDimitry Andric // bcfla %TReg 2589e8d8bef9SDimitry Andric 2590e8d8bef9SDimitry Andric assert(isPositionIndependent()); 2591e8d8bef9SDimitry Andric Register OReg = MRI.createVirtualRegister(RC); 2592e8d8bef9SDimitry Andric Register TReg = MRI.createVirtualRegister(RC); 2593e8d8bef9SDimitry Andric Register Tmp1 = MRI.createVirtualRegister(RC); 2594e8d8bef9SDimitry Andric 2595e8d8bef9SDimitry Andric BuildMI(DispContBB, DL, TII->get(VE::SLLri), Tmp1) 2596e8d8bef9SDimitry Andric .addReg(IReg, getKillRegState(true)) 2597e8d8bef9SDimitry Andric .addImm(2); 2598e8d8bef9SDimitry Andric BuildMI(DispContBB, DL, TII->get(VE::LDLZXrri), OReg) 2599e8d8bef9SDimitry Andric .addReg(BReg, getKillRegState(true)) 2600e8d8bef9SDimitry Andric .addReg(Tmp1, getKillRegState(true)) 2601e8d8bef9SDimitry Andric .addImm(0); 2602e8d8bef9SDimitry Andric Register BReg2 = 2603e8d8bef9SDimitry Andric prepareSymbol(*DispContBB, DispContBB->end(), 2604e8d8bef9SDimitry Andric DispContBB->getParent()->getName(), DL, /* Local */ true); 2605e8d8bef9SDimitry Andric BuildMI(DispContBB, DL, TII->get(VE::ADDSLrr), TReg) 2606e8d8bef9SDimitry Andric .addReg(OReg, getKillRegState(true)) 2607e8d8bef9SDimitry Andric .addReg(BReg2, getKillRegState(true)); 2608e8d8bef9SDimitry Andric BuildMI(DispContBB, DL, TII->get(VE::BCFLari_t)) 2609e8d8bef9SDimitry Andric .addReg(TReg, getKillRegState(true)) 2610e8d8bef9SDimitry Andric .addImm(0); 2611e8d8bef9SDimitry Andric break; 2612e8d8bef9SDimitry Andric } 2613e8d8bef9SDimitry Andric default: 2614e8d8bef9SDimitry Andric llvm_unreachable("Unexpected jump table encoding"); 2615e8d8bef9SDimitry Andric } 2616e8d8bef9SDimitry Andric 2617e8d8bef9SDimitry Andric // Add the jump table entries as successors to the MBB. 2618e8d8bef9SDimitry Andric SmallPtrSet<MachineBasicBlock *, 8> SeenMBBs; 2619e8d8bef9SDimitry Andric for (auto &LP : LPadList) 2620e8d8bef9SDimitry Andric if (SeenMBBs.insert(LP).second) 2621e8d8bef9SDimitry Andric DispContBB->addSuccessor(LP); 2622e8d8bef9SDimitry Andric 2623e8d8bef9SDimitry Andric // N.B. the order the invoke BBs are processed in doesn't matter here. 2624e8d8bef9SDimitry Andric SmallVector<MachineBasicBlock *, 64> MBBLPads; 2625e8d8bef9SDimitry Andric const MCPhysReg *SavedRegs = MF->getRegInfo().getCalleeSavedRegs(); 2626e8d8bef9SDimitry Andric for (MachineBasicBlock *MBB : InvokeBBs) { 2627e8d8bef9SDimitry Andric // Remove the landing pad successor from the invoke block and replace it 2628e8d8bef9SDimitry Andric // with the new dispatch block. 2629e8d8bef9SDimitry Andric // Keep a copy of Successors since it's modified inside the loop. 2630e8d8bef9SDimitry Andric SmallVector<MachineBasicBlock *, 8> Successors(MBB->succ_rbegin(), 2631e8d8bef9SDimitry Andric MBB->succ_rend()); 2632e8d8bef9SDimitry Andric // FIXME: Avoid quadratic complexity. 2633bdd1243dSDimitry Andric for (auto *MBBS : Successors) { 2634e8d8bef9SDimitry Andric if (MBBS->isEHPad()) { 2635e8d8bef9SDimitry Andric MBB->removeSuccessor(MBBS); 2636e8d8bef9SDimitry Andric MBBLPads.push_back(MBBS); 2637e8d8bef9SDimitry Andric } 2638e8d8bef9SDimitry Andric } 2639e8d8bef9SDimitry Andric 2640e8d8bef9SDimitry Andric MBB->addSuccessor(DispatchBB); 2641e8d8bef9SDimitry Andric 2642e8d8bef9SDimitry Andric // Find the invoke call and mark all of the callee-saved registers as 2643e8d8bef9SDimitry Andric // 'implicit defined' so that they're spilled. This prevents code from 2644e8d8bef9SDimitry Andric // moving instructions to before the EH block, where they will never be 2645e8d8bef9SDimitry Andric // executed. 2646e8d8bef9SDimitry Andric for (auto &II : reverse(*MBB)) { 2647e8d8bef9SDimitry Andric if (!II.isCall()) 2648e8d8bef9SDimitry Andric continue; 2649e8d8bef9SDimitry Andric 2650e8d8bef9SDimitry Andric DenseMap<Register, bool> DefRegs; 2651e8d8bef9SDimitry Andric for (auto &MOp : II.operands()) 2652e8d8bef9SDimitry Andric if (MOp.isReg()) 2653e8d8bef9SDimitry Andric DefRegs[MOp.getReg()] = true; 2654e8d8bef9SDimitry Andric 2655e8d8bef9SDimitry Andric MachineInstrBuilder MIB(*MF, &II); 2656e8d8bef9SDimitry Andric for (unsigned RI = 0; SavedRegs[RI]; ++RI) { 2657e8d8bef9SDimitry Andric Register Reg = SavedRegs[RI]; 2658e8d8bef9SDimitry Andric if (!DefRegs[Reg]) 2659e8d8bef9SDimitry Andric MIB.addReg(Reg, RegState::ImplicitDefine | RegState::Dead); 2660e8d8bef9SDimitry Andric } 2661e8d8bef9SDimitry Andric 2662e8d8bef9SDimitry Andric break; 2663e8d8bef9SDimitry Andric } 2664e8d8bef9SDimitry Andric } 2665e8d8bef9SDimitry Andric 2666e8d8bef9SDimitry Andric // Mark all former landing pads as non-landing pads. The dispatch is the only 2667e8d8bef9SDimitry Andric // landing pad now. 2668e8d8bef9SDimitry Andric for (auto &LP : MBBLPads) 2669e8d8bef9SDimitry Andric LP->setIsEHPad(false); 2670e8d8bef9SDimitry Andric 2671e8d8bef9SDimitry Andric // The instruction is gone now. 2672e8d8bef9SDimitry Andric MI.eraseFromParent(); 2673e8d8bef9SDimitry Andric return BB; 2674e8d8bef9SDimitry Andric } 2675e8d8bef9SDimitry Andric 2676e8d8bef9SDimitry Andric MachineBasicBlock * 2677e8d8bef9SDimitry Andric VETargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, 2678e8d8bef9SDimitry Andric MachineBasicBlock *BB) const { 2679e8d8bef9SDimitry Andric switch (MI.getOpcode()) { 2680e8d8bef9SDimitry Andric default: 2681e8d8bef9SDimitry Andric llvm_unreachable("Unknown Custom Instruction!"); 2682e8d8bef9SDimitry Andric case VE::EH_SjLj_LongJmp: 2683e8d8bef9SDimitry Andric return emitEHSjLjLongJmp(MI, BB); 2684e8d8bef9SDimitry Andric case VE::EH_SjLj_SetJmp: 2685e8d8bef9SDimitry Andric return emitEHSjLjSetJmp(MI, BB); 2686e8d8bef9SDimitry Andric case VE::EH_SjLj_Setup_Dispatch: 2687e8d8bef9SDimitry Andric return emitSjLjDispatchBlock(MI, BB); 2688e8d8bef9SDimitry Andric } 2689e8d8bef9SDimitry Andric } 2690e8d8bef9SDimitry Andric 2691bdd1243dSDimitry Andric static bool isSimm7(SDValue V) { 2692bdd1243dSDimitry Andric EVT VT = V.getValueType(); 2693bdd1243dSDimitry Andric if (VT.isVector()) 2694bdd1243dSDimitry Andric return false; 2695bdd1243dSDimitry Andric 2696bdd1243dSDimitry Andric if (VT.isInteger()) { 2697bdd1243dSDimitry Andric if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(V)) 2698bdd1243dSDimitry Andric return isInt<7>(C->getSExtValue()); 2699bdd1243dSDimitry Andric } else if (VT.isFloatingPoint()) { 2700bdd1243dSDimitry Andric if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(V)) { 2701bdd1243dSDimitry Andric if (VT == MVT::f32 || VT == MVT::f64) { 2702bdd1243dSDimitry Andric const APInt &Imm = C->getValueAPF().bitcastToAPInt(); 2703bdd1243dSDimitry Andric uint64_t Val = Imm.getSExtValue(); 2704bdd1243dSDimitry Andric if (Imm.getBitWidth() == 32) 2705bdd1243dSDimitry Andric Val <<= 32; // Immediate value of float place at higher bits on VE. 2706bdd1243dSDimitry Andric return isInt<7>(Val); 2707bdd1243dSDimitry Andric } 2708bdd1243dSDimitry Andric } 2709bdd1243dSDimitry Andric } 2710bdd1243dSDimitry Andric return false; 2711bdd1243dSDimitry Andric } 2712bdd1243dSDimitry Andric 2713bdd1243dSDimitry Andric static bool isMImm(SDValue V) { 2714bdd1243dSDimitry Andric EVT VT = V.getValueType(); 2715bdd1243dSDimitry Andric if (VT.isVector()) 2716bdd1243dSDimitry Andric return false; 2717bdd1243dSDimitry Andric 2718bdd1243dSDimitry Andric if (VT.isInteger()) { 2719bdd1243dSDimitry Andric if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(V)) 2720bdd1243dSDimitry Andric return isMImmVal(getImmVal(C)); 2721bdd1243dSDimitry Andric } else if (VT.isFloatingPoint()) { 2722bdd1243dSDimitry Andric if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(V)) { 2723bdd1243dSDimitry Andric if (VT == MVT::f32) { 2724bdd1243dSDimitry Andric // Float value places at higher bits, so ignore lower 32 bits. 2725bdd1243dSDimitry Andric return isMImm32Val(getFpImmVal(C) >> 32); 2726bdd1243dSDimitry Andric } else if (VT == MVT::f64) { 2727bdd1243dSDimitry Andric return isMImmVal(getFpImmVal(C)); 2728bdd1243dSDimitry Andric } 2729bdd1243dSDimitry Andric } 2730bdd1243dSDimitry Andric } 2731bdd1243dSDimitry Andric return false; 2732bdd1243dSDimitry Andric } 2733bdd1243dSDimitry Andric 2734bdd1243dSDimitry Andric static unsigned decideComp(EVT SrcVT, ISD::CondCode CC) { 2735bdd1243dSDimitry Andric if (SrcVT.isFloatingPoint()) { 2736bdd1243dSDimitry Andric if (SrcVT == MVT::f128) 2737bdd1243dSDimitry Andric return VEISD::CMPQ; 2738bdd1243dSDimitry Andric return VEISD::CMPF; 2739bdd1243dSDimitry Andric } 2740bdd1243dSDimitry Andric return isSignedIntSetCC(CC) ? VEISD::CMPI : VEISD::CMPU; 2741bdd1243dSDimitry Andric } 2742bdd1243dSDimitry Andric 2743bdd1243dSDimitry Andric static EVT decideCompType(EVT SrcVT) { 2744bdd1243dSDimitry Andric if (SrcVT == MVT::f128) 2745bdd1243dSDimitry Andric return MVT::f64; 2746bdd1243dSDimitry Andric return SrcVT; 2747bdd1243dSDimitry Andric } 2748bdd1243dSDimitry Andric 2749bdd1243dSDimitry Andric static bool safeWithoutCompWithNull(EVT SrcVT, ISD::CondCode CC, 2750bdd1243dSDimitry Andric bool WithCMov) { 2751bdd1243dSDimitry Andric if (SrcVT.isFloatingPoint()) { 2752bdd1243dSDimitry Andric // For the case of floating point setcc, only unordered comparison 2753bdd1243dSDimitry Andric // or general comparison with -enable-no-nans-fp-math option reach 2754bdd1243dSDimitry Andric // here, so it is safe even if values are NaN. Only f128 doesn't 2755bdd1243dSDimitry Andric // safe since VE uses f64 result of f128 comparison. 2756bdd1243dSDimitry Andric return SrcVT != MVT::f128; 2757bdd1243dSDimitry Andric } 2758bdd1243dSDimitry Andric if (isIntEqualitySetCC(CC)) { 2759bdd1243dSDimitry Andric // For the case of equal or not equal, it is safe without comparison with 0. 2760bdd1243dSDimitry Andric return true; 2761bdd1243dSDimitry Andric } 2762bdd1243dSDimitry Andric if (WithCMov) { 2763bdd1243dSDimitry Andric // For the case of integer setcc with cmov, all signed comparison with 0 2764bdd1243dSDimitry Andric // are safe. 2765bdd1243dSDimitry Andric return isSignedIntSetCC(CC); 2766bdd1243dSDimitry Andric } 2767bdd1243dSDimitry Andric // For the case of integer setcc, only signed 64 bits comparison is safe. 2768bdd1243dSDimitry Andric // For unsigned, "CMPU 0x80000000, 0" has to be greater than 0, but it becomes 2769bdd1243dSDimitry Andric // less than 0 witout CMPU. For 32 bits, other half of 32 bits are 2770bdd1243dSDimitry Andric // uncoditional, so it is not safe too without CMPI.. 2771bdd1243dSDimitry Andric return isSignedIntSetCC(CC) && SrcVT == MVT::i64; 2772bdd1243dSDimitry Andric } 2773bdd1243dSDimitry Andric 2774bdd1243dSDimitry Andric static SDValue generateComparison(EVT VT, SDValue LHS, SDValue RHS, 2775bdd1243dSDimitry Andric ISD::CondCode CC, bool WithCMov, 2776bdd1243dSDimitry Andric const SDLoc &DL, SelectionDAG &DAG) { 2777bdd1243dSDimitry Andric // Compare values. If RHS is 0 and it is safe to calculate without 2778bdd1243dSDimitry Andric // comparison, we don't generate an instruction for comparison. 2779bdd1243dSDimitry Andric EVT CompVT = decideCompType(VT); 2780bdd1243dSDimitry Andric if (CompVT == VT && safeWithoutCompWithNull(VT, CC, WithCMov) && 2781bdd1243dSDimitry Andric (isNullConstant(RHS) || isNullFPConstant(RHS))) { 2782bdd1243dSDimitry Andric return LHS; 2783bdd1243dSDimitry Andric } 2784bdd1243dSDimitry Andric return DAG.getNode(decideComp(VT, CC), DL, CompVT, LHS, RHS); 2785bdd1243dSDimitry Andric } 2786bdd1243dSDimitry Andric 2787bdd1243dSDimitry Andric SDValue VETargetLowering::combineSelect(SDNode *N, 2788bdd1243dSDimitry Andric DAGCombinerInfo &DCI) const { 2789bdd1243dSDimitry Andric assert(N->getOpcode() == ISD::SELECT && 2790bdd1243dSDimitry Andric "Should be called with a SELECT node"); 2791bdd1243dSDimitry Andric ISD::CondCode CC = ISD::CondCode::SETNE; 2792bdd1243dSDimitry Andric SDValue Cond = N->getOperand(0); 2793bdd1243dSDimitry Andric SDValue True = N->getOperand(1); 2794bdd1243dSDimitry Andric SDValue False = N->getOperand(2); 2795bdd1243dSDimitry Andric 2796bdd1243dSDimitry Andric // We handle only scalar SELECT. 2797bdd1243dSDimitry Andric EVT VT = N->getValueType(0); 2798bdd1243dSDimitry Andric if (VT.isVector()) 2799bdd1243dSDimitry Andric return SDValue(); 2800bdd1243dSDimitry Andric 2801bdd1243dSDimitry Andric // Peform combineSelect after leagalize DAG. 2802bdd1243dSDimitry Andric if (!DCI.isAfterLegalizeDAG()) 2803bdd1243dSDimitry Andric return SDValue(); 2804bdd1243dSDimitry Andric 2805bdd1243dSDimitry Andric EVT VT0 = Cond.getValueType(); 2806bdd1243dSDimitry Andric if (isMImm(True)) { 2807bdd1243dSDimitry Andric // VE's condition move can handle MImm in True clause, so nothing to do. 2808bdd1243dSDimitry Andric } else if (isMImm(False)) { 2809bdd1243dSDimitry Andric // VE's condition move can handle MImm in True clause, so swap True and 2810bdd1243dSDimitry Andric // False clauses if False has MImm value. And, update condition code. 2811bdd1243dSDimitry Andric std::swap(True, False); 2812bdd1243dSDimitry Andric CC = getSetCCInverse(CC, VT0); 2813bdd1243dSDimitry Andric } 2814bdd1243dSDimitry Andric 2815bdd1243dSDimitry Andric SDLoc DL(N); 2816bdd1243dSDimitry Andric SelectionDAG &DAG = DCI.DAG; 2817bdd1243dSDimitry Andric VECC::CondCode VECCVal; 2818bdd1243dSDimitry Andric if (VT0.isFloatingPoint()) { 2819bdd1243dSDimitry Andric VECCVal = fpCondCode2Fcc(CC); 2820bdd1243dSDimitry Andric } else { 2821bdd1243dSDimitry Andric VECCVal = intCondCode2Icc(CC); 2822bdd1243dSDimitry Andric } 2823bdd1243dSDimitry Andric SDValue Ops[] = {Cond, True, False, 2824bdd1243dSDimitry Andric DAG.getConstant(VECCVal, DL, MVT::i32)}; 2825bdd1243dSDimitry Andric return DAG.getNode(VEISD::CMOV, DL, VT, Ops); 2826bdd1243dSDimitry Andric } 2827bdd1243dSDimitry Andric 2828bdd1243dSDimitry Andric SDValue VETargetLowering::combineSelectCC(SDNode *N, 2829bdd1243dSDimitry Andric DAGCombinerInfo &DCI) const { 2830bdd1243dSDimitry Andric assert(N->getOpcode() == ISD::SELECT_CC && 2831bdd1243dSDimitry Andric "Should be called with a SELECT_CC node"); 2832bdd1243dSDimitry Andric ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(4))->get(); 2833bdd1243dSDimitry Andric SDValue LHS = N->getOperand(0); 2834bdd1243dSDimitry Andric SDValue RHS = N->getOperand(1); 2835bdd1243dSDimitry Andric SDValue True = N->getOperand(2); 2836bdd1243dSDimitry Andric SDValue False = N->getOperand(3); 2837bdd1243dSDimitry Andric 2838bdd1243dSDimitry Andric // We handle only scalar SELECT_CC. 2839bdd1243dSDimitry Andric EVT VT = N->getValueType(0); 2840bdd1243dSDimitry Andric if (VT.isVector()) 2841bdd1243dSDimitry Andric return SDValue(); 2842bdd1243dSDimitry Andric 2843bdd1243dSDimitry Andric // Peform combineSelectCC after leagalize DAG. 2844bdd1243dSDimitry Andric if (!DCI.isAfterLegalizeDAG()) 2845bdd1243dSDimitry Andric return SDValue(); 2846bdd1243dSDimitry Andric 2847bdd1243dSDimitry Andric // We handle only i32/i64/f32/f64/f128 comparisons. 2848bdd1243dSDimitry Andric EVT LHSVT = LHS.getValueType(); 2849bdd1243dSDimitry Andric assert(LHSVT == RHS.getValueType()); 2850bdd1243dSDimitry Andric switch (LHSVT.getSimpleVT().SimpleTy) { 2851bdd1243dSDimitry Andric case MVT::i32: 2852bdd1243dSDimitry Andric case MVT::i64: 2853bdd1243dSDimitry Andric case MVT::f32: 2854bdd1243dSDimitry Andric case MVT::f64: 2855bdd1243dSDimitry Andric case MVT::f128: 2856bdd1243dSDimitry Andric break; 2857bdd1243dSDimitry Andric default: 2858bdd1243dSDimitry Andric // Return SDValue to let llvm handle other types. 2859bdd1243dSDimitry Andric return SDValue(); 2860bdd1243dSDimitry Andric } 2861bdd1243dSDimitry Andric 2862bdd1243dSDimitry Andric if (isMImm(RHS)) { 2863bdd1243dSDimitry Andric // VE's comparison can handle MImm in RHS, so nothing to do. 2864bdd1243dSDimitry Andric } else if (isSimm7(RHS)) { 2865bdd1243dSDimitry Andric // VE's comparison can handle Simm7 in LHS, so swap LHS and RHS, and 2866bdd1243dSDimitry Andric // update condition code. 2867bdd1243dSDimitry Andric std::swap(LHS, RHS); 2868bdd1243dSDimitry Andric CC = getSetCCSwappedOperands(CC); 2869bdd1243dSDimitry Andric } 2870bdd1243dSDimitry Andric if (isMImm(True)) { 2871bdd1243dSDimitry Andric // VE's condition move can handle MImm in True clause, so nothing to do. 2872bdd1243dSDimitry Andric } else if (isMImm(False)) { 2873bdd1243dSDimitry Andric // VE's condition move can handle MImm in True clause, so swap True and 2874bdd1243dSDimitry Andric // False clauses if False has MImm value. And, update condition code. 2875bdd1243dSDimitry Andric std::swap(True, False); 2876bdd1243dSDimitry Andric CC = getSetCCInverse(CC, LHSVT); 2877bdd1243dSDimitry Andric } 2878bdd1243dSDimitry Andric 2879bdd1243dSDimitry Andric SDLoc DL(N); 2880bdd1243dSDimitry Andric SelectionDAG &DAG = DCI.DAG; 2881bdd1243dSDimitry Andric 2882bdd1243dSDimitry Andric bool WithCMov = true; 2883bdd1243dSDimitry Andric SDValue CompNode = generateComparison(LHSVT, LHS, RHS, CC, WithCMov, DL, DAG); 2884bdd1243dSDimitry Andric 2885bdd1243dSDimitry Andric VECC::CondCode VECCVal; 2886bdd1243dSDimitry Andric if (LHSVT.isFloatingPoint()) { 2887bdd1243dSDimitry Andric VECCVal = fpCondCode2Fcc(CC); 2888bdd1243dSDimitry Andric } else { 2889bdd1243dSDimitry Andric VECCVal = intCondCode2Icc(CC); 2890bdd1243dSDimitry Andric } 2891bdd1243dSDimitry Andric SDValue Ops[] = {CompNode, True, False, 2892bdd1243dSDimitry Andric DAG.getConstant(VECCVal, DL, MVT::i32)}; 2893bdd1243dSDimitry Andric return DAG.getNode(VEISD::CMOV, DL, VT, Ops); 2894bdd1243dSDimitry Andric } 2895bdd1243dSDimitry Andric 2896bdd1243dSDimitry Andric static bool isI32InsnAllUses(const SDNode *User, const SDNode *N); 2897e8d8bef9SDimitry Andric static bool isI32Insn(const SDNode *User, const SDNode *N) { 2898e8d8bef9SDimitry Andric switch (User->getOpcode()) { 2899e8d8bef9SDimitry Andric default: 2900e8d8bef9SDimitry Andric return false; 2901e8d8bef9SDimitry Andric case ISD::ADD: 2902e8d8bef9SDimitry Andric case ISD::SUB: 2903e8d8bef9SDimitry Andric case ISD::MUL: 2904e8d8bef9SDimitry Andric case ISD::SDIV: 2905e8d8bef9SDimitry Andric case ISD::UDIV: 2906e8d8bef9SDimitry Andric case ISD::SETCC: 2907e8d8bef9SDimitry Andric case ISD::SMIN: 2908e8d8bef9SDimitry Andric case ISD::SMAX: 2909e8d8bef9SDimitry Andric case ISD::SHL: 2910e8d8bef9SDimitry Andric case ISD::SRA: 2911e8d8bef9SDimitry Andric case ISD::BSWAP: 2912e8d8bef9SDimitry Andric case ISD::SINT_TO_FP: 2913e8d8bef9SDimitry Andric case ISD::UINT_TO_FP: 2914e8d8bef9SDimitry Andric case ISD::BR_CC: 2915e8d8bef9SDimitry Andric case ISD::BITCAST: 2916e8d8bef9SDimitry Andric case ISD::ATOMIC_CMP_SWAP: 2917e8d8bef9SDimitry Andric case ISD::ATOMIC_SWAP: 2918bdd1243dSDimitry Andric case VEISD::CMPU: 2919bdd1243dSDimitry Andric case VEISD::CMPI: 2920e8d8bef9SDimitry Andric return true; 2921e8d8bef9SDimitry Andric case ISD::SRL: 2922e8d8bef9SDimitry Andric if (N->getOperand(0).getOpcode() != ISD::SRL) 2923e8d8bef9SDimitry Andric return true; 2924e8d8bef9SDimitry Andric // (srl (trunc (srl ...))) may be optimized by combining srl, so 2925e8d8bef9SDimitry Andric // doesn't optimize trunc now. 2926e8d8bef9SDimitry Andric return false; 2927e8d8bef9SDimitry Andric case ISD::SELECT_CC: 2928e8d8bef9SDimitry Andric if (User->getOperand(2).getNode() != N && 2929e8d8bef9SDimitry Andric User->getOperand(3).getNode() != N) 2930e8d8bef9SDimitry Andric return true; 2931bdd1243dSDimitry Andric return isI32InsnAllUses(User, N); 2932bdd1243dSDimitry Andric case VEISD::CMOV: 2933bdd1243dSDimitry Andric // CMOV in (cmov (trunc ...), true, false, int-comparison) is safe. 2934bdd1243dSDimitry Andric // However, trunc in true or false clauses is not safe. 2935bdd1243dSDimitry Andric if (User->getOperand(1).getNode() != N && 2936bdd1243dSDimitry Andric User->getOperand(2).getNode() != N && 2937bdd1243dSDimitry Andric isa<ConstantSDNode>(User->getOperand(3))) { 2938647cbc5dSDimitry Andric VECC::CondCode VECCVal = 2939647cbc5dSDimitry Andric static_cast<VECC::CondCode>(User->getConstantOperandVal(3)); 2940bdd1243dSDimitry Andric return isIntVECondCode(VECCVal); 2941bdd1243dSDimitry Andric } 2942bdd1243dSDimitry Andric [[fallthrough]]; 2943e8d8bef9SDimitry Andric case ISD::AND: 2944e8d8bef9SDimitry Andric case ISD::OR: 2945e8d8bef9SDimitry Andric case ISD::XOR: 2946e8d8bef9SDimitry Andric case ISD::SELECT: 2947e8d8bef9SDimitry Andric case ISD::CopyToReg: 2948e8d8bef9SDimitry Andric // Check all use of selections, bit operations, and copies. If all of them 2949e8d8bef9SDimitry Andric // are safe, optimize truncate to extract_subreg. 2950bdd1243dSDimitry Andric return isI32InsnAllUses(User, N); 2951bdd1243dSDimitry Andric } 2952bdd1243dSDimitry Andric } 2953bdd1243dSDimitry Andric 2954bdd1243dSDimitry Andric static bool isI32InsnAllUses(const SDNode *User, const SDNode *N) { 2955bdd1243dSDimitry Andric // Check all use of User node. If all of them are safe, optimize 2956bdd1243dSDimitry Andric // truncate to extract_subreg. 2957349cc55cSDimitry Andric for (const SDNode *U : User->uses()) { 2958349cc55cSDimitry Andric switch (U->getOpcode()) { 2959e8d8bef9SDimitry Andric default: 2960e8d8bef9SDimitry Andric // If the use is an instruction which treats the source operand as i32, 2961e8d8bef9SDimitry Andric // it is safe to avoid truncate here. 2962349cc55cSDimitry Andric if (isI32Insn(U, N)) 2963e8d8bef9SDimitry Andric continue; 2964e8d8bef9SDimitry Andric break; 2965e8d8bef9SDimitry Andric case ISD::ANY_EXTEND: 2966e8d8bef9SDimitry Andric case ISD::SIGN_EXTEND: 2967e8d8bef9SDimitry Andric case ISD::ZERO_EXTEND: { 2968e8d8bef9SDimitry Andric // Special optimizations to the combination of ext and trunc. 2969e8d8bef9SDimitry Andric // (ext ... (select ... (trunc ...))) is safe to avoid truncate here 2970e8d8bef9SDimitry Andric // since this truncate instruction clears higher 32 bits which is filled 2971e8d8bef9SDimitry Andric // by one of ext instructions later. 2972e8d8bef9SDimitry Andric assert(N->getValueType(0) == MVT::i32 && 2973e8d8bef9SDimitry Andric "find truncate to not i32 integer"); 2974e8d8bef9SDimitry Andric if (User->getOpcode() == ISD::SELECT_CC || 2975bdd1243dSDimitry Andric User->getOpcode() == ISD::SELECT || User->getOpcode() == VEISD::CMOV) 2976e8d8bef9SDimitry Andric continue; 2977e8d8bef9SDimitry Andric break; 2978e8d8bef9SDimitry Andric } 2979e8d8bef9SDimitry Andric } 2980e8d8bef9SDimitry Andric return false; 2981e8d8bef9SDimitry Andric } 2982e8d8bef9SDimitry Andric return true; 2983e8d8bef9SDimitry Andric } 2984e8d8bef9SDimitry Andric 2985e8d8bef9SDimitry Andric // Optimize TRUNCATE in DAG combining. Optimizing it in CUSTOM lower is 2986e8d8bef9SDimitry Andric // sometime too early. Optimizing it in DAG pattern matching in VEInstrInfo.td 2987e8d8bef9SDimitry Andric // is sometime too late. So, doing it at here. 2988e8d8bef9SDimitry Andric SDValue VETargetLowering::combineTRUNCATE(SDNode *N, 2989e8d8bef9SDimitry Andric DAGCombinerInfo &DCI) const { 2990e8d8bef9SDimitry Andric assert(N->getOpcode() == ISD::TRUNCATE && 2991e8d8bef9SDimitry Andric "Should be called with a TRUNCATE node"); 2992e8d8bef9SDimitry Andric 2993e8d8bef9SDimitry Andric SelectionDAG &DAG = DCI.DAG; 2994e8d8bef9SDimitry Andric SDLoc DL(N); 2995e8d8bef9SDimitry Andric EVT VT = N->getValueType(0); 2996e8d8bef9SDimitry Andric 2997e8d8bef9SDimitry Andric // We prefer to do this when all types are legal. 2998e8d8bef9SDimitry Andric if (!DCI.isAfterLegalizeDAG()) 2999e8d8bef9SDimitry Andric return SDValue(); 3000e8d8bef9SDimitry Andric 3001e8d8bef9SDimitry Andric // Skip combine TRUNCATE atm if the operand of TRUNCATE might be a constant. 3002e8d8bef9SDimitry Andric if (N->getOperand(0)->getOpcode() == ISD::SELECT_CC && 3003e8d8bef9SDimitry Andric isa<ConstantSDNode>(N->getOperand(0)->getOperand(0)) && 3004e8d8bef9SDimitry Andric isa<ConstantSDNode>(N->getOperand(0)->getOperand(1))) 3005e8d8bef9SDimitry Andric return SDValue(); 3006e8d8bef9SDimitry Andric 3007e8d8bef9SDimitry Andric // Check all use of this TRUNCATE. 3008349cc55cSDimitry Andric for (const SDNode *User : N->uses()) { 3009e8d8bef9SDimitry Andric // Make sure that we're not going to replace TRUNCATE for non i32 3010e8d8bef9SDimitry Andric // instructions. 3011e8d8bef9SDimitry Andric // 3012e8d8bef9SDimitry Andric // FIXME: Although we could sometimes handle this, and it does occur in 3013e8d8bef9SDimitry Andric // practice that one of the condition inputs to the select is also one of 3014e8d8bef9SDimitry Andric // the outputs, we currently can't deal with this. 3015e8d8bef9SDimitry Andric if (isI32Insn(User, N)) 3016e8d8bef9SDimitry Andric continue; 3017e8d8bef9SDimitry Andric 3018e8d8bef9SDimitry Andric return SDValue(); 3019e8d8bef9SDimitry Andric } 3020e8d8bef9SDimitry Andric 3021e8d8bef9SDimitry Andric SDValue SubI32 = DAG.getTargetConstant(VE::sub_i32, DL, MVT::i32); 3022e8d8bef9SDimitry Andric return SDValue(DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, VT, 3023e8d8bef9SDimitry Andric N->getOperand(0), SubI32), 3024e8d8bef9SDimitry Andric 0); 3025e8d8bef9SDimitry Andric } 3026e8d8bef9SDimitry Andric 3027e8d8bef9SDimitry Andric SDValue VETargetLowering::PerformDAGCombine(SDNode *N, 3028e8d8bef9SDimitry Andric DAGCombinerInfo &DCI) const { 3029e8d8bef9SDimitry Andric switch (N->getOpcode()) { 3030e8d8bef9SDimitry Andric default: 3031e8d8bef9SDimitry Andric break; 3032bdd1243dSDimitry Andric case ISD::SELECT: 3033bdd1243dSDimitry Andric return combineSelect(N, DCI); 3034bdd1243dSDimitry Andric case ISD::SELECT_CC: 3035bdd1243dSDimitry Andric return combineSelectCC(N, DCI); 3036e8d8bef9SDimitry Andric case ISD::TRUNCATE: 3037e8d8bef9SDimitry Andric return combineTRUNCATE(N, DCI); 3038e8d8bef9SDimitry Andric } 3039e8d8bef9SDimitry Andric 3040e8d8bef9SDimitry Andric return SDValue(); 3041e8d8bef9SDimitry Andric } 3042e8d8bef9SDimitry Andric 3043e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 3044e8d8bef9SDimitry Andric // VE Inline Assembly Support 3045e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 3046e8d8bef9SDimitry Andric 3047e8d8bef9SDimitry Andric VETargetLowering::ConstraintType 3048e8d8bef9SDimitry Andric VETargetLowering::getConstraintType(StringRef Constraint) const { 3049e8d8bef9SDimitry Andric if (Constraint.size() == 1) { 3050e8d8bef9SDimitry Andric switch (Constraint[0]) { 3051e8d8bef9SDimitry Andric default: 3052e8d8bef9SDimitry Andric break; 3053e8d8bef9SDimitry Andric case 'v': // vector registers 3054e8d8bef9SDimitry Andric return C_RegisterClass; 3055e8d8bef9SDimitry Andric } 3056e8d8bef9SDimitry Andric } 3057e8d8bef9SDimitry Andric return TargetLowering::getConstraintType(Constraint); 3058e8d8bef9SDimitry Andric } 3059e8d8bef9SDimitry Andric 3060e8d8bef9SDimitry Andric std::pair<unsigned, const TargetRegisterClass *> 3061e8d8bef9SDimitry Andric VETargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, 3062e8d8bef9SDimitry Andric StringRef Constraint, 3063e8d8bef9SDimitry Andric MVT VT) const { 3064e8d8bef9SDimitry Andric const TargetRegisterClass *RC = nullptr; 3065e8d8bef9SDimitry Andric if (Constraint.size() == 1) { 3066e8d8bef9SDimitry Andric switch (Constraint[0]) { 3067e8d8bef9SDimitry Andric default: 3068e8d8bef9SDimitry Andric return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); 3069e8d8bef9SDimitry Andric case 'r': 3070e8d8bef9SDimitry Andric RC = &VE::I64RegClass; 3071e8d8bef9SDimitry Andric break; 3072e8d8bef9SDimitry Andric case 'v': 3073e8d8bef9SDimitry Andric RC = &VE::V64RegClass; 3074e8d8bef9SDimitry Andric break; 3075e8d8bef9SDimitry Andric } 3076e8d8bef9SDimitry Andric return std::make_pair(0U, RC); 3077e8d8bef9SDimitry Andric } 3078e8d8bef9SDimitry Andric 3079e8d8bef9SDimitry Andric return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); 3080e8d8bef9SDimitry Andric } 3081e8d8bef9SDimitry Andric 3082e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 3083e8d8bef9SDimitry Andric // VE Target Optimization Support 3084e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 3085e8d8bef9SDimitry Andric 3086e8d8bef9SDimitry Andric unsigned VETargetLowering::getMinimumJumpTableEntries() const { 3087e8d8bef9SDimitry Andric // Specify 8 for PIC model to relieve the impact of PIC load instructions. 3088e8d8bef9SDimitry Andric if (isJumpTableRelative()) 3089e8d8bef9SDimitry Andric return 8; 3090e8d8bef9SDimitry Andric 3091e8d8bef9SDimitry Andric return TargetLowering::getMinimumJumpTableEntries(); 3092e8d8bef9SDimitry Andric } 3093e8d8bef9SDimitry Andric 3094e8d8bef9SDimitry Andric bool VETargetLowering::hasAndNot(SDValue Y) const { 3095e8d8bef9SDimitry Andric EVT VT = Y.getValueType(); 3096e8d8bef9SDimitry Andric 3097e8d8bef9SDimitry Andric // VE doesn't have vector and not instruction. 3098e8d8bef9SDimitry Andric if (VT.isVector()) 3099e8d8bef9SDimitry Andric return false; 3100e8d8bef9SDimitry Andric 3101e8d8bef9SDimitry Andric // VE allows different immediate values for X and Y where ~X & Y. 3102e8d8bef9SDimitry Andric // Only simm7 works for X, and only mimm works for Y on VE. However, this 3103e8d8bef9SDimitry Andric // function is used to check whether an immediate value is OK for and-not 3104e8d8bef9SDimitry Andric // instruction as both X and Y. Generating additional instruction to 3105e8d8bef9SDimitry Andric // retrieve an immediate value is no good since the purpose of this 3106e8d8bef9SDimitry Andric // function is to convert a series of 3 instructions to another series of 3107e8d8bef9SDimitry Andric // 3 instructions with better parallelism. Therefore, we return false 3108e8d8bef9SDimitry Andric // for all immediate values now. 3109e8d8bef9SDimitry Andric // FIXME: Change hasAndNot function to have two operands to make it work 3110e8d8bef9SDimitry Andric // correctly with Aurora VE. 3111e8d8bef9SDimitry Andric if (isa<ConstantSDNode>(Y)) 3112e8d8bef9SDimitry Andric return false; 3113e8d8bef9SDimitry Andric 3114e8d8bef9SDimitry Andric // It's ok for generic registers. 3115e8d8bef9SDimitry Andric return true; 3116e8d8bef9SDimitry Andric } 3117e8d8bef9SDimitry Andric 3118e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerEXTRACT_VECTOR_ELT(SDValue Op, 3119e8d8bef9SDimitry Andric SelectionDAG &DAG) const { 3120e8d8bef9SDimitry Andric assert(Op.getOpcode() == ISD::EXTRACT_VECTOR_ELT && "Unknown opcode!"); 3121e8d8bef9SDimitry Andric MVT VT = Op.getOperand(0).getSimpleValueType(); 3122e8d8bef9SDimitry Andric 3123e8d8bef9SDimitry Andric // Special treatment for packed V64 types. 3124e8d8bef9SDimitry Andric assert(VT == MVT::v512i32 || VT == MVT::v512f32); 3125fe6060f1SDimitry Andric (void)VT; 3126e8d8bef9SDimitry Andric // Example of codes: 3127e8d8bef9SDimitry Andric // %packed_v = extractelt %vr, %idx / 2 3128e8d8bef9SDimitry Andric // %v = %packed_v >> (%idx % 2 * 32) 3129e8d8bef9SDimitry Andric // %res = %v & 0xffffffff 3130e8d8bef9SDimitry Andric 3131e8d8bef9SDimitry Andric SDValue Vec = Op.getOperand(0); 3132e8d8bef9SDimitry Andric SDValue Idx = Op.getOperand(1); 3133e8d8bef9SDimitry Andric SDLoc DL(Op); 3134e8d8bef9SDimitry Andric SDValue Result = Op; 313504eeddc0SDimitry Andric if (false /* Idx->isConstant() */) { 3136e8d8bef9SDimitry Andric // TODO: optimized implementation using constant values 3137e8d8bef9SDimitry Andric } else { 3138e8d8bef9SDimitry Andric SDValue Const1 = DAG.getConstant(1, DL, MVT::i64); 3139e8d8bef9SDimitry Andric SDValue HalfIdx = DAG.getNode(ISD::SRL, DL, MVT::i64, {Idx, Const1}); 3140e8d8bef9SDimitry Andric SDValue PackedElt = 3141e8d8bef9SDimitry Andric SDValue(DAG.getMachineNode(VE::LVSvr, DL, MVT::i64, {Vec, HalfIdx}), 0); 3142e8d8bef9SDimitry Andric SDValue AndIdx = DAG.getNode(ISD::AND, DL, MVT::i64, {Idx, Const1}); 3143e8d8bef9SDimitry Andric SDValue Shift = DAG.getNode(ISD::XOR, DL, MVT::i64, {AndIdx, Const1}); 3144e8d8bef9SDimitry Andric SDValue Const5 = DAG.getConstant(5, DL, MVT::i64); 3145e8d8bef9SDimitry Andric Shift = DAG.getNode(ISD::SHL, DL, MVT::i64, {Shift, Const5}); 3146e8d8bef9SDimitry Andric PackedElt = DAG.getNode(ISD::SRL, DL, MVT::i64, {PackedElt, Shift}); 3147e8d8bef9SDimitry Andric SDValue Mask = DAG.getConstant(0xFFFFFFFFL, DL, MVT::i64); 3148e8d8bef9SDimitry Andric PackedElt = DAG.getNode(ISD::AND, DL, MVT::i64, {PackedElt, Mask}); 3149e8d8bef9SDimitry Andric SDValue SubI32 = DAG.getTargetConstant(VE::sub_i32, DL, MVT::i32); 3150e8d8bef9SDimitry Andric Result = SDValue(DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, 3151e8d8bef9SDimitry Andric MVT::i32, PackedElt, SubI32), 3152e8d8bef9SDimitry Andric 0); 3153e8d8bef9SDimitry Andric 3154e8d8bef9SDimitry Andric if (Op.getSimpleValueType() == MVT::f32) { 3155e8d8bef9SDimitry Andric Result = DAG.getBitcast(MVT::f32, Result); 3156e8d8bef9SDimitry Andric } else { 3157e8d8bef9SDimitry Andric assert(Op.getSimpleValueType() == MVT::i32); 3158e8d8bef9SDimitry Andric } 3159e8d8bef9SDimitry Andric } 3160e8d8bef9SDimitry Andric return Result; 3161e8d8bef9SDimitry Andric } 3162e8d8bef9SDimitry Andric 3163e8d8bef9SDimitry Andric SDValue VETargetLowering::lowerINSERT_VECTOR_ELT(SDValue Op, 3164e8d8bef9SDimitry Andric SelectionDAG &DAG) const { 3165e8d8bef9SDimitry Andric assert(Op.getOpcode() == ISD::INSERT_VECTOR_ELT && "Unknown opcode!"); 3166e8d8bef9SDimitry Andric MVT VT = Op.getOperand(0).getSimpleValueType(); 3167e8d8bef9SDimitry Andric 3168e8d8bef9SDimitry Andric // Special treatment for packed V64 types. 3169e8d8bef9SDimitry Andric assert(VT == MVT::v512i32 || VT == MVT::v512f32); 3170fe6060f1SDimitry Andric (void)VT; 3171e8d8bef9SDimitry Andric // The v512i32 and v512f32 starts from upper bits (0..31). This "upper 3172e8d8bef9SDimitry Andric // bits" required `val << 32` from C implementation's point of view. 3173e8d8bef9SDimitry Andric // 3174e8d8bef9SDimitry Andric // Example of codes: 3175e8d8bef9SDimitry Andric // %packed_elt = extractelt %vr, (%idx >> 1) 3176e8d8bef9SDimitry Andric // %shift = ((%idx & 1) ^ 1) << 5 3177e8d8bef9SDimitry Andric // %packed_elt &= 0xffffffff00000000 >> shift 3178e8d8bef9SDimitry Andric // %packed_elt |= (zext %val) << shift 3179e8d8bef9SDimitry Andric // %vr = insertelt %vr, %packed_elt, (%idx >> 1) 3180e8d8bef9SDimitry Andric 3181e8d8bef9SDimitry Andric SDLoc DL(Op); 3182e8d8bef9SDimitry Andric SDValue Vec = Op.getOperand(0); 3183e8d8bef9SDimitry Andric SDValue Val = Op.getOperand(1); 3184e8d8bef9SDimitry Andric SDValue Idx = Op.getOperand(2); 3185e8d8bef9SDimitry Andric if (Idx.getSimpleValueType() == MVT::i32) 3186e8d8bef9SDimitry Andric Idx = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, Idx); 3187e8d8bef9SDimitry Andric if (Val.getSimpleValueType() == MVT::f32) 3188e8d8bef9SDimitry Andric Val = DAG.getBitcast(MVT::i32, Val); 3189e8d8bef9SDimitry Andric assert(Val.getSimpleValueType() == MVT::i32); 3190e8d8bef9SDimitry Andric Val = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, Val); 3191e8d8bef9SDimitry Andric 3192e8d8bef9SDimitry Andric SDValue Result = Op; 319304eeddc0SDimitry Andric if (false /* Idx->isConstant()*/) { 3194e8d8bef9SDimitry Andric // TODO: optimized implementation using constant values 3195e8d8bef9SDimitry Andric } else { 3196e8d8bef9SDimitry Andric SDValue Const1 = DAG.getConstant(1, DL, MVT::i64); 3197e8d8bef9SDimitry Andric SDValue HalfIdx = DAG.getNode(ISD::SRL, DL, MVT::i64, {Idx, Const1}); 3198e8d8bef9SDimitry Andric SDValue PackedElt = 3199e8d8bef9SDimitry Andric SDValue(DAG.getMachineNode(VE::LVSvr, DL, MVT::i64, {Vec, HalfIdx}), 0); 3200e8d8bef9SDimitry Andric SDValue AndIdx = DAG.getNode(ISD::AND, DL, MVT::i64, {Idx, Const1}); 3201e8d8bef9SDimitry Andric SDValue Shift = DAG.getNode(ISD::XOR, DL, MVT::i64, {AndIdx, Const1}); 3202e8d8bef9SDimitry Andric SDValue Const5 = DAG.getConstant(5, DL, MVT::i64); 3203e8d8bef9SDimitry Andric Shift = DAG.getNode(ISD::SHL, DL, MVT::i64, {Shift, Const5}); 3204e8d8bef9SDimitry Andric SDValue Mask = DAG.getConstant(0xFFFFFFFF00000000L, DL, MVT::i64); 3205e8d8bef9SDimitry Andric Mask = DAG.getNode(ISD::SRL, DL, MVT::i64, {Mask, Shift}); 3206e8d8bef9SDimitry Andric PackedElt = DAG.getNode(ISD::AND, DL, MVT::i64, {PackedElt, Mask}); 3207e8d8bef9SDimitry Andric Val = DAG.getNode(ISD::SHL, DL, MVT::i64, {Val, Shift}); 3208e8d8bef9SDimitry Andric PackedElt = DAG.getNode(ISD::OR, DL, MVT::i64, {PackedElt, Val}); 3209e8d8bef9SDimitry Andric Result = 3210e8d8bef9SDimitry Andric SDValue(DAG.getMachineNode(VE::LSVrr_v, DL, Vec.getSimpleValueType(), 3211e8d8bef9SDimitry Andric {HalfIdx, PackedElt, Vec}), 3212e8d8bef9SDimitry Andric 0); 3213e8d8bef9SDimitry Andric } 3214e8d8bef9SDimitry Andric return Result; 3215e8d8bef9SDimitry Andric } 3216