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 61 auto MaskPosOpt = VPIntrinsic::getMaskParamPos(VPID); 62 auto VLenPosOpt = VPIntrinsic::getVectorLengthParamPos(VPID); 63 size_t NumInstParams = InstOpArray.size(); 64 size_t NumVPParams = 65 NumInstParams + MaskPosOpt.has_value() + VLenPosOpt.has_value(); 66 67 SmallVector<Value *, 6> IntrinParams; 68 69 // Whether the mask and vlen parameter are at the end of the parameter list. 70 bool TrailingMaskAndVLen = 71 std::min<size_t>(MaskPosOpt.value_or(NumInstParams), 72 VLenPosOpt.value_or(NumInstParams)) >= NumInstParams; 73 74 if (TrailingMaskAndVLen) { 75 // Fast path for trailing mask, vector length. 76 IntrinParams.append(InstOpArray.begin(), InstOpArray.end()); 77 IntrinParams.resize(NumVPParams); 78 } else { 79 IntrinParams.resize(NumVPParams); 80 // Insert mask and evl operands in between the instruction operands. 81 for (size_t VPParamIdx = 0, ParamIdx = 0; VPParamIdx < NumVPParams; 82 ++VPParamIdx) { 83 if ((MaskPosOpt && MaskPosOpt.value_or(NumVPParams) == VPParamIdx) || 84 (VLenPosOpt && VLenPosOpt.value_or(NumVPParams) == VPParamIdx)) 85 continue; 86 assert(ParamIdx < NumInstParams); 87 IntrinParams[VPParamIdx] = InstOpArray[ParamIdx++]; 88 } 89 } 90 91 if (MaskPosOpt) 92 IntrinParams[*MaskPosOpt] = &requestMask(); 93 if (VLenPosOpt) 94 IntrinParams[*VLenPosOpt] = &requestEVL(); 95 96 auto *VPDecl = VPIntrinsic::getDeclarationForParams(&getModule(), VPID, 97 ReturnTy, IntrinParams); 98 return Builder.CreateCall(VPDecl, IntrinParams, Name); 99 } 100 101 } // namespace llvm 102