diff options
Diffstat (limited to 'llvm/lib/IR/VectorBuilder.cpp')
-rw-r--r-- | llvm/lib/IR/VectorBuilder.cpp | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/llvm/lib/IR/VectorBuilder.cpp b/llvm/lib/IR/VectorBuilder.cpp new file mode 100644 index 000000000000..e7be7a98a593 --- /dev/null +++ b/llvm/lib/IR/VectorBuilder.cpp @@ -0,0 +1,103 @@ +//===- VectorBuilder.cpp - Builder for VP Intrinsics ----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the VectorBuilder class, which is used as a convenient +// way to create VP intrinsics as if they were LLVM instructions with a +// consistent and simplified interface. +// +//===----------------------------------------------------------------------===// + +#include <llvm/ADT/SmallVector.h> +#include <llvm/IR/FPEnv.h> +#include <llvm/IR/Instructions.h> +#include <llvm/IR/IntrinsicInst.h> +#include <llvm/IR/Intrinsics.h> +#include <llvm/IR/VectorBuilder.h> + +namespace llvm { + +void VectorBuilder::handleError(const char *ErrorMsg) const { + if (ErrorHandling == Behavior::SilentlyReturnNone) + return; + report_fatal_error(ErrorMsg); +} + +Module &VectorBuilder::getModule() const { + return *Builder.GetInsertBlock()->getModule(); +} + +Value *VectorBuilder::getAllTrueMask() { + auto *BoolTy = Builder.getInt1Ty(); + auto *MaskTy = VectorType::get(BoolTy, StaticVectorLength); + return ConstantInt::getAllOnesValue(MaskTy); +} + +Value &VectorBuilder::requestMask() { + if (Mask) + return *Mask; + + return *getAllTrueMask(); +} + +Value &VectorBuilder::requestEVL() { + if (ExplicitVectorLength) + return *ExplicitVectorLength; + + assert(!StaticVectorLength.isScalable() && "TODO vscale lowering"); + auto *IntTy = Builder.getInt32Ty(); + return *ConstantInt::get(IntTy, StaticVectorLength.getFixedValue()); +} + +Value *VectorBuilder::createVectorInstruction(unsigned Opcode, Type *ReturnTy, + ArrayRef<Value *> InstOpArray, + const Twine &Name) { + auto VPID = VPIntrinsic::getForOpcode(Opcode); + if (VPID == Intrinsic::not_intrinsic) + return returnWithError<Value *>("No VPIntrinsic for this opcode"); + + auto MaskPosOpt = VPIntrinsic::getMaskParamPos(VPID); + auto VLenPosOpt = VPIntrinsic::getVectorLengthParamPos(VPID); + size_t NumInstParams = InstOpArray.size(); + size_t NumVPParams = + NumInstParams + MaskPosOpt.has_value() + VLenPosOpt.has_value(); + + SmallVector<Value *, 6> IntrinParams; + + // Whether the mask and vlen parameter are at the end of the parameter list. + bool TrailingMaskAndVLen = + std::min<size_t>(MaskPosOpt.value_or(NumInstParams), + VLenPosOpt.value_or(NumInstParams)) >= NumInstParams; + + if (TrailingMaskAndVLen) { + // Fast path for trailing mask, vector length. + IntrinParams.append(InstOpArray.begin(), InstOpArray.end()); + IntrinParams.resize(NumVPParams); + } else { + IntrinParams.resize(NumVPParams); + // Insert mask and evl operands in between the instruction operands. + for (size_t VPParamIdx = 0, ParamIdx = 0; VPParamIdx < NumVPParams; + ++VPParamIdx) { + if ((MaskPosOpt && MaskPosOpt.value_or(NumVPParams) == VPParamIdx) || + (VLenPosOpt && VLenPosOpt.value_or(NumVPParams) == VPParamIdx)) + continue; + assert(ParamIdx < NumInstParams); + IntrinParams[VPParamIdx] = InstOpArray[ParamIdx++]; + } + } + + if (MaskPosOpt) + IntrinParams[*MaskPosOpt] = &requestMask(); + if (VLenPosOpt) + IntrinParams[*VLenPosOpt] = &requestEVL(); + + auto *VPDecl = VPIntrinsic::getDeclarationForParams(&getModule(), VPID, + ReturnTy, IntrinParams); + return Builder.CreateCall(VPDecl, IntrinParams, Name); +} + +} // namespace llvm |