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
22namespace llvm {
23
24void VectorBuilder::handleError(const char *ErrorMsg) const {
25  if (ErrorHandling == Behavior::SilentlyReturnNone)
26    return;
27  report_fatal_error(ErrorMsg);
28}
29
30Module &VectorBuilder::getModule() const {
31  return *Builder.GetInsertBlock()->getModule();
32}
33
34Value *VectorBuilder::getAllTrueMask() {
35  return Builder.getAllOnesMask(StaticVectorLength);
36}
37
38Value &VectorBuilder::requestMask() {
39  if (Mask)
40    return *Mask;
41
42  return *getAllTrueMask();
43}
44
45Value &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
54Value *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
61  auto MaskPosOpt = VPIntrinsic::getMaskParamPos(VPID);
62  auto VLenPosOpt = VPIntrinsic::getVectorLengthParamPos(VPID);
63  size_t NumInstParams = InstOpArray.size();
64  size_t NumVPParams =
65      NumInstParams + MaskPosOpt.has_value() + VLenPosOpt.has_value();
66
67  SmallVector<Value *, 6> IntrinParams;
68
69  // Whether the mask and vlen parameter are at the end of the parameter list.
70  bool TrailingMaskAndVLen =
71      std::min<size_t>(MaskPosOpt.value_or(NumInstParams),
72                       VLenPosOpt.value_or(NumInstParams)) >= NumInstParams;
73
74  if (TrailingMaskAndVLen) {
75    // Fast path for trailing mask, vector length.
76    IntrinParams.append(InstOpArray.begin(), InstOpArray.end());
77    IntrinParams.resize(NumVPParams);
78  } else {
79    IntrinParams.resize(NumVPParams);
80    // Insert mask and evl operands in between the instruction operands.
81    for (size_t VPParamIdx = 0, ParamIdx = 0; VPParamIdx < NumVPParams;
82         ++VPParamIdx) {
83      if ((MaskPosOpt && MaskPosOpt.value_or(NumVPParams) == VPParamIdx) ||
84          (VLenPosOpt && VLenPosOpt.value_or(NumVPParams) == VPParamIdx))
85        continue;
86      assert(ParamIdx < NumInstParams);
87      IntrinParams[VPParamIdx] = InstOpArray[ParamIdx++];
88    }
89  }
90
91  if (MaskPosOpt)
92    IntrinParams[*MaskPosOpt] = &requestMask();
93  if (VLenPosOpt)
94    IntrinParams[*VLenPosOpt] = &requestEVL();
95
96  auto *VPDecl = VPIntrinsic::getDeclarationForParams(&getModule(), VPID,
97                                                      ReturnTy, IntrinParams);
98  return Builder.CreateCall(VPDecl, IntrinParams, Name);
99}
100
101} // namespace llvm
102