xref: /freebsd-src/contrib/llvm-project/llvm/lib/IR/VectorBuilder.cpp (revision 52418fc2be8efa5172b90a3a9e617017173612c4)
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