-
Notifications
You must be signed in to change notification settings - Fork 10.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[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
- Loading branch information
Showing
6 changed files
with
485 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.