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