xref: /freebsd-src/contrib/llvm-project/llvm/lib/IR/VectorBuilder.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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() {
35*06c3fb27SDimitry 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");
6081ad6265SDimitry Andric 
6181ad6265SDimitry Andric   auto MaskPosOpt = VPIntrinsic::getMaskParamPos(VPID);
6281ad6265SDimitry Andric   auto VLenPosOpt = VPIntrinsic::getVectorLengthParamPos(VPID);
6381ad6265SDimitry Andric   size_t NumInstParams = InstOpArray.size();
6481ad6265SDimitry Andric   size_t NumVPParams =
6581ad6265SDimitry Andric       NumInstParams + MaskPosOpt.has_value() + VLenPosOpt.has_value();
6681ad6265SDimitry Andric 
6781ad6265SDimitry Andric   SmallVector<Value *, 6> IntrinParams;
6881ad6265SDimitry Andric 
6981ad6265SDimitry Andric   // Whether the mask and vlen parameter are at the end of the parameter list.
7081ad6265SDimitry Andric   bool TrailingMaskAndVLen =
7181ad6265SDimitry Andric       std::min<size_t>(MaskPosOpt.value_or(NumInstParams),
7281ad6265SDimitry Andric                        VLenPosOpt.value_or(NumInstParams)) >= NumInstParams;
7381ad6265SDimitry Andric 
7481ad6265SDimitry Andric   if (TrailingMaskAndVLen) {
7581ad6265SDimitry Andric     // Fast path for trailing mask, vector length.
7681ad6265SDimitry Andric     IntrinParams.append(InstOpArray.begin(), InstOpArray.end());
7781ad6265SDimitry Andric     IntrinParams.resize(NumVPParams);
7881ad6265SDimitry Andric   } else {
7981ad6265SDimitry Andric     IntrinParams.resize(NumVPParams);
8081ad6265SDimitry Andric     // Insert mask and evl operands in between the instruction operands.
8181ad6265SDimitry Andric     for (size_t VPParamIdx = 0, ParamIdx = 0; VPParamIdx < NumVPParams;
8281ad6265SDimitry Andric          ++VPParamIdx) {
8381ad6265SDimitry Andric       if ((MaskPosOpt && MaskPosOpt.value_or(NumVPParams) == VPParamIdx) ||
8481ad6265SDimitry Andric           (VLenPosOpt && VLenPosOpt.value_or(NumVPParams) == VPParamIdx))
8581ad6265SDimitry Andric         continue;
8681ad6265SDimitry Andric       assert(ParamIdx < NumInstParams);
8781ad6265SDimitry Andric       IntrinParams[VPParamIdx] = InstOpArray[ParamIdx++];
8881ad6265SDimitry Andric     }
8981ad6265SDimitry Andric   }
9081ad6265SDimitry Andric 
9181ad6265SDimitry Andric   if (MaskPosOpt)
9281ad6265SDimitry Andric     IntrinParams[*MaskPosOpt] = &requestMask();
9381ad6265SDimitry Andric   if (VLenPosOpt)
9481ad6265SDimitry Andric     IntrinParams[*VLenPosOpt] = &requestEVL();
9581ad6265SDimitry Andric 
9681ad6265SDimitry Andric   auto *VPDecl = VPIntrinsic::getDeclarationForParams(&getModule(), VPID,
9781ad6265SDimitry Andric                                                       ReturnTy, IntrinParams);
9881ad6265SDimitry Andric   return Builder.CreateCall(VPDecl, IntrinParams, Name);
9981ad6265SDimitry Andric }
10081ad6265SDimitry Andric 
10181ad6265SDimitry Andric } // namespace llvm
102