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