181ad6265SDimitry Andric //===- VectorBuilder.cpp - Builder for VP Intrinsics ----------------------===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric // 981ad6265SDimitry Andric // This file implements the VectorBuilder class, which is used as a convenient 1081ad6265SDimitry Andric // way to create VP intrinsics as if they were LLVM instructions with a 1181ad6265SDimitry Andric // consistent and simplified interface. 1281ad6265SDimitry Andric // 1381ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1481ad6265SDimitry Andric 1581ad6265SDimitry Andric #include <llvm/ADT/SmallVector.h> 1681ad6265SDimitry Andric #include <llvm/IR/FPEnv.h> 1781ad6265SDimitry Andric #include <llvm/IR/Instructions.h> 1881ad6265SDimitry Andric #include <llvm/IR/IntrinsicInst.h> 1981ad6265SDimitry Andric #include <llvm/IR/Intrinsics.h> 2081ad6265SDimitry Andric #include <llvm/IR/VectorBuilder.h> 2181ad6265SDimitry Andric 2281ad6265SDimitry Andric namespace llvm { 2381ad6265SDimitry Andric 2481ad6265SDimitry Andric void VectorBuilder::handleError(const char *ErrorMsg) const { 2581ad6265SDimitry Andric if (ErrorHandling == Behavior::SilentlyReturnNone) 2681ad6265SDimitry Andric return; 2781ad6265SDimitry Andric report_fatal_error(ErrorMsg); 2881ad6265SDimitry Andric } 2981ad6265SDimitry Andric 3081ad6265SDimitry Andric Module &VectorBuilder::getModule() const { 3181ad6265SDimitry Andric return *Builder.GetInsertBlock()->getModule(); 3281ad6265SDimitry Andric } 3381ad6265SDimitry Andric 3481ad6265SDimitry Andric Value *VectorBuilder::getAllTrueMask() { 3506c3fb27SDimitry Andric return Builder.getAllOnesMask(StaticVectorLength); 3681ad6265SDimitry Andric } 3781ad6265SDimitry Andric 3881ad6265SDimitry Andric Value &VectorBuilder::requestMask() { 3981ad6265SDimitry Andric if (Mask) 4081ad6265SDimitry Andric return *Mask; 4181ad6265SDimitry Andric 4281ad6265SDimitry Andric return *getAllTrueMask(); 4381ad6265SDimitry Andric } 4481ad6265SDimitry Andric 4581ad6265SDimitry Andric Value &VectorBuilder::requestEVL() { 4681ad6265SDimitry Andric if (ExplicitVectorLength) 4781ad6265SDimitry Andric return *ExplicitVectorLength; 4881ad6265SDimitry Andric 4981ad6265SDimitry Andric assert(!StaticVectorLength.isScalable() && "TODO vscale lowering"); 5081ad6265SDimitry Andric auto *IntTy = Builder.getInt32Ty(); 5181ad6265SDimitry Andric return *ConstantInt::get(IntTy, StaticVectorLength.getFixedValue()); 5281ad6265SDimitry Andric } 5381ad6265SDimitry Andric 5481ad6265SDimitry Andric Value *VectorBuilder::createVectorInstruction(unsigned Opcode, Type *ReturnTy, 5581ad6265SDimitry Andric ArrayRef<Value *> InstOpArray, 5681ad6265SDimitry Andric const Twine &Name) { 5781ad6265SDimitry Andric auto VPID = VPIntrinsic::getForOpcode(Opcode); 5881ad6265SDimitry Andric if (VPID == Intrinsic::not_intrinsic) 5981ad6265SDimitry Andric return returnWithError<Value *>("No VPIntrinsic for this opcode"); 600fca6ea1SDimitry Andric return createVectorInstructionImpl(VPID, ReturnTy, InstOpArray, Name); 610fca6ea1SDimitry Andric } 6281ad6265SDimitry Andric 63*52418fc2SDimitry Andric Value *VectorBuilder::createSimpleTargetReduction(Intrinsic::ID RdxID, 64*52418fc2SDimitry Andric Type *ValTy, 650fca6ea1SDimitry Andric ArrayRef<Value *> InstOpArray, 660fca6ea1SDimitry Andric const Twine &Name) { 67*52418fc2SDimitry Andric auto VPID = VPIntrinsic::getForIntrinsic(RdxID); 68*52418fc2SDimitry Andric assert(VPReductionIntrinsic::isVPReduction(VPID) && 69*52418fc2SDimitry Andric "No VPIntrinsic for this reduction"); 700fca6ea1SDimitry Andric return createVectorInstructionImpl(VPID, ValTy, InstOpArray, Name); 710fca6ea1SDimitry Andric } 720fca6ea1SDimitry Andric 730fca6ea1SDimitry Andric Value *VectorBuilder::createVectorInstructionImpl(Intrinsic::ID VPID, 740fca6ea1SDimitry Andric Type *ReturnTy, 750fca6ea1SDimitry Andric ArrayRef<Value *> InstOpArray, 760fca6ea1SDimitry Andric const Twine &Name) { 7781ad6265SDimitry Andric auto MaskPosOpt = VPIntrinsic::getMaskParamPos(VPID); 7881ad6265SDimitry Andric auto VLenPosOpt = VPIntrinsic::getVectorLengthParamPos(VPID); 7981ad6265SDimitry Andric size_t NumInstParams = InstOpArray.size(); 8081ad6265SDimitry Andric size_t NumVPParams = 8181ad6265SDimitry Andric NumInstParams + MaskPosOpt.has_value() + VLenPosOpt.has_value(); 8281ad6265SDimitry Andric 8381ad6265SDimitry Andric SmallVector<Value *, 6> IntrinParams; 8481ad6265SDimitry Andric 8581ad6265SDimitry Andric // Whether the mask and vlen parameter are at the end of the parameter list. 8681ad6265SDimitry Andric bool TrailingMaskAndVLen = 8781ad6265SDimitry Andric std::min<size_t>(MaskPosOpt.value_or(NumInstParams), 8881ad6265SDimitry Andric VLenPosOpt.value_or(NumInstParams)) >= NumInstParams; 8981ad6265SDimitry Andric 9081ad6265SDimitry Andric if (TrailingMaskAndVLen) { 9181ad6265SDimitry Andric // Fast path for trailing mask, vector length. 9281ad6265SDimitry Andric IntrinParams.append(InstOpArray.begin(), InstOpArray.end()); 9381ad6265SDimitry Andric IntrinParams.resize(NumVPParams); 9481ad6265SDimitry Andric } else { 9581ad6265SDimitry Andric IntrinParams.resize(NumVPParams); 9681ad6265SDimitry Andric // Insert mask and evl operands in between the instruction operands. 9781ad6265SDimitry Andric for (size_t VPParamIdx = 0, ParamIdx = 0; VPParamIdx < NumVPParams; 9881ad6265SDimitry Andric ++VPParamIdx) { 9981ad6265SDimitry Andric if ((MaskPosOpt && MaskPosOpt.value_or(NumVPParams) == VPParamIdx) || 10081ad6265SDimitry Andric (VLenPosOpt && VLenPosOpt.value_or(NumVPParams) == VPParamIdx)) 10181ad6265SDimitry Andric continue; 10281ad6265SDimitry Andric assert(ParamIdx < NumInstParams); 10381ad6265SDimitry Andric IntrinParams[VPParamIdx] = InstOpArray[ParamIdx++]; 10481ad6265SDimitry Andric } 10581ad6265SDimitry Andric } 10681ad6265SDimitry Andric 10781ad6265SDimitry Andric if (MaskPosOpt) 10881ad6265SDimitry Andric IntrinParams[*MaskPosOpt] = &requestMask(); 10981ad6265SDimitry Andric if (VLenPosOpt) 11081ad6265SDimitry Andric IntrinParams[*VLenPosOpt] = &requestEVL(); 11181ad6265SDimitry Andric 11281ad6265SDimitry Andric auto *VPDecl = VPIntrinsic::getDeclarationForParams(&getModule(), VPID, 11381ad6265SDimitry Andric ReturnTy, IntrinParams); 11481ad6265SDimitry Andric return Builder.CreateCall(VPDecl, IntrinParams, Name); 11581ad6265SDimitry Andric } 11681ad6265SDimitry Andric 11781ad6265SDimitry Andric } // namespace llvm 118