Skip to content

Commit 5f62156

Browse files
author
Simon Moll
committed
[VP] Introducing VectorBuilder, the VP intrinsic builder
VectorBuilder wraps around an IRBuilder and VectorBuilder::createVectorInstructions emits VP intrinsics as if they were regular instructions. Reviewed By: craig.topper Differential Revision: https://reviews.llvm.org/D105283
1 parent a9b03d9 commit 5f62156

File tree

6 files changed

+485
-0
lines changed

6 files changed

+485
-0
lines changed

llvm/include/llvm/IR/VectorBuilder.h

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//===- llvm/VectorBuilder.h - Builder for VP Intrinsics ---------*- C++ -*-===//
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 defines the VectorBuilder class, which is used as a convenient way
10+
// to create VP intrinsics as if they were LLVM instructions with a consistent
11+
// and simplified interface.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_IR_VECTORBUILDER_H
16+
#define LLVM_IR_VECTORBUILDER_H
17+
18+
#include <llvm/IR/IRBuilder.h>
19+
#include <llvm/IR/InstrTypes.h>
20+
#include <llvm/IR/Instruction.h>
21+
#include <llvm/IR/Value.h>
22+
23+
namespace llvm {
24+
25+
class VectorBuilder {
26+
public:
27+
enum class Behavior {
28+
// Abort if the requested VP intrinsic could not be created.
29+
// This is useful for strict consistency.
30+
ReportAndAbort = 0,
31+
32+
// Return a default-initialized value if the requested VP intrinsic could
33+
// not be created.
34+
// This is useful for a defensive fallback to non-VP code.
35+
SilentlyReturnNone = 1,
36+
};
37+
38+
private:
39+
IRBuilder<> &Builder;
40+
Behavior ErrorHandling;
41+
42+
// Explicit mask parameter.
43+
Value *Mask;
44+
// Explicit vector length parameter.
45+
Value *ExplicitVectorLength;
46+
// Compile-time vector length.
47+
ElementCount StaticVectorLength;
48+
49+
// Get mask/evl value handles for the current configuration.
50+
Value &requestMask();
51+
Value &requestEVL();
52+
53+
void handleError(const char *ErrorMsg) const;
54+
template <typename RetType>
55+
RetType returnWithError(const char *ErrorMsg) const {
56+
handleError(ErrorMsg);
57+
return RetType();
58+
}
59+
60+
public:
61+
VectorBuilder(IRBuilder<> &Builder,
62+
Behavior ErrorHandling = Behavior::ReportAndAbort)
63+
: Builder(Builder), ErrorHandling(ErrorHandling), Mask(nullptr),
64+
ExplicitVectorLength(nullptr),
65+
StaticVectorLength(ElementCount::getFixed(0)) {}
66+
67+
Module &getModule() const;
68+
LLVMContext &getContext() const { return Builder.getContext(); }
69+
70+
// All-true mask for the currently configured explicit vector length.
71+
Value *getAllTrueMask();
72+
73+
VectorBuilder &setMask(Value *NewMask) {
74+
Mask = NewMask;
75+
return *this;
76+
}
77+
VectorBuilder &setEVL(Value *NewExplicitVectorLength) {
78+
ExplicitVectorLength = NewExplicitVectorLength;
79+
return *this;
80+
}
81+
VectorBuilder &setStaticVL(unsigned NewFixedVL) {
82+
StaticVectorLength = ElementCount::getFixed(NewFixedVL);
83+
return *this;
84+
}
85+
// TODO: setStaticVL(ElementCount) for scalable types.
86+
87+
// Emit a VP intrinsic call that mimics a regular instruction.
88+
// This operation behaves according to the VectorBuilderBehavior.
89+
// \p Opcode The functional instruction opcode of the emitted intrinsic.
90+
// \p ReturnTy The return type of the operation.
91+
// \p VecOpArray The operand list.
92+
Value *createVectorInstruction(unsigned Opcode, Type *ReturnTy,
93+
ArrayRef<Value *> VecOpArray,
94+
const Twine &Name = Twine());
95+
};
96+
97+
} // namespace llvm
98+
99+
#endif // LLVM_IR_VECTORBUILDER_H

llvm/include/llvm/module.modulemap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ module LLVM_intrinsic_gen {
254254
module IR_InstrTypes { header "IR/InstrTypes.h" export * }
255255
module IR_Instructions { header "IR/Instructions.h" export * }
256256
module IR_TypeFinder { header "IR/TypeFinder.h" export * }
257+
module IR_VectorBuilder { header "IR/VectorBuilder.h" export * }
257258

258259

259260
// Intrinsics.h

llvm/lib/IR/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ add_llvm_component_library(LLVMCore
6161
User.cpp
6262
Value.cpp
6363
ValueSymbolTable.cpp
64+
VectorBuilder.cpp
6465
Verifier.cpp
6566

6667
ADDITIONAL_HEADER_DIRS

llvm/lib/IR/VectorBuilder.cpp

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

llvm/unittests/IR/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ add_llvm_unittest(IRTests
4141
ValueHandleTest.cpp
4242
ValueMapTest.cpp
4343
ValueTest.cpp
44+
VectorBuilderTest.cpp
4445
VectorTypesTest.cpp
4546
VerifierTest.cpp
4647
VPIntrinsicTest.cpp

0 commit comments

Comments
 (0)