Skip to content

Commit

Permalink
[VP] Introducing VectorBuilder, the VP intrinsic builder
Browse files Browse the repository at this point in the history
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
  • Loading branch information
simoll committed Mar 7, 2022
1 parent a9b03d9 commit 5f62156
Show file tree
Hide file tree
Showing 6 changed files with 485 additions and 0 deletions.
99 changes: 99 additions & 0 deletions llvm/include/llvm/IR/VectorBuilder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//===- llvm/VectorBuilder.h - Builder for VP Intrinsics ---------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the VectorBuilder class, which is used as a convenient way
// to create VP intrinsics as if they were LLVM instructions with a consistent
// and simplified interface.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_IR_VECTORBUILDER_H
#define LLVM_IR_VECTORBUILDER_H

#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/InstrTypes.h>
#include <llvm/IR/Instruction.h>
#include <llvm/IR/Value.h>

namespace llvm {

class VectorBuilder {
public:
enum class Behavior {
// Abort if the requested VP intrinsic could not be created.
// This is useful for strict consistency.
ReportAndAbort = 0,

// Return a default-initialized value if the requested VP intrinsic could
// not be created.
// This is useful for a defensive fallback to non-VP code.
SilentlyReturnNone = 1,
};

private:
IRBuilder<> &Builder;
Behavior ErrorHandling;

// Explicit mask parameter.
Value *Mask;
// Explicit vector length parameter.
Value *ExplicitVectorLength;
// Compile-time vector length.
ElementCount StaticVectorLength;

// Get mask/evl value handles for the current configuration.
Value &requestMask();
Value &requestEVL();

void handleError(const char *ErrorMsg) const;
template <typename RetType>
RetType returnWithError(const char *ErrorMsg) const {
handleError(ErrorMsg);
return RetType();
}

public:
VectorBuilder(IRBuilder<> &Builder,
Behavior ErrorHandling = Behavior::ReportAndAbort)
: Builder(Builder), ErrorHandling(ErrorHandling), Mask(nullptr),
ExplicitVectorLength(nullptr),
StaticVectorLength(ElementCount::getFixed(0)) {}

Module &getModule() const;
LLVMContext &getContext() const { return Builder.getContext(); }

// All-true mask for the currently configured explicit vector length.
Value *getAllTrueMask();

VectorBuilder &setMask(Value *NewMask) {
Mask = NewMask;
return *this;
}
VectorBuilder &setEVL(Value *NewExplicitVectorLength) {
ExplicitVectorLength = NewExplicitVectorLength;
return *this;
}
VectorBuilder &setStaticVL(unsigned NewFixedVL) {
StaticVectorLength = ElementCount::getFixed(NewFixedVL);
return *this;
}
// TODO: setStaticVL(ElementCount) for scalable types.

// Emit a VP intrinsic call that mimics a regular instruction.
// This operation behaves according to the VectorBuilderBehavior.
// \p Opcode The functional instruction opcode of the emitted intrinsic.
// \p ReturnTy The return type of the operation.
// \p VecOpArray The operand list.
Value *createVectorInstruction(unsigned Opcode, Type *ReturnTy,
ArrayRef<Value *> VecOpArray,
const Twine &Name = Twine());
};

} // namespace llvm

#endif // LLVM_IR_VECTORBUILDER_H
1 change: 1 addition & 0 deletions llvm/include/llvm/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ module LLVM_intrinsic_gen {
module IR_InstrTypes { header "IR/InstrTypes.h" export * }
module IR_Instructions { header "IR/Instructions.h" export * }
module IR_TypeFinder { header "IR/TypeFinder.h" export * }
module IR_VectorBuilder { header "IR/VectorBuilder.h" export * }


// Intrinsics.h
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/IR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ add_llvm_component_library(LLVMCore
User.cpp
Value.cpp
ValueSymbolTable.cpp
VectorBuilder.cpp
Verifier.cpp

ADDITIONAL_HEADER_DIRS
Expand Down
103 changes: 103 additions & 0 deletions llvm/lib/IR/VectorBuilder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//===- VectorBuilder.cpp - Builder for VP Intrinsics ----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the VectorBuilder class, which is used as a convenient
// way to create VP intrinsics as if they were LLVM instructions with a
// consistent and simplified interface.
//
//===----------------------------------------------------------------------===//

#include <llvm/ADT/SmallVector.h>
#include <llvm/IR/FPEnv.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/IntrinsicInst.h>
#include <llvm/IR/Intrinsics.h>
#include <llvm/IR/VectorBuilder.h>

namespace llvm {

void VectorBuilder::handleError(const char *ErrorMsg) const {
if (ErrorHandling == Behavior::SilentlyReturnNone)
return;
report_fatal_error(ErrorMsg);
}

Module &VectorBuilder::getModule() const {
return *Builder.GetInsertBlock()->getModule();
}

Value *VectorBuilder::getAllTrueMask() {
auto *BoolTy = Builder.getInt1Ty();
auto *MaskTy = VectorType::get(BoolTy, StaticVectorLength);
return ConstantInt::getAllOnesValue(MaskTy);
}

Value &VectorBuilder::requestMask() {
if (Mask)
return *Mask;

return *getAllTrueMask();
}

Value &VectorBuilder::requestEVL() {
if (ExplicitVectorLength)
return *ExplicitVectorLength;

assert(!StaticVectorLength.isScalable() && "TODO vscale lowering");
auto *IntTy = Builder.getInt32Ty();
return *ConstantInt::get(IntTy, StaticVectorLength.getFixedValue());
}

Value *VectorBuilder::createVectorInstruction(unsigned Opcode, Type *ReturnTy,
ArrayRef<Value *> InstOpArray,
const Twine &Name) {
auto VPID = VPIntrinsic::getForOpcode(Opcode);
if (VPID == Intrinsic::not_intrinsic)
return returnWithError<Value *>("No VPIntrinsic for this opcode");

auto MaskPosOpt = VPIntrinsic::getMaskParamPos(VPID);
auto VLenPosOpt = VPIntrinsic::getVectorLengthParamPos(VPID);
size_t NumInstParams = InstOpArray.size();
size_t NumVPParams =
NumInstParams + MaskPosOpt.hasValue() + VLenPosOpt.hasValue();

SmallVector<Value *, 6> IntrinParams;

// Whether the mask and vlen parameter are at the end of the parameter list.
bool TrailingMaskAndVLen =
std::min<size_t>(MaskPosOpt.getValueOr(NumInstParams),
VLenPosOpt.getValueOr(NumInstParams)) >= NumInstParams;

if (TrailingMaskAndVLen) {
// Fast path for trailing mask, vector length.
IntrinParams.append(InstOpArray.begin(), InstOpArray.end());
IntrinParams.resize(NumVPParams);
} else {
IntrinParams.resize(NumVPParams);
// Insert mask and evl operands in between the instruction operands.
for (size_t VPParamIdx = 0, ParamIdx = 0; VPParamIdx < NumVPParams;
++VPParamIdx) {
if ((MaskPosOpt && MaskPosOpt.getValueOr(NumVPParams) == VPParamIdx) ||
(VLenPosOpt && VLenPosOpt.getValueOr(NumVPParams) == VPParamIdx))
continue;
assert(ParamIdx < NumInstParams);
IntrinParams[VPParamIdx] = InstOpArray[ParamIdx++];
}
}

if (MaskPosOpt.hasValue())
IntrinParams[*MaskPosOpt] = &requestMask();
if (VLenPosOpt.hasValue())
IntrinParams[*VLenPosOpt] = &requestEVL();

auto *VPDecl = VPIntrinsic::getDeclarationForParams(&getModule(), VPID,
ReturnTy, IntrinParams);
return Builder.CreateCall(VPDecl, IntrinParams, Name);
}

} // namespace llvm
1 change: 1 addition & 0 deletions llvm/unittests/IR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ add_llvm_unittest(IRTests
ValueHandleTest.cpp
ValueMapTest.cpp
ValueTest.cpp
VectorBuilderTest.cpp
VectorTypesTest.cpp
VerifierTest.cpp
VPIntrinsicTest.cpp
Expand Down
Loading

0 comments on commit 5f62156

Please sign in to comment.