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/Intrinsics.h>
19 #include <llvm/IR/VectorBuilder.h>
20 
21 namespace llvm {
22 
23 void VectorBuilder::handleError(const char *ErrorMsg) const {
24   if (Behavior == Behavior::SilentlyReturnNone)
25     return;
26   report_fatal_error(ErrorMsg);
27 }
28 
29 Module &VectorBuilder::getModule() const {
30   return *Builder.GetInsertBlock()->getModule();
31 }
32 
33 Value *VectorBuilder::getAllTrueMask() {
34   auto *BoolTy = Builder.getInt1Ty();
35   auto *MaskTy = VectorType::get(BoolTy, StaticVectorLength);
36   return ConstantInt::getAllOnesValue(MaskTy);
37 }
38 
39 Value &VectorBuilder::requestMask() {
40   if (Mask)
41     return *Mask;
42 
43   return *getAllTrueMask();
44 }
45 
46 Value &VectorBuilder::requestEVL() {
47   if (ExplicitVectorLength)
48     return *ExplicitVectorLength;
49 
50   assert(!StaticVectorLength.isScalable() && "TODO vscale lowering");
51   auto *IntTy = Builder.getInt32Ty();
52   return *ConstantInt::get(IntTy, StaticVectorLength.getFixedValue());
53 }
54 
55 Value *VectorBuilder::createVectorInstruction(unsigned Opcode, Type *ReturnTy,
56                                               ArrayRef<Value *> InstOpArray,
57                                               const Twine &Name) {
58   auto VPID = VPIntrinsic::getForOpcode(Opcode);
59   if (VPID == Intrinsic::not_intrinsic)
60     return returnWithError<Value *>("No VPIntrinsic for this opcode");
61 
62   auto MaskPosOpt = VPIntrinsic::getMaskParamPos(VPID);
63   auto VLenPosOpt = VPIntrinsic::getVectorLengthParamPos(VPID);
64   size_t NumInstParams = InstOpArray.size();
65   size_t NumVPParams =
66       NumInstParams + MaskPosOpt.hasValue() + VLenPosOpt.hasValue();
67 
68   SmallVector<Value *, 6> IntrinParams;
69 
70   // Whether the mask and vlen parameter are at the end of the parameter list.
71   bool TrailingMaskAndVLen =
72       std::min<size_t>(MaskPosOpt.getValueOr(NumInstParams),
73                        VLenPosOpt.getValueOr(NumInstParams)) >= NumInstParams;
74 
75   if (TrailingMaskAndVLen) {
76     // Fast path for trailing mask, vector length.
77     IntrinParams.append(InstOpArray.begin(), InstOpArray.end());
78     IntrinParams.resize(NumVPParams);
79   } else {
80     IntrinParams.resize(NumVPParams);
81     // Insert mask and evl operands in between the instruction operands.
82     for (size_t VPParamIdx = 0, ParamIdx = 0; VPParamIdx < NumVPParams;
83          ++VPParamIdx) {
84       if ((MaskPosOpt && MaskPosOpt.getValueOr(NumVPParams) == VPParamIdx) ||
85           (VLenPosOpt && VLenPosOpt.getValueOr(NumVPParams) == VPParamIdx))
86         continue;
87       assert(ParamIdx < NumInstParams);
88       IntrinParams[VPParamIdx] = InstOpArray[ParamIdx++];
89     }
90   }
91 
92   if (MaskPosOpt.hasValue())
93     IntrinParams[*MaskPosOpt] = &requestMask();
94   if (VLenPosOpt.hasValue())
95     IntrinParams[*VLenPosOpt] = &requestEVL();
96 
97   auto *VPDecl = VPIntrinsic::getDeclarationForParams(&getModule(), VPID,
98                                                       ReturnTy, IntrinParams);
99   return Builder.CreateCall(VPDecl, IntrinParams, Name);
100 }
101 
102 } // namespace llvm
103