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 auto *BoolTy = Builder.getInt1Ty(); 36 auto *MaskTy = VectorType::get(BoolTy, StaticVectorLength); 37 return ConstantInt::getAllOnesValue(MaskTy); 38 } 39 40 Value &VectorBuilder::requestMask() { 41 if (Mask) 42 return *Mask; 43 44 return *getAllTrueMask(); 45 } 46 47 Value &VectorBuilder::requestEVL() { 48 if (ExplicitVectorLength) 49 return *ExplicitVectorLength; 50 51 assert(!StaticVectorLength.isScalable() && "TODO vscale lowering"); 52 auto *IntTy = Builder.getInt32Ty(); 53 return *ConstantInt::get(IntTy, StaticVectorLength.getFixedValue()); 54 } 55 56 Value *VectorBuilder::createVectorInstruction(unsigned Opcode, Type *ReturnTy, 57 ArrayRef<Value *> InstOpArray, 58 const Twine &Name) { 59 auto VPID = VPIntrinsic::getForOpcode(Opcode); 60 if (VPID == Intrinsic::not_intrinsic) 61 return returnWithError<Value *>("No VPIntrinsic for this opcode"); 62 63 auto MaskPosOpt = VPIntrinsic::getMaskParamPos(VPID); 64 auto VLenPosOpt = VPIntrinsic::getVectorLengthParamPos(VPID); 65 size_t NumInstParams = InstOpArray.size(); 66 size_t NumVPParams = 67 NumInstParams + MaskPosOpt.has_value() + VLenPosOpt.has_value(); 68 69 SmallVector<Value *, 6> IntrinParams; 70 71 // Whether the mask and vlen parameter are at the end of the parameter list. 72 bool TrailingMaskAndVLen = 73 std::min<size_t>(MaskPosOpt.value_or(NumInstParams), 74 VLenPosOpt.value_or(NumInstParams)) >= NumInstParams; 75 76 if (TrailingMaskAndVLen) { 77 // Fast path for trailing mask, vector length. 78 IntrinParams.append(InstOpArray.begin(), InstOpArray.end()); 79 IntrinParams.resize(NumVPParams); 80 } else { 81 IntrinParams.resize(NumVPParams); 82 // Insert mask and evl operands in between the instruction operands. 83 for (size_t VPParamIdx = 0, ParamIdx = 0; VPParamIdx < NumVPParams; 84 ++VPParamIdx) { 85 if ((MaskPosOpt && MaskPosOpt.value_or(NumVPParams) == VPParamIdx) || 86 (VLenPosOpt && VLenPosOpt.value_or(NumVPParams) == VPParamIdx)) 87 continue; 88 assert(ParamIdx < NumInstParams); 89 IntrinParams[VPParamIdx] = InstOpArray[ParamIdx++]; 90 } 91 } 92 93 if (MaskPosOpt) 94 IntrinParams[*MaskPosOpt] = &requestMask(); 95 if (VLenPosOpt) 96 IntrinParams[*VLenPosOpt] = &requestEVL(); 97 98 auto *VPDecl = VPIntrinsic::getDeclarationForParams(&getModule(), VPID, 99 ReturnTy, IntrinParams); 100 return Builder.CreateCall(VPDecl, IntrinParams, Name); 101 } 102 103 } // namespace llvm 104