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