From: Igor Laevsky Date: Thu, 30 Nov 2017 15:24:41 +0000 (+0000) Subject: [FuzzMutate] Don't create load as a new source if it doesn't match with the descriptor X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=703237d8da94cc579ca0238466d44d3ccd6928ff;p=llvm [FuzzMutate] Don't create load as a new source if it doesn't match with the descriptor Differential Revision: https://reviews.llvm.org/D40394 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@319439 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/FuzzMutate/RandomIRBuilder.cpp b/lib/FuzzMutate/RandomIRBuilder.cpp index 42e30464b0d..3c9a35986be 100644 --- a/lib/FuzzMutate/RandomIRBuilder.cpp +++ b/lib/FuzzMutate/RandomIRBuilder.cpp @@ -45,22 +45,25 @@ Value *RandomIRBuilder::newSource(BasicBlock &BB, ArrayRef Insts, // Generate some constants to choose from. auto RS = makeSampler(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(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(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, diff --git a/unittests/FuzzMutate/CMakeLists.txt b/unittests/FuzzMutate/CMakeLists.txt index e50c15b377b..c4a5fcf4f14 100644 --- a/unittests/FuzzMutate/CMakeLists.txt +++ b/unittests/FuzzMutate/CMakeLists.txt @@ -9,4 +9,5 @@ add_llvm_unittest(FuzzMutateTests OperationsTest.cpp ReservoirSamplerTest.cpp StrategiesTest.cpp + RandomIRBuilderTest.cpp ) diff --git a/unittests/FuzzMutate/RandomIRBuilderTest.cpp b/unittests/FuzzMutate/RandomIRBuilderTest.cpp new file mode 100644 index 00000000000..f8a50a117ba --- /dev/null +++ b/unittests/FuzzMutate/RandomIRBuilderTest.cpp @@ -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 parseAssembly( + const char *Assembly, LLVMContext &Context) { + + SMDiagnostic Error; + std::unique_ptr 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 Insts; + for (auto I = BB.getFirstInsertionPt(), E = BB.end(); I != E; ++I) + Insts.push_back(&*I); + + // Pick first and second sources + SmallVector 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)); + } +} + +}