[FuzzMutate] Don't create load as a new source if it doesn't match with the descriptor
authorIgor Laevsky <igmyrj@gmail.com>
Thu, 30 Nov 2017 15:24:41 +0000 (15:24 +0000)
committerIgor Laevsky <igmyrj@gmail.com>
Thu, 30 Nov 2017 15:24:41 +0000 (15:24 +0000)
Differential Revision: https://reviews.llvm.org/D40394

llvm-svn: 319439

llvm/lib/FuzzMutate/RandomIRBuilder.cpp
llvm/unittests/FuzzMutate/CMakeLists.txt
llvm/unittests/FuzzMutate/RandomIRBuilderTest.cpp [new file with mode: 0644]

index 42e3046..3c9a359 100644 (file)
@@ -45,22 +45,25 @@ Value *RandomIRBuilder::newSource(BasicBlock &BB, ArrayRef<Instruction *> Insts,
   // Generate some constants to choose from.
   auto RS = makeSampler<Value *>(Rand);
   RS.sample(Pred.generate(Srcs, KnownTypes));
-  assert(!RS.isEmpty() && "Failed to generate sources");
 
   // If we can find a pointer to load from, use it half the time.
   Value *Ptr = findPointer(BB, Insts, Srcs, Pred);
-  if (Ptr)
-    RS.sample(Ptr, RS.totalWeight());
+  if (Ptr) {
+    // Create load from the chosen pointer
+    auto IP = BB.getFirstInsertionPt();
+    if (auto *I = dyn_cast<Instruction>(Ptr))
+      IP = ++I->getIterator();
+    auto *NewLoad = new LoadInst(Ptr, "L", &*IP);
 
-  Value *Result = RS.getSelection();
-  if (Result != Ptr)
-    return Result;
+    // Only sample this load if it really matches the descriptor
+    if (Pred.matches(Srcs, NewLoad))
+      RS.sample(NewLoad, RS.totalWeight());
+    else
+      NewLoad->eraseFromParent();
+  }
 
-  // If we choose the pointer, we need to create a load.
-  auto IP = BB.getFirstInsertionPt();
-  if (auto *I = dyn_cast<Instruction>(Ptr))
-    IP = ++I->getIterator();
-  return new LoadInst(Ptr, "L", &*IP);
+  assert(!RS.isEmpty() && "Failed to generate sources");
+  return RS.getSelection();
 }
 
 static bool isCompatibleReplacement(const Instruction *I, const Use &Operand,
index e50c15b..c4a5fcf 100644 (file)
@@ -9,4 +9,5 @@ add_llvm_unittest(FuzzMutateTests
   OperationsTest.cpp
   ReservoirSamplerTest.cpp
   StrategiesTest.cpp
+  RandomIRBuilderTest.cpp
   )
diff --git a/llvm/unittests/FuzzMutate/RandomIRBuilderTest.cpp b/llvm/unittests/FuzzMutate/RandomIRBuilderTest.cpp
new file mode 100644 (file)
index 0000000..f8a50a1
--- /dev/null
@@ -0,0 +1,87 @@
+//===- RandomIRBuilderTest.cpp - Tests for injector strategy --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/FuzzMutate/RandomIRBuilder.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/AsmParser/SlotMapping.h"
+#include "llvm/FuzzMutate/IRMutator.h"
+#include "llvm/FuzzMutate/OpDescriptor.h"
+#include "llvm/FuzzMutate/Operations.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Support/SourceMgr.h"
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+static constexpr int Seed = 5;
+
+namespace {
+
+std::unique_ptr<Module> parseAssembly(
+    const char *Assembly, LLVMContext &Context) {
+
+  SMDiagnostic Error;
+  std::unique_ptr<Module> M = parseAssemblyString(Assembly, Error, Context);
+
+  std::string ErrMsg;
+  raw_string_ostream OS(ErrMsg);
+  Error.print("", OS);
+
+  assert(M && !verifyModule(*M, &errs()));
+  return M;
+}
+
+TEST(RandomIRBuilderTest, ShuffleVectorIncorrectOperands) {
+  // Test that we don't create load instruction as a source for the shuffle
+  // vector operation.
+
+  LLVMContext Ctx;
+  const char *Source =
+      "define <2 x i32> @test(<2 x i1> %cond, <2 x i32> %a) {\n"
+      "  %A = alloca <2 x i32>\n"
+      "  %I = insertelement <2 x i32> %a, i32 1, i32 1\n"
+      "  ret <2 x i32> undef\n"
+      "}";
+  auto M = parseAssembly(Source, Ctx);
+
+  fuzzerop::OpDescriptor Descr = fuzzerop::shuffleVectorDescriptor(1);
+
+  // Empty known types since we ShuffleVector descriptor doesn't care about them
+  RandomIRBuilder IB(Seed, {});
+
+  // Get first basic block of the first function
+  Function &F = *M->begin();
+  BasicBlock &BB = *F.begin();
+
+  SmallVector<Instruction *, 32> Insts;
+  for (auto I = BB.getFirstInsertionPt(), E = BB.end(); I != E; ++I)
+    Insts.push_back(&*I);
+
+  // Pick first and second sources
+  SmallVector<Value *, 2> Srcs;
+  ASSERT_TRUE(Descr.SourcePreds[0].matches(Srcs, Insts[1]));
+  Srcs.push_back(Insts[1]);
+  ASSERT_TRUE(Descr.SourcePreds[1].matches(Srcs, Insts[1]));
+  Srcs.push_back(Insts[1]);
+
+  // Create new source. Check that it always matches with the descriptor.
+  // Run some iterations to account for random decisions.
+  for (int i = 0; i < 10; ++i) {
+    Value *LastSrc = IB.newSource(BB, Insts, Srcs, Descr.SourcePreds[2]);
+    ASSERT_TRUE(Descr.SourcePreds[2].matches(Srcs, LastSrc));
+  }
+}
+
+}