[llvm] 5f62156 - [VP] Introducing VectorBuilder, the VP intrinsic builder

Simon Moll via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 7 01:03:15 PST 2022


Author: Simon Moll
Date: 2022-03-07T10:02:07+01:00
New Revision: 5f62156762d45f53fa70446c718813f9f9a099e5

URL: https://github.com/llvm/llvm-project/commit/5f62156762d45f53fa70446c718813f9f9a099e5
DIFF: https://github.com/llvm/llvm-project/commit/5f62156762d45f53fa70446c718813f9f9a099e5.diff

LOG: [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

Added: 
    llvm/include/llvm/IR/VectorBuilder.h
    llvm/lib/IR/VectorBuilder.cpp
    llvm/unittests/IR/VectorBuilderTest.cpp

Modified: 
    llvm/include/llvm/module.modulemap
    llvm/lib/IR/CMakeLists.txt
    llvm/unittests/IR/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/VectorBuilder.h b/llvm/include/llvm/IR/VectorBuilder.h
new file mode 100644
index 0000000000000..a24338adf3c5d
--- /dev/null
+++ b/llvm/include/llvm/IR/VectorBuilder.h
@@ -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

diff  --git a/llvm/include/llvm/module.modulemap b/llvm/include/llvm/module.modulemap
index 2e6bf791330d1..c94bece5c0985 100644
--- a/llvm/include/llvm/module.modulemap
+++ b/llvm/include/llvm/module.modulemap
@@ -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

diff  --git a/llvm/lib/IR/CMakeLists.txt b/llvm/lib/IR/CMakeLists.txt
index 2c09e57c3f970..3e542e4622fbd 100644
--- a/llvm/lib/IR/CMakeLists.txt
+++ b/llvm/lib/IR/CMakeLists.txt
@@ -61,6 +61,7 @@ add_llvm_component_library(LLVMCore
   User.cpp
   Value.cpp
   ValueSymbolTable.cpp
+  VectorBuilder.cpp
   Verifier.cpp
 
   ADDITIONAL_HEADER_DIRS

diff  --git a/llvm/lib/IR/VectorBuilder.cpp b/llvm/lib/IR/VectorBuilder.cpp
new file mode 100644
index 0000000000000..34d943a9b10b4
--- /dev/null
+++ b/llvm/lib/IR/VectorBuilder.cpp
@@ -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

diff  --git a/llvm/unittests/IR/CMakeLists.txt b/llvm/unittests/IR/CMakeLists.txt
index 42fa677b24721..e9f3d5598d142 100644
--- a/llvm/unittests/IR/CMakeLists.txt
+++ b/llvm/unittests/IR/CMakeLists.txt
@@ -41,6 +41,7 @@ add_llvm_unittest(IRTests
   ValueHandleTest.cpp
   ValueMapTest.cpp
   ValueTest.cpp
+  VectorBuilderTest.cpp
   VectorTypesTest.cpp
   VerifierTest.cpp
   VPIntrinsicTest.cpp

diff  --git a/llvm/unittests/IR/VectorBuilderTest.cpp b/llvm/unittests/IR/VectorBuilderTest.cpp
new file mode 100644
index 0000000000000..82ce045ab4b05
--- /dev/null
+++ b/llvm/unittests/IR/VectorBuilderTest.cpp
@@ -0,0 +1,280 @@
+//===--------- VectorBuilderTest.cpp - VectorBuilder unit tests -----------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/VectorBuilder.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+static unsigned VectorNumElements = 8;
+
+class VectorBuilderTest : public testing::Test {
+protected:
+  LLVMContext Context;
+
+  VectorBuilderTest() : Context() {}
+
+  std::unique_ptr<Module> createBuilderModule(Function *&Func, BasicBlock *&BB,
+                                              Value *&Mask, Value *&EVL) {
+    auto Mod = std::make_unique<Module>("TestModule", Context);
+    auto *Int32Ty = Type::getInt32Ty(Context);
+    auto *Mask8Ty =
+        FixedVectorType::get(Type::getInt1Ty(Context), VectorNumElements);
+    auto *VoidFuncTy =
+        FunctionType::get(Type::getVoidTy(Context), {Mask8Ty, Int32Ty}, false);
+    Func =
+        Function::Create(VoidFuncTy, GlobalValue::ExternalLinkage, "bla", *Mod);
+    Mask = Func->getArg(0);
+    EVL = Func->getArg(1);
+    BB = BasicBlock::Create(Context, "entry", Func);
+
+    return Mod;
+  }
+};
+
+/// Check that creating binary arithmetic VP intrinsics works.
+TEST_F(VectorBuilderTest, TestCreateBinaryInstructions) {
+  Function *F;
+  BasicBlock *BB;
+  Value *Mask, *EVL;
+  auto Mod = createBuilderModule(F, BB, Mask, EVL);
+
+  IRBuilder<> Builder(BB);
+  VectorBuilder VBuild(Builder);
+  VBuild.setMask(Mask).setEVL(EVL);
+
+  auto *FloatVecTy =
+      FixedVectorType::get(Type::getFloatTy(Context), VectorNumElements);
+  auto *IntVecTy =
+      FixedVectorType::get(Type::getInt32Ty(Context), VectorNumElements);
+
+#define HANDLE_BINARY_INST(NUM, OPCODE, INSTCLASS)                             \
+  {                                                                            \
+    auto VPID = VPIntrinsic::getForOpcode(Instruction::OPCODE);                \
+    bool IsFP = (#INSTCLASS)[0] == 'F';                                        \
+    auto *ValueTy = IsFP ? FloatVecTy : IntVecTy;                              \
+    Value *Op = UndefValue::get(ValueTy);                                      \
+    auto *I = VBuild.createVectorInstruction(Instruction::OPCODE, ValueTy,     \
+                                             {Op, Op});                        \
+    ASSERT_TRUE(isa<VPIntrinsic>(I));                                          \
+    auto *VPIntrin = cast<VPIntrinsic>(I);                                     \
+    ASSERT_EQ(VPIntrin->getIntrinsicID(), VPID);                               \
+    ASSERT_EQ(VPIntrin->getMaskParam(), Mask);                                 \
+    ASSERT_EQ(VPIntrin->getVectorLengthParam(), EVL);                          \
+  }
+#include "llvm/IR/Instruction.def"
+}
+
+static bool isAllTrueMask(Value *Val, unsigned NumElements) {
+  auto *ConstMask = dyn_cast<Constant>(Val);
+  if (!ConstMask)
+    return false;
+
+  // Structure check.
+  if (!ConstMask->isAllOnesValue())
+    return false;
+
+  // Type check.
+  auto *MaskVecTy = cast<FixedVectorType>(ConstMask->getType());
+  if (MaskVecTy->getNumElements() != NumElements)
+    return false;
+
+  return MaskVecTy->getElementType()->isIntegerTy(1);
+}
+
+/// Check that creating binary arithmetic VP intrinsics works.
+TEST_F(VectorBuilderTest, TestCreateBinaryInstructions_FixedVector_NoMask) {
+  Function *F;
+  BasicBlock *BB;
+  Value *Mask, *EVL;
+  auto Mod = createBuilderModule(F, BB, Mask, EVL);
+
+  IRBuilder<> Builder(BB);
+  VectorBuilder VBuild(Builder);
+  VBuild.setEVL(EVL).setStaticVL(VectorNumElements);
+
+  auto *FloatVecTy =
+      FixedVectorType::get(Type::getFloatTy(Context), VectorNumElements);
+  auto *IntVecTy =
+      FixedVectorType::get(Type::getInt32Ty(Context), VectorNumElements);
+
+#define HANDLE_BINARY_INST(NUM, OPCODE, INSTCLASS)                             \
+  {                                                                            \
+    auto VPID = VPIntrinsic::getForOpcode(Instruction::OPCODE);                \
+    bool IsFP = (#INSTCLASS)[0] == 'F';                                        \
+    Type *ValueTy = IsFP ? FloatVecTy : IntVecTy;                              \
+    Value *Op = UndefValue::get(ValueTy);                                      \
+    auto *I = VBuild.createVectorInstruction(Instruction::OPCODE, ValueTy,     \
+                                             {Op, Op});                        \
+    ASSERT_TRUE(isa<VPIntrinsic>(I));                                          \
+    auto *VPIntrin = cast<VPIntrinsic>(I);                                     \
+    ASSERT_EQ(VPIntrin->getIntrinsicID(), VPID);                               \
+    ASSERT_TRUE(isAllTrueMask(VPIntrin->getMaskParam(), VectorNumElements));   \
+    ASSERT_EQ(VPIntrin->getVectorLengthParam(), EVL);                          \
+  }
+#include "llvm/IR/Instruction.def"
+}
+
+static bool isLegalConstEVL(Value *Val, unsigned ExpectedEVL) {
+  auto *ConstEVL = dyn_cast<ConstantInt>(Val);
+  if (!ConstEVL)
+    return false;
+
+  // Value check.
+  if (ConstEVL->getZExtValue() != ExpectedEVL)
+    return false;
+
+  // Type check.
+  return ConstEVL->getType()->isIntegerTy(32);
+}
+
+/// Check that creating binary arithmetic VP intrinsics works.
+TEST_F(VectorBuilderTest, TestCreateBinaryInstructions_FixedVector_NoEVL) {
+  Function *F;
+  BasicBlock *BB;
+  Value *Mask, *EVL;
+  auto Mod = createBuilderModule(F, BB, Mask, EVL);
+
+  IRBuilder<> Builder(BB);
+  VectorBuilder VBuild(Builder);
+  VBuild.setMask(Mask).setStaticVL(VectorNumElements);
+
+  auto *FloatVecTy =
+      FixedVectorType::get(Type::getFloatTy(Context), VectorNumElements);
+  auto *IntVecTy =
+      FixedVectorType::get(Type::getInt32Ty(Context), VectorNumElements);
+
+#define HANDLE_BINARY_INST(NUM, OPCODE, INSTCLASS)                             \
+  {                                                                            \
+    auto VPID = VPIntrinsic::getForOpcode(Instruction::OPCODE);                \
+    bool IsFP = (#INSTCLASS)[0] == 'F';                                        \
+    Type *ValueTy = IsFP ? FloatVecTy : IntVecTy;                              \
+    Value *Op = UndefValue::get(ValueTy);                                      \
+    auto *I = VBuild.createVectorInstruction(Instruction::OPCODE, ValueTy,     \
+                                             {Op, Op});                        \
+    ASSERT_TRUE(isa<VPIntrinsic>(I));                                          \
+    auto *VPIntrin = cast<VPIntrinsic>(I);                                     \
+    ASSERT_EQ(VPIntrin->getIntrinsicID(), VPID);                               \
+    ASSERT_EQ(VPIntrin->getMaskParam(), Mask);                                 \
+    ASSERT_TRUE(                                                               \
+        isLegalConstEVL(VPIntrin->getVectorLengthParam(), VectorNumElements)); \
+  }
+#include "llvm/IR/Instruction.def"
+}
+
+/// Check that creating binary arithmetic VP intrinsics works.
+TEST_F(VectorBuilderTest,
+       TestCreateBinaryInstructions_FixedVector_NoMask_NoEVL) {
+  Function *F;
+  BasicBlock *BB;
+  Value *Mask, *EVL;
+  auto Mod = createBuilderModule(F, BB, Mask, EVL);
+
+  IRBuilder<> Builder(BB);
+  VectorBuilder VBuild(Builder);
+  VBuild.setStaticVL(VectorNumElements);
+
+  auto *FloatVecTy =
+      FixedVectorType::get(Type::getFloatTy(Context), VectorNumElements);
+  auto *IntVecTy =
+      FixedVectorType::get(Type::getInt32Ty(Context), VectorNumElements);
+
+#define HANDLE_BINARY_INST(NUM, OPCODE, INSTCLASS)                             \
+  {                                                                            \
+    auto VPID = VPIntrinsic::getForOpcode(Instruction::OPCODE);                \
+    bool IsFP = (#INSTCLASS)[0] == 'F';                                        \
+    Type *ValueTy = IsFP ? FloatVecTy : IntVecTy;                              \
+    Value *Op = UndefValue::get(ValueTy);                                      \
+    auto *I = VBuild.createVectorInstruction(Instruction::OPCODE, ValueTy,     \
+                                             {Op, Op});                        \
+    ASSERT_TRUE(isa<VPIntrinsic>(I));                                          \
+    auto *VPIntrin = cast<VPIntrinsic>(I);                                     \
+    ASSERT_EQ(VPIntrin->getIntrinsicID(), VPID);                               \
+    ASSERT_TRUE(isAllTrueMask(VPIntrin->getMaskParam(), VectorNumElements));   \
+    ASSERT_TRUE(                                                               \
+        isLegalConstEVL(VPIntrin->getVectorLengthParam(), VectorNumElements)); \
+  }
+#include "llvm/IR/Instruction.def"
+}
+/// Check that creating vp.load/vp.store works.
+TEST_F(VectorBuilderTest, TestCreateLoadStore) {
+  Function *F;
+  BasicBlock *BB;
+  Value *Mask, *EVL;
+  auto Mod = createBuilderModule(F, BB, Mask, EVL);
+
+  IRBuilder<> Builder(BB);
+  VectorBuilder VBuild(Builder);
+  VBuild.setMask(Mask).setEVL(EVL);
+
+  auto *FloatVecTy =
+      FixedVectorType::get(Type::getFloatTy(Context), VectorNumElements);
+  auto *FloatVecPtrTy = FloatVecTy->getPointerTo();
+
+  Value *FloatVecPtr = UndefValue::get(FloatVecPtrTy);
+  Value *FloatVec = UndefValue::get(FloatVecTy);
+
+  // vp.load
+  auto LoadVPID = VPIntrinsic::getForOpcode(Instruction::Load);
+  auto *LoadIntrin = VBuild.createVectorInstruction(Instruction::Load,
+                                                    FloatVecTy, {FloatVecPtr});
+  ASSERT_TRUE(isa<VPIntrinsic>(LoadIntrin));
+  auto *VPLoad = cast<VPIntrinsic>(LoadIntrin);
+  ASSERT_EQ(VPLoad->getIntrinsicID(), LoadVPID);
+  ASSERT_EQ(VPLoad->getMemoryPointerParam(), FloatVecPtr);
+
+  // vp.store
+  auto *VoidTy = Builder.getVoidTy();
+  auto StoreVPID = VPIntrinsic::getForOpcode(Instruction::Store);
+  auto *StoreIntrin = VBuild.createVectorInstruction(Instruction::Store, VoidTy,
+                                                     {FloatVec, FloatVecPtr});
+  ASSERT_TRUE(isa<VPIntrinsic>(LoadIntrin));
+  auto *VPStore = cast<VPIntrinsic>(StoreIntrin);
+  ASSERT_EQ(VPStore->getIntrinsicID(), StoreVPID);
+  ASSERT_EQ(VPStore->getMemoryPointerParam(), FloatVecPtr);
+  ASSERT_EQ(VPStore->getMemoryDataParam(), FloatVec);
+}
+
+/// Check that the SilentlyReturnNone error handling mode works.
+TEST_F(VectorBuilderTest, TestFail_SilentlyReturnNone) {
+  Function *F;
+  BasicBlock *BB;
+  Value *Mask, *EVL;
+  auto Mod = createBuilderModule(F, BB, Mask, EVL);
+
+  IRBuilder<> Builder(BB);
+  auto *VoidTy = Builder.getVoidTy();
+  VectorBuilder VBuild(Builder, VectorBuilder::Behavior::SilentlyReturnNone);
+  VBuild.setMask(Mask).setEVL(EVL);
+  auto *Val = VBuild.createVectorInstruction(Instruction::Br, VoidTy, {});
+  ASSERT_EQ(Val, nullptr);
+}
+
+/// Check that the ReportAndFail error handling mode aborts as advertised.
+TEST_F(VectorBuilderTest, TestFail_ReportAndAbort) {
+  Function *F;
+  BasicBlock *BB;
+  Value *Mask, *EVL;
+  auto Mod = createBuilderModule(F, BB, Mask, EVL);
+
+  IRBuilder<> Builder(BB);
+  auto *VoidTy = Builder.getVoidTy();
+  VectorBuilder VBuild(Builder, VectorBuilder::Behavior::ReportAndAbort);
+  VBuild.setMask(Mask).setEVL(EVL);
+  ASSERT_DEATH({ VBuild.createVectorInstruction(Instruction::Br, VoidTy, {}); },
+               "No VPIntrinsic for this opcode");
+}
+
+} // end anonymous namespace


        


More information about the llvm-commits mailing list