forked from OSchip/llvm-project
104 lines
3.6 KiB
C++
104 lines
3.6 KiB
C++
//===- 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
|