1 //===- VectorBuilder.cpp - Builder for VP Intrinsics ----------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the VectorBuilder class, which is used as a convenient 10 // way to create VP intrinsics as if they were LLVM instructions with a 11 // consistent and simplified interface. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include <llvm/ADT/SmallVector.h> 16 #include <llvm/IR/FPEnv.h> 17 #include <llvm/IR/Instructions.h> 18 #include <llvm/IR/IntrinsicInst.h> 19 #include <llvm/IR/Intrinsics.h> 20 #include <llvm/IR/VectorBuilder.h> 21 22 namespace llvm { 23 24 void VectorBuilder::handleError(const char *ErrorMsg) const { 25 if (ErrorHandling == Behavior::SilentlyReturnNone) 26 return; 27 report_fatal_error(ErrorMsg); 28 } 29 30 Module &VectorBuilder::getModule() const { 31 return *Builder.GetInsertBlock()->getModule(); 32 } 33 34 Value *VectorBuilder::getAllTrueMask() { 35 return Builder.getAllOnesMask(StaticVectorLength); 36 } 37 38 Value &VectorBuilder::requestMask() { 39 if (Mask) 40 return *Mask; 41 42 return *getAllTrueMask(); 43 } 44 45 Value &VectorBuilder::requestEVL() { 46 if (ExplicitVectorLength) 47 return *ExplicitVectorLength; 48 49 assert(!StaticVectorLength.isScalable() && "TODO vscale lowering"); 50 auto *IntTy = Builder.getInt32Ty(); 51 return *ConstantInt::get(IntTy, StaticVectorLength.getFixedValue()); 52 } 53 54 Value *VectorBuilder::createVectorInstruction(unsigned Opcode, Type *ReturnTy, 55 ArrayRef<Value *> InstOpArray, 56 const Twine &Name) { 57 auto VPID = VPIntrinsic::getForOpcode(Opcode); 58 if (VPID == Intrinsic::not_intrinsic) 59 return returnWithError<Value *>("No VPIntrinsic for this opcode"); 60 return createVectorInstructionImpl(VPID, ReturnTy, InstOpArray, Name); 61 } 62 63 Value *VectorBuilder::createSimpleTargetReduction(Intrinsic::ID RdxID, 64 Type *ValTy, 65 ArrayRef<Value *> InstOpArray, 66 const Twine &Name) { 67 auto VPID = VPIntrinsic::getForIntrinsic(RdxID); 68 assert(VPReductionIntrinsic::isVPReduction(VPID) && 69 "No VPIntrinsic for this reduction"); 70 return createVectorInstructionImpl(VPID, ValTy, InstOpArray, Name); 71 } 72 73 Value *VectorBuilder::createVectorInstructionImpl(Intrinsic::ID VPID, 74 Type *ReturnTy, 75 ArrayRef<Value *> InstOpArray, 76 const Twine &Name) { 77 auto MaskPosOpt = VPIntrinsic::getMaskParamPos(VPID); 78 auto VLenPosOpt = VPIntrinsic::getVectorLengthParamPos(VPID); 79 size_t NumInstParams = InstOpArray.size(); 80 size_t NumVPParams = 81 NumInstParams + MaskPosOpt.has_value() + VLenPosOpt.has_value(); 82 83 SmallVector<Value *, 6> IntrinParams; 84 85 // Whether the mask and vlen parameter are at the end of the parameter list. 86 bool TrailingMaskAndVLen = 87 std::min<size_t>(MaskPosOpt.value_or(NumInstParams), 88 VLenPosOpt.value_or(NumInstParams)) >= NumInstParams; 89 90 if (TrailingMaskAndVLen) { 91 // Fast path for trailing mask, vector length. 92 IntrinParams.append(InstOpArray.begin(), InstOpArray.end()); 93 IntrinParams.resize(NumVPParams); 94 } else { 95 IntrinParams.resize(NumVPParams); 96 // Insert mask and evl operands in between the instruction operands. 97 for (size_t VPParamIdx = 0, ParamIdx = 0; VPParamIdx < NumVPParams; 98 ++VPParamIdx) { 99 if ((MaskPosOpt && MaskPosOpt.value_or(NumVPParams) == VPParamIdx) || 100 (VLenPosOpt && VLenPosOpt.value_or(NumVPParams) == VPParamIdx)) 101 continue; 102 assert(ParamIdx < NumInstParams); 103 IntrinParams[VPParamIdx] = InstOpArray[ParamIdx++]; 104 } 105 } 106 107 if (MaskPosOpt) 108 IntrinParams[*MaskPosOpt] = &requestMask(); 109 if (VLenPosOpt) 110 IntrinParams[*VLenPosOpt] = &requestEVL(); 111 112 auto *VPDecl = VPIntrinsic::getDeclarationForParams(&getModule(), VPID, 113 ReturnTy, IntrinParams); 114 return Builder.CreateCall(VPDecl, IntrinParams, Name); 115 } 116 117 } // namespace llvm 118