xref: /freebsd/contrib/llvm-project/llvm/lib/IR/VectorBuilder.cpp (revision 52418fc2be8efa5172b90a3a9e617017173612c4)
1  //===- VectorBuilder.cpp - Builder for VP Intrinsics ----------------------===//
2  //
3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4  // See https://llvm.org/LICENSE.txt for license information.
5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6  //
7  //===----------------------------------------------------------------------===//
8  //
9  // This file implements the VectorBuilder class, which is used as a convenient
10  // way to create VP intrinsics as if they were LLVM instructions with a
11  // consistent and simplified interface.
12  //
13  //===----------------------------------------------------------------------===//
14  
15  #include <llvm/ADT/SmallVector.h>
16  #include <llvm/IR/FPEnv.h>
17  #include <llvm/IR/Instructions.h>
18  #include <llvm/IR/IntrinsicInst.h>
19  #include <llvm/IR/Intrinsics.h>
20  #include <llvm/IR/VectorBuilder.h>
21  
22  namespace llvm {
23  
handleError(const char * ErrorMsg) const24  void VectorBuilder::handleError(const char *ErrorMsg) const {
25    if (ErrorHandling == Behavior::SilentlyReturnNone)
26      return;
27    report_fatal_error(ErrorMsg);
28  }
29  
getModule() const30  Module &VectorBuilder::getModule() const {
31    return *Builder.GetInsertBlock()->getModule();
32  }
33  
getAllTrueMask()34  Value *VectorBuilder::getAllTrueMask() {
35    return Builder.getAllOnesMask(StaticVectorLength);
36  }
37  
requestMask()38  Value &VectorBuilder::requestMask() {
39    if (Mask)
40      return *Mask;
41  
42    return *getAllTrueMask();
43  }
44  
requestEVL()45  Value &VectorBuilder::requestEVL() {
46    if (ExplicitVectorLength)
47      return *ExplicitVectorLength;
48  
49    assert(!StaticVectorLength.isScalable() && "TODO vscale lowering");
50    auto *IntTy = Builder.getInt32Ty();
51    return *ConstantInt::get(IntTy, StaticVectorLength.getFixedValue());
52  }
53  
createVectorInstruction(unsigned Opcode,Type * ReturnTy,ArrayRef<Value * > InstOpArray,const Twine & Name)54  Value *VectorBuilder::createVectorInstruction(unsigned Opcode, Type *ReturnTy,
55                                                ArrayRef<Value *> InstOpArray,
56                                                const Twine &Name) {
57    auto VPID = VPIntrinsic::getForOpcode(Opcode);
58    if (VPID == Intrinsic::not_intrinsic)
59      return returnWithError<Value *>("No VPIntrinsic for this opcode");
60    return createVectorInstructionImpl(VPID, ReturnTy, InstOpArray, Name);
61  }
62  
createSimpleTargetReduction(Intrinsic::ID RdxID,Type * ValTy,ArrayRef<Value * > InstOpArray,const Twine & Name)63  Value *VectorBuilder::createSimpleTargetReduction(Intrinsic::ID RdxID,
64                                                    Type *ValTy,
65                                                    ArrayRef<Value *> InstOpArray,
66                                                    const Twine &Name) {
67    auto VPID = VPIntrinsic::getForIntrinsic(RdxID);
68    assert(VPReductionIntrinsic::isVPReduction(VPID) &&
69           "No VPIntrinsic for this reduction");
70    return createVectorInstructionImpl(VPID, ValTy, InstOpArray, Name);
71  }
72  
createVectorInstructionImpl(Intrinsic::ID VPID,Type * ReturnTy,ArrayRef<Value * > InstOpArray,const Twine & Name)73  Value *VectorBuilder::createVectorInstructionImpl(Intrinsic::ID VPID,
74                                                    Type *ReturnTy,
75                                                    ArrayRef<Value *> InstOpArray,
76                                                    const Twine &Name) {
77    auto MaskPosOpt = VPIntrinsic::getMaskParamPos(VPID);
78    auto VLenPosOpt = VPIntrinsic::getVectorLengthParamPos(VPID);
79    size_t NumInstParams = InstOpArray.size();
80    size_t NumVPParams =
81        NumInstParams + MaskPosOpt.has_value() + VLenPosOpt.has_value();
82  
83    SmallVector<Value *, 6> IntrinParams;
84  
85    // Whether the mask and vlen parameter are at the end of the parameter list.
86    bool TrailingMaskAndVLen =
87        std::min<size_t>(MaskPosOpt.value_or(NumInstParams),
88                         VLenPosOpt.value_or(NumInstParams)) >= NumInstParams;
89  
90    if (TrailingMaskAndVLen) {
91      // Fast path for trailing mask, vector length.
92      IntrinParams.append(InstOpArray.begin(), InstOpArray.end());
93      IntrinParams.resize(NumVPParams);
94    } else {
95      IntrinParams.resize(NumVPParams);
96      // Insert mask and evl operands in between the instruction operands.
97      for (size_t VPParamIdx = 0, ParamIdx = 0; VPParamIdx < NumVPParams;
98           ++VPParamIdx) {
99        if ((MaskPosOpt && MaskPosOpt.value_or(NumVPParams) == VPParamIdx) ||
100            (VLenPosOpt && VLenPosOpt.value_or(NumVPParams) == VPParamIdx))
101          continue;
102        assert(ParamIdx < NumInstParams);
103        IntrinParams[VPParamIdx] = InstOpArray[ParamIdx++];
104      }
105    }
106  
107    if (MaskPosOpt)
108      IntrinParams[*MaskPosOpt] = &requestMask();
109    if (VLenPosOpt)
110      IntrinParams[*VLenPosOpt] = &requestEVL();
111  
112    auto *VPDecl = VPIntrinsic::getDeclarationForParams(&getModule(), VPID,
113                                                        ReturnTy, IntrinParams);
114    return Builder.CreateCall(VPDecl, IntrinParams, Name);
115  }
116  
117  } // namespace llvm
118