[llvm] c06adae - [FuzzMutate] introduce vector operations, select and fneg into InstInjectorStrategy

Peter Rong via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 31 17:48:33 PDT 2023


Author: Peter Rong
Date: 2023-03-31T17:48:27-07:00
New Revision: c06adaeba69de173f8eaa16f3449d7e0edaa897f

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

LOG: [FuzzMutate] introduce vector operations, select and fneg into InstInjectorStrategy

Reviewed By: arsenm

Differential Revision: https://reviews.llvm.org/D139894

Added: 
    

Modified: 
    llvm/include/llvm/FuzzMutate/OpDescriptor.h
    llvm/include/llvm/FuzzMutate/Operations.h
    llvm/lib/FuzzMutate/OpDescriptor.cpp
    llvm/lib/FuzzMutate/Operations.cpp
    llvm/unittests/FuzzMutate/OperationsTest.cpp
    llvm/unittests/FuzzMutate/StrategiesTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/FuzzMutate/OpDescriptor.h b/llvm/include/llvm/FuzzMutate/OpDescriptor.h
index 800586da8f2d1..f3b185dfedd8d 100644
--- a/llvm/include/llvm/FuzzMutate/OpDescriptor.h
+++ b/llvm/include/llvm/FuzzMutate/OpDescriptor.h
@@ -18,6 +18,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/Type.h"
 #include "llvm/IR/Value.h"
 #include <functional>
@@ -117,6 +118,20 @@ static inline SourcePred anyIntType() {
   return {Pred, Make};
 }
 
+static inline SourcePred anyIntOrVecIntType() {
+  auto Pred = [](ArrayRef<Value *>, const Value *V) {
+    return V->getType()->isIntOrIntVectorTy();
+  };
+  return {Pred, std::nullopt};
+}
+
+static inline SourcePred boolOrVecBoolType() {
+  auto Pred = [](ArrayRef<Value *>, const Value *V) {
+    return V->getType()->isIntOrIntVectorTy(1);
+  };
+  return {Pred, std::nullopt};
+}
+
 static inline SourcePred anyFloatType() {
   auto Pred = [](ArrayRef<Value *>, const Value *V) {
     return V->getType()->isFloatingPointTy();
@@ -125,6 +140,13 @@ static inline SourcePred anyFloatType() {
   return {Pred, Make};
 }
 
+static inline SourcePred anyFloatOrVecFloatType() {
+  auto Pred = [](ArrayRef<Value *>, const Value *V) {
+    return V->getType()->isFPOrFPVectorTy();
+  };
+  return {Pred, std::nullopt};
+}
+
 static inline SourcePred anyPtrType() {
   auto Pred = [](ArrayRef<Value *>, const Value *V) {
     return V->getType()->isPointerTy() && !V->isSwiftError();
@@ -161,6 +183,54 @@ static inline SourcePred sizedPtrType() {
   return {Pred, Make};
 }
 
+static inline SourcePred matchFirstLengthWAnyType() {
+  auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
+    assert(!Cur.empty() && "No first source yet");
+    Type *This = V->getType(), *First = Cur[0]->getType();
+    VectorType *ThisVec = dyn_cast<VectorType>(This);
+    VectorType *FirstVec = dyn_cast<VectorType>(First);
+    if (ThisVec && FirstVec) {
+      return ThisVec->getElementCount() == FirstVec->getElementCount();
+    }
+    return (ThisVec == nullptr) && (FirstVec == nullptr) && (!This->isVoidTy());
+  };
+  auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes) {
+    assert(!Cur.empty() && "No first source yet");
+    std::vector<Constant *> Result;
+    ElementCount EC;
+    bool isVec = false;
+    if (VectorType *VecTy = dyn_cast<VectorType>(Cur[0]->getType())) {
+      EC = VecTy->getElementCount();
+      isVec = true;
+    }
+    for (Type *T : BaseTypes) {
+      if (VectorType::isValidElementType(T)) {
+        if (isVec)
+          // If the first pred is <i1 x N>, make the result <T x N>
+          makeConstantsWithType(VectorType::get(T, EC), Result);
+        else
+          makeConstantsWithType(T, Result);
+      }
+    }
+    assert(!Result.empty() && "No potential constants.");
+    return Result;
+  };
+  return {Pred, Make};
+}
+
+/// Match values that have the same type as the first source.
+static inline SourcePred matchSecondType() {
+  auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
+    assert((Cur.size() > 1) && "No second source yet");
+    return V->getType() == Cur[1]->getType();
+  };
+  auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
+    assert((Cur.size() > 1) && "No second source yet");
+    return makeConstantsWithType(Cur[1]->getType());
+  };
+  return {Pred, Make};
+}
+
 static inline SourcePred anyAggregateType() {
   auto Pred = [](ArrayRef<Value *>, const Value *V) {
     // We can't index zero sized arrays.

diff  --git a/llvm/include/llvm/FuzzMutate/Operations.h b/llvm/include/llvm/FuzzMutate/Operations.h
index d2a6180633ea2..84155730a93cd 100644
--- a/llvm/include/llvm/FuzzMutate/Operations.h
+++ b/llvm/include/llvm/FuzzMutate/Operations.h
@@ -28,12 +28,16 @@ void describeFuzzerControlFlowOps(std::vector<fuzzerop::OpDescriptor> &Ops);
 void describeFuzzerPointerOps(std::vector<fuzzerop::OpDescriptor> &Ops);
 void describeFuzzerAggregateOps(std::vector<fuzzerop::OpDescriptor> &Ops);
 void describeFuzzerVectorOps(std::vector<fuzzerop::OpDescriptor> &Ops);
+void describeFuzzerUnaryOperations(std::vector<fuzzerop::OpDescriptor> &Ops);
+void describeFuzzerOtherOps(std::vector<fuzzerop::OpDescriptor> &Ops);
 /// @}
 
 namespace fuzzerop {
 
 /// Descriptors for individual operations.
 /// @{
+OpDescriptor selectDescriptor(unsigned Weight);
+OpDescriptor fnegDescriptor(unsigned Weight);
 OpDescriptor binOpDescriptor(unsigned Weight, Instruction::BinaryOps Op);
 OpDescriptor cmpOpDescriptor(unsigned Weight, Instruction::OtherOps CmpOp,
                              CmpInst::Predicate Pred);
@@ -44,6 +48,7 @@ OpDescriptor insertValueDescriptor(unsigned Weight);
 OpDescriptor extractElementDescriptor(unsigned Weight);
 OpDescriptor insertElementDescriptor(unsigned Weight);
 OpDescriptor shuffleVectorDescriptor(unsigned Weight);
+
 /// @}
 
 } // namespace fuzzerop

diff  --git a/llvm/lib/FuzzMutate/OpDescriptor.cpp b/llvm/lib/FuzzMutate/OpDescriptor.cpp
index 67d44be8b699b..4baf45284de10 100644
--- a/llvm/lib/FuzzMutate/OpDescriptor.cpp
+++ b/llvm/lib/FuzzMutate/OpDescriptor.cpp
@@ -15,6 +15,9 @@ using namespace fuzzerop;
 void fuzzerop::makeConstantsWithType(Type *T, std::vector<Constant *> &Cs) {
   if (auto *IntTy = dyn_cast<IntegerType>(T)) {
     uint64_t W = IntTy->getBitWidth();
+    Cs.push_back(ConstantInt::get(IntTy, 0));
+    Cs.push_back(ConstantInt::get(IntTy, 1));
+    Cs.push_back(ConstantInt::get(IntTy, 42));
     Cs.push_back(ConstantInt::get(IntTy, APInt::getMaxValue(W)));
     Cs.push_back(ConstantInt::get(IntTy, APInt::getMinValue(W)));
     Cs.push_back(ConstantInt::get(IntTy, APInt::getSignedMaxValue(W)));
@@ -24,10 +27,24 @@ void fuzzerop::makeConstantsWithType(Type *T, std::vector<Constant *> &Cs) {
     auto &Ctx = T->getContext();
     auto &Sem = T->getFltSemantics();
     Cs.push_back(ConstantFP::get(Ctx, APFloat::getZero(Sem)));
+    Cs.push_back(ConstantFP::get(Ctx, APFloat(Sem, 1)));
+    Cs.push_back(ConstantFP::get(Ctx, APFloat(Sem, 42)));
     Cs.push_back(ConstantFP::get(Ctx, APFloat::getLargest(Sem)));
     Cs.push_back(ConstantFP::get(Ctx, APFloat::getSmallest(Sem)));
-  } else
+    Cs.push_back(ConstantFP::get(Ctx, APFloat::getInf(Sem)));
+    Cs.push_back(ConstantFP::get(Ctx, APFloat::getNaN(Sem)));
+  } else if (VectorType *VecTy = dyn_cast<VectorType>(T)) {
+    std::vector<Constant *> EleCs;
+    Type *EltTy = VecTy->getElementType();
+    makeConstantsWithType(EltTy, EleCs);
+    ElementCount EC = VecTy->getElementCount();
+    for (Constant *Elt : EleCs) {
+      Cs.push_back(ConstantVector::getSplat(EC, Elt));
+    }
+  } else {
     Cs.push_back(UndefValue::get(T));
+    Cs.push_back(PoisonValue::get(T));
+  }
 }
 
 std::vector<Constant *> fuzzerop::makeConstantsWithType(Type *T) {

diff  --git a/llvm/lib/FuzzMutate/Operations.cpp b/llvm/lib/FuzzMutate/Operations.cpp
index 46ebbef4d9d24..48455c781629f 100644
--- a/llvm/lib/FuzzMutate/Operations.cpp
+++ b/llvm/lib/FuzzMutate/Operations.cpp
@@ -67,11 +67,20 @@ void llvm::describeFuzzerFloatOps(std::vector<fuzzerop::OpDescriptor> &Ops) {
   Ops.push_back(cmpOpDescriptor(1, Instruction::FCmp, CmpInst::FCMP_TRUE));
 }
 
+void llvm::describeFuzzerUnaryOperations(
+    std::vector<fuzzerop::OpDescriptor> &Ops) {
+  Ops.push_back(fnegDescriptor(1));
+}
+
 void llvm::describeFuzzerControlFlowOps(
     std::vector<fuzzerop::OpDescriptor> &Ops) {
   Ops.push_back(splitBlockDescriptor(1));
 }
 
+void llvm::describeFuzzerOtherOps(std::vector<fuzzerop::OpDescriptor> &Ops) {
+  Ops.push_back(selectDescriptor(1));
+}
+
 void llvm::describeFuzzerPointerOps(std::vector<fuzzerop::OpDescriptor> &Ops) {
   Ops.push_back(gepDescriptor(1));
 }
@@ -88,6 +97,22 @@ void llvm::describeFuzzerVectorOps(std::vector<fuzzerop::OpDescriptor> &Ops) {
   Ops.push_back(shuffleVectorDescriptor(1));
 }
 
+OpDescriptor llvm::fuzzerop::selectDescriptor(unsigned Weight) {
+  auto buildOp = [](ArrayRef<Value *> Srcs, Instruction *Inst) {
+    return SelectInst::Create(Srcs[0], Srcs[1], Srcs[2], "S", Inst);
+  };
+  return {Weight,
+          {boolOrVecBoolType(), matchFirstLengthWAnyType(), matchSecondType()},
+          buildOp};
+}
+
+OpDescriptor llvm::fuzzerop::fnegDescriptor(unsigned Weight) {
+  auto buildOp = [](ArrayRef<Value *> Srcs, Instruction *Inst) {
+    return UnaryOperator::Create(Instruction::FNeg, Srcs[0], "F", Inst);
+  };
+  return {Weight, {anyFloatOrVecFloatType()}, buildOp};
+}
+
 OpDescriptor llvm::fuzzerop::binOpDescriptor(unsigned Weight,
                                              Instruction::BinaryOps Op) {
   auto buildOp = [Op](ArrayRef<Value *> Srcs, Instruction *Inst) {
@@ -107,13 +132,13 @@ OpDescriptor llvm::fuzzerop::binOpDescriptor(unsigned Weight,
   case Instruction::And:
   case Instruction::Or:
   case Instruction::Xor:
-    return {Weight, {anyIntType(), matchFirstType()}, buildOp};
+    return {Weight, {anyIntOrVecIntType(), matchFirstType()}, buildOp};
   case Instruction::FAdd:
   case Instruction::FSub:
   case Instruction::FMul:
   case Instruction::FDiv:
   case Instruction::FRem:
-    return {Weight, {anyFloatType(), matchFirstType()}, buildOp};
+    return {Weight, {anyFloatOrVecFloatType(), matchFirstType()}, buildOp};
   case Instruction::BinaryOpsEnd:
     llvm_unreachable("Value out of range of enum");
   }
@@ -129,9 +154,9 @@ OpDescriptor llvm::fuzzerop::cmpOpDescriptor(unsigned Weight,
 
   switch (CmpOp) {
   case Instruction::ICmp:
-    return {Weight, {anyIntType(), matchFirstType()}, buildOp};
+    return {Weight, {anyIntOrVecIntType(), matchFirstType()}, buildOp};
   case Instruction::FCmp:
-    return {Weight, {anyFloatType(), matchFirstType()}, buildOp};
+    return {Weight, {anyFloatOrVecFloatType(), matchFirstType()}, buildOp};
   default:
     llvm_unreachable("CmpOp must be ICmp or FCmp");
   }

diff  --git a/llvm/unittests/FuzzMutate/OperationsTest.cpp b/llvm/unittests/FuzzMutate/OperationsTest.cpp
index d4c589d74b031..82a37e02aab8c 100644
--- a/llvm/unittests/FuzzMutate/OperationsTest.cpp
+++ b/llvm/unittests/FuzzMutate/OperationsTest.cpp
@@ -91,10 +91,17 @@ TEST(OperationsTest, SourcePreds) {
   Constant *s = ConstantStruct::get(StructType::create(Ctx, "OpaqueStruct"));
   Constant *a =
       ConstantArray::get(ArrayType::get(i32->getType(), 2), {i32, i32});
+  Constant *v8i1 = ConstantVector::getSplat(ElementCount::getFixed(8), i1);
   Constant *v8i8 = ConstantVector::getSplat(ElementCount::getFixed(8), i8);
   Constant *v4f16 = ConstantVector::getSplat(ElementCount::getFixed(4), f16);
   Constant *p0i32 =
       ConstantPointerNull::get(PointerType::get(i32->getType(), 0));
+  Constant *v8p0i32 =
+      ConstantVector::getSplat(ElementCount::getFixed(8), p0i32);
+  Constant *vni32 = ConstantVector::getSplat(ElementCount::getScalable(8), i32);
+  Constant *vnf64 = ConstantVector::getSplat(ElementCount::getScalable(8), f64);
+  Constant *vnp0i32 =
+      ConstantVector::getSplat(ElementCount::getScalable(8), p0i32);
 
   auto OnlyI32 = onlyType(i32->getType());
   EXPECT_TRUE(OnlyI32.matches({}, i32));
@@ -126,6 +133,36 @@ TEST(OperationsTest, SourcePreds) {
       AnyInt.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
       AllOf(SizeIs(Ge(1u)), Each(TypesMatch(i32))));
 
+  auto AnyIntOrVecInt = anyIntOrVecIntType();
+  EXPECT_TRUE(AnyIntOrVecInt.matches({}, i1));
+  EXPECT_TRUE(AnyIntOrVecInt.matches({}, i64));
+  EXPECT_FALSE(AnyIntOrVecInt.matches({}, f32));
+  EXPECT_FALSE(AnyIntOrVecInt.matches({}, v4f16));
+  EXPECT_TRUE(AnyIntOrVecInt.matches({}, v8i8));
+  EXPECT_FALSE(AnyIntOrVecInt.matches({}, v4f16));
+  EXPECT_FALSE(AnyIntOrVecInt.matches({}, v8p0i32));
+  EXPECT_TRUE(AnyIntOrVecInt.matches({}, vni32));
+  EXPECT_FALSE(AnyIntOrVecInt.matches({}, vnf64));
+  EXPECT_FALSE(AnyIntOrVecInt.matches({}, vnp0i32));
+
+  EXPECT_THAT(AnyIntOrVecInt.generate({}, {v8i8->getType()}),
+              AllOf(Each(TypesMatch(v8i8))));
+
+  auto BoolOrVecBool = boolOrVecBoolType();
+  EXPECT_TRUE(BoolOrVecBool.matches({}, i1));
+  EXPECT_FALSE(BoolOrVecBool.matches({}, i64));
+  EXPECT_FALSE(BoolOrVecBool.matches({}, f32));
+  EXPECT_FALSE(BoolOrVecBool.matches({}, v4f16));
+  EXPECT_TRUE(BoolOrVecBool.matches({}, v8i1));
+  EXPECT_FALSE(BoolOrVecBool.matches({}, v4f16));
+  EXPECT_FALSE(BoolOrVecBool.matches({}, v8p0i32));
+  EXPECT_FALSE(BoolOrVecBool.matches({}, vni32));
+  EXPECT_FALSE(BoolOrVecBool.matches({}, vnf64));
+  EXPECT_FALSE(BoolOrVecBool.matches({}, vnp0i32));
+
+  EXPECT_THAT(BoolOrVecBool.generate({}, {v8i8->getType(), v8i1->getType()}),
+              AllOf(Each(TypesMatch(v8i1))));
+
   auto AnyFP = anyFloatType();
   EXPECT_TRUE(AnyFP.matches({}, f16));
   EXPECT_TRUE(AnyFP.matches({}, f32));
@@ -137,11 +174,30 @@ TEST(OperationsTest, SourcePreds) {
       AnyFP.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
       AllOf(SizeIs(Ge(1u)), Each(TypesMatch(f16))));
 
+  auto AnyFPOrVecFP = anyFloatOrVecFloatType();
+  EXPECT_TRUE(AnyFPOrVecFP.matches({}, f16));
+  EXPECT_TRUE(AnyFPOrVecFP.matches({}, f32));
+  EXPECT_FALSE(AnyFPOrVecFP.matches({}, i16));
+  EXPECT_FALSE(AnyFPOrVecFP.matches({}, p0i32));
+  EXPECT_TRUE(AnyFPOrVecFP.matches({}, v4f16));
+  EXPECT_FALSE(AnyFPOrVecFP.matches({}, v8p0i32));
+  EXPECT_FALSE(AnyFPOrVecFP.matches({}, vni32));
+  EXPECT_TRUE(AnyFPOrVecFP.matches({}, vnf64));
+  EXPECT_FALSE(AnyFPOrVecFP.matches({}, vnp0i32));
+
+  EXPECT_THAT(AnyFPOrVecFP.generate(
+                  {}, {i32->getType(), f16->getType(), v8i8->getType()}),
+              AllOf(SizeIs(Ge(1u)), Each(TypesMatch(f16))));
+  EXPECT_THAT(AnyFPOrVecFP.generate({}, {v4f16->getType()}),
+              AllOf(SizeIs(Ge(1u)), Each(TypesMatch(v4f16))));
+
   auto AnyPtr = anyPtrType();
   EXPECT_TRUE(AnyPtr.matches({}, p0i32));
   EXPECT_FALSE(AnyPtr.matches({}, i8));
   EXPECT_FALSE(AnyPtr.matches({}, a));
   EXPECT_FALSE(AnyPtr.matches({}, v8i8));
+  EXPECT_FALSE(AnyPtr.matches({}, v8p0i32));
+  EXPECT_FALSE(AnyPtr.matches({}, vni32));
 
   auto isPointer = [](Value *V) { return V->getType()->isPointerTy(); };
   EXPECT_THAT(
@@ -154,9 +210,12 @@ TEST(OperationsTest, SourcePreds) {
   EXPECT_FALSE(AnyVec.matches({}, i8));
   EXPECT_FALSE(AnyVec.matches({}, a));
   EXPECT_FALSE(AnyVec.matches({}, s));
+  EXPECT_TRUE(AnyVec.matches({}, v8p0i32));
+  EXPECT_TRUE(AnyVec.matches({}, vni32));
+  EXPECT_TRUE(AnyVec.matches({}, vnf64));
+  EXPECT_TRUE(AnyVec.matches({}, vnp0i32));
 
-  EXPECT_THAT(AnyVec.generate({}, {v8i8->getType()}),
-              ElementsAre(TypesMatch(v8i8)));
+  EXPECT_THAT(AnyVec.generate({}, {v8i8->getType()}), Each(TypesMatch(v8i8)));
 
   auto First = matchFirstType();
   EXPECT_TRUE(First.matches({i8}, i8));
@@ -167,6 +226,28 @@ TEST(OperationsTest, SourcePreds) {
   EXPECT_THAT(First.generate({i8}, {}), Each(TypesMatch(i8)));
   EXPECT_THAT(First.generate({f16}, {i8->getType()}), Each(TypesMatch(f16)));
   EXPECT_THAT(First.generate({v8i8, i32}, {}), Each(TypesMatch(v8i8)));
+
+  auto FirstLength = matchFirstLengthWAnyType();
+  EXPECT_TRUE(FirstLength.matches({v8i8}, v8i1));
+
+  EXPECT_THAT(FirstLength.generate({v8i1}, {i8->getType()}),
+              Each(TypesMatch(v8i8)));
+
+  auto Second = matchSecondType();
+  EXPECT_TRUE(Second.matches({i32, i8}, i8));
+  EXPECT_TRUE(Second.matches({i8, f16}, f16));
+
+  EXPECT_THAT(Second.generate({v8i8, i32}, {}), Each(TypesMatch(i32)));
+  EXPECT_THAT(Second.generate({f32, f16}, {f16->getType()}),
+              Each(TypesMatch(f16)));
+
+  auto FirstScalar = matchScalarOfFirstType();
+  EXPECT_TRUE(FirstScalar.matches({v8i8}, i8));
+  EXPECT_TRUE(FirstScalar.matches({i8}, i8));
+  EXPECT_TRUE(FirstScalar.matches({v4f16}, f16));
+
+  EXPECT_THAT(FirstScalar.generate({v8i8}, {i8->getType()}),
+              Each(TypesMatch(i8)));
 }
 
 TEST(OperationsTest, SplitBlock) {
@@ -301,13 +382,12 @@ TEST(OperationsTest, GEPPointerOperand) {
   // Check that we only pick sized pointers for the GEP instructions
 
   LLVMContext Ctx;
-  const char *SourceCode =
-      "%opaque = type opaque\n"
-      "declare void @f()\n"
-      "define void @test(%opaque %o) {\n"
-      "  %a = alloca i64, i32 10\n"
-      "  ret void\n"
-      "}";
+  const char *SourceCode = "%opaque = type opaque\n"
+                           "declare void @f()\n"
+                           "define void @test(%opaque %o) {\n"
+                           "  %a = alloca i64, i32 10\n"
+                           "  ret void\n"
+                           "}";
   auto M = parseAssembly(SourceCode, Ctx);
 
   fuzzerop::OpDescriptor Descr = fuzzerop::gepDescriptor(1);

diff  --git a/llvm/unittests/FuzzMutate/StrategiesTest.cpp b/llvm/unittests/FuzzMutate/StrategiesTest.cpp
index 688280f70f22b..92d7fc112020e 100644
--- a/llvm/unittests/FuzzMutate/StrategiesTest.cpp
+++ b/llvm/unittests/FuzzMutate/StrategiesTest.cpp
@@ -34,6 +34,17 @@ std::unique_ptr<IRMutator> createInjectorMutator() {
       Type::getInt1Ty,  Type::getInt8Ty,  Type::getInt16Ty, Type::getInt32Ty,
       Type::getInt64Ty, Type::getFloatTy, Type::getDoubleTy};
 
+  // Add vector 1, 2, 3, 4, and 8.
+  int VectorLength[] = {1, 2, 3, 4, 8};
+  std::vector<TypeGetter> BasicTypeGetters(Types);
+  for (auto typeGetter : BasicTypeGetters) {
+    for (int length : VectorLength) {
+      Types.push_back([typeGetter, length](LLVMContext &C) {
+        return VectorType::get(typeGetter(C), length, false);
+      });
+    }
+  }
+
   std::vector<std::unique_ptr<IRMutationStrategy>> Strategies;
   Strategies.push_back(std::make_unique<InjectorIRStrategy>(
       InjectorIRStrategy::getDefaultOps()));
@@ -78,6 +89,25 @@ void IterateOnSource(StringRef Source, IRMutator &Mutator) {
   }
 }
 
+static void mutateAndVerifyModule(StringRef Source,
+                                  std::unique_ptr<IRMutator> &Mutator,
+                                  int repeat = 100) {
+  LLVMContext Ctx;
+  auto M = parseAssembly(Source.data(), Ctx);
+  std::mt19937 mt(Seed);
+  std::uniform_int_distribution<int> RandInt(INT_MIN, INT_MAX);
+  for (int i = 0; i < repeat; i++) {
+    Mutator->mutateModule(*M, RandInt(mt), Source.size(), Source.size() + 1024);
+    ASSERT_FALSE(verifyModule(*M, &errs()));
+  }
+}
+template <class Strategy>
+static void mutateAndVerifyModule(StringRef Source, int repeat = 100) {
+  auto Mutator = createMutator<Strategy>();
+  ASSERT_TRUE(Mutator);
+  mutateAndVerifyModule(Source, Mutator, repeat);
+}
+
 TEST(InjectorIRStrategyTest, EmptyModule) {
   // Test that we can inject into empty module
 
@@ -92,6 +122,13 @@ TEST(InjectorIRStrategyTest, EmptyModule) {
   EXPECT_TRUE(!verifyModule(*M, &errs()));
 }
 
+TEST(InjectorIRStrategyTest, LargeInsertion) {
+  StringRef Source = "";
+  auto Mutator = createInjectorMutator();
+  ASSERT_TRUE(Mutator);
+  mutateAndVerifyModule(Source, Mutator, 100);
+}
+
 TEST(InstDeleterIRStrategyTest, EmptyFunction) {
   // Test that we don't crash even if we can't remove from one of the functions.
 
@@ -385,21 +422,6 @@ TEST(InstModificationIRStrategy, FastMath) {
     ASSERT_TRUE(p.second);
 }
 
-template <class Strategy>
-static void mutateAndVerifyModule(StringRef Source, int repeat = 100) {
-  LLVMContext Ctx;
-  auto Mutator = createMutator<Strategy>();
-  ASSERT_TRUE(Mutator);
-
-  auto M = parseAssembly(Source.data(), Ctx);
-  std::mt19937 mt(Seed);
-  std::uniform_int_distribution<int> RandInt(INT_MIN, INT_MAX);
-  for (int i = 0; i < repeat; i++) {
-    Mutator->mutateModule(*M, RandInt(mt), Source.size(), Source.size() + 1024);
-    ASSERT_FALSE(verifyModule(*M, &errs()));
-  }
-}
-
 TEST(InsertCFGStrategy, CFG) {
   StringRef Source = "\n\
       define i32 @test(i1 %C1, i1 %C2, i1 %C3, i16 %S1, i16 %S2, i32 %I1) { \n\


        


More information about the llvm-commits mailing list