| //===- 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 |