[llvm] 4be0873 - [FuzzMutate] New InsertPHINode strategy.
Peter Rong via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 30 15:26:58 PST 2022
Author: Peter Rong
Date: 2022-11-30T15:26:52-08:00
New Revision: 4be0873471e4f4fd646a9c5351d82dc38247abf5
URL: https://github.com/llvm/llvm-project/commit/4be0873471e4f4fd646a9c5351d82dc38247abf5
DIFF: https://github.com/llvm/llvm-project/commit/4be0873471e4f4fd646a9c5351d82dc38247abf5.diff
LOG: [FuzzMutate] New InsertPHINode strategy.
PHI Node can't be modeled like other instructions since its operand
number depends on predecessors. So we have a stand alone strategy for it.
Signed-off-by: Peter Rong <PeterRong96 at gmail.com>
Reviewed By: arsenm
Differential Revision: https://reviews.llvm.org/D138959
Added:
Modified:
llvm/include/llvm/FuzzMutate/IRMutator.h
llvm/include/llvm/FuzzMutate/RandomIRBuilder.h
llvm/lib/FuzzMutate/IRMutator.cpp
llvm/lib/FuzzMutate/RandomIRBuilder.cpp
llvm/unittests/FuzzMutate/StrategiesTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/FuzzMutate/IRMutator.h b/llvm/include/llvm/FuzzMutate/IRMutator.h
index 3d9837289e673..0c266f60b4cba 100644
--- a/llvm/include/llvm/FuzzMutate/IRMutator.h
+++ b/llvm/include/llvm/FuzzMutate/IRMutator.h
@@ -118,6 +118,17 @@ class InstModificationIRStrategy : public IRMutationStrategy {
void mutate(Instruction &Inst, RandomIRBuilder &IB) override;
};
+/// Strategy to insert PHI Nodes at the head of each basic block.
+class InsertPHIStrategy : public IRMutationStrategy {
+public:
+ uint64_t getWeight(size_t CurrentSize, size_t MaxSize,
+ uint64_t CurrentWeight) override {
+ return 2;
+ }
+
+ void mutate(BasicBlock &BB, RandomIRBuilder &IB) override;
+};
+
/// Strategy to select a random instruction and add a new sink (user) to it to
/// increate data dependency.
class SinkInstructionStrategy : public IRMutationStrategy {
diff --git a/llvm/include/llvm/FuzzMutate/RandomIRBuilder.h b/llvm/include/llvm/FuzzMutate/RandomIRBuilder.h
index 61703be14771f..d91333eb29e69 100644
--- a/llvm/include/llvm/FuzzMutate/RandomIRBuilder.h
+++ b/llvm/include/llvm/FuzzMutate/RandomIRBuilder.h
@@ -61,6 +61,8 @@ struct RandomIRBuilder {
ArrayRef<Value *> Srcs, fuzzerop::SourcePred Pred);
Type *chooseType(LLVMContext &Context, ArrayRef<Value *> Srcs,
fuzzerop::SourcePred Pred);
+ /// Return a uniformly choosen type from \c AllowedTypes
+ Type *randomType();
};
} // namespace llvm
diff --git a/llvm/lib/FuzzMutate/IRMutator.cpp b/llvm/lib/FuzzMutate/IRMutator.cpp
index 3b57a4d3e558e..11d7e24108639 100644
--- a/llvm/lib/FuzzMutate/IRMutator.cpp
+++ b/llvm/lib/FuzzMutate/IRMutator.cpp
@@ -299,6 +299,35 @@ void InstModificationIRStrategy::mutate(Instruction &Inst,
RS.getSelection()();
}
+void InsertPHIStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {
+ // Can't insert PHI node to entry node.
+ if (&BB == &BB.getParent()->getEntryBlock())
+ return;
+ Type *Ty = IB.randomType();
+ PHINode *PHI = PHINode::Create(Ty, llvm::pred_size(&BB), "", &BB.front());
+
+ // Use a map to make sure the same incoming basic block has the same value.
+ DenseMap<BasicBlock *, Value *> IncomingValues;
+ for (BasicBlock *Pred : predecessors(&BB)) {
+ Value *Src = IncomingValues[Pred];
+ // If `Pred` is not in the map yet, we'll get a nullptr.
+ if (!Src) {
+ SmallVector<Instruction *, 32> Insts;
+ for (auto I = Pred->begin(); I != Pred->end(); ++I)
+ Insts.push_back(&*I);
+ // There is no need to inform IB what previously used values are if we are
+ // using `onlyType`
+ Src = IB.findOrCreateSource(*Pred, Insts, {}, fuzzerop::onlyType(Ty));
+ IncomingValues[Pred] = Src;
+ }
+ PHI->addIncoming(Src, Pred);
+ }
+ SmallVector<Instruction *, 32> InstsAfter;
+ for (auto I = BB.getFirstInsertionPt(), E = BB.end(); I != E; ++I)
+ InstsAfter.push_back(&*I);
+ IB.connectToSink(BB, InstsAfter, PHI);
+}
+
void SinkInstructionStrategy::mutate(Function &F, RandomIRBuilder &IB) {
for (BasicBlock &BB : F) {
this->mutate(BB, IB);
diff --git a/llvm/lib/FuzzMutate/RandomIRBuilder.cpp b/llvm/lib/FuzzMutate/RandomIRBuilder.cpp
index 0aa73340e1f8d..d3574e1770d3b 100644
--- a/llvm/lib/FuzzMutate/RandomIRBuilder.cpp
+++ b/llvm/lib/FuzzMutate/RandomIRBuilder.cpp
@@ -169,3 +169,8 @@ Value *RandomIRBuilder::findPointer(BasicBlock &BB,
return RS.getSelection();
return nullptr;
}
+
+Type *RandomIRBuilder::randomType() {
+ uint64_t TyIdx = uniform<uint64_t>(Rand, 0, KnownTypes.size() - 1);
+ return KnownTypes[TyIdx];
+}
diff --git a/llvm/unittests/FuzzMutate/StrategiesTest.cpp b/llvm/unittests/FuzzMutate/StrategiesTest.cpp
index c720bd03530db..3be9d565d1547 100644
--- a/llvm/unittests/FuzzMutate/StrategiesTest.cpp
+++ b/llvm/unittests/FuzzMutate/StrategiesTest.cpp
@@ -12,6 +12,7 @@
#include "llvm/AsmParser/SlotMapping.h"
#include "llvm/FuzzMutate/IRMutator.h"
#include "llvm/FuzzMutate/Operations.h"
+#include "llvm/FuzzMutate/RandomIRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
@@ -310,6 +311,72 @@ TEST(InstModificationIRStrategyTest, DidntShuffleFRem) {
VerfyDivDidntShuffle(Source);
}
+TEST(InsertPHIStrategy, PHI) {
+ LLVMContext Ctx;
+ StringRef Source = "\n\
+ define void @test(i1 %C1, i1 %C2, i32 %I, double %FP) { \n\
+ Entry: \n\
+ %C = and i1 %C1, %C2 \n\
+ br i1 %C, label %LoopHead, label %Exit \n\
+ LoopHead: ; pred Entry, LoopBody \n\
+ switch i32 %I, label %Default [ \n\
+ i32 1, label %OnOne \n\
+ i32 2, label %OnTwo \n\
+ i32 3, label %OnThree \n\
+ ] \n\
+ Default: \n\
+ br label %LoopBody \n\
+ OnOne: ; pred LoopHead \n\
+ %DFP = fmul double %FP, 2.0 \n\
+ %OnOneCond = fcmp ogt double %DFP, %FP \n\
+ br i1 %OnOneCond, label %LoopBody, label %Exit \n\
+ OnTwo: ; pred Entry \n\
+ br i1 %C1, label %OnThree, label %LoopBody \n\
+ OnThree: ; pred Entry, OnTwo, OnThree \n\
+ br i1 %C2, label %OnThree, label %LoopBody \n\
+ LoopBody: ; pred Default, OnOne, OnTwo, OnThree \n\
+ br label %LoopHead \n\
+ Exit: ; pred Entry, OnOne \n\
+ ret void \n\
+ }";
+ auto Mutator = createMutator<InsertPHIStrategy>();
+ 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 < 100; i++) {
+ Mutator->mutateModule(*M, RandInt(mt), Source.size(), Source.size() + 1024);
+ ASSERT_FALSE(verifyModule(*M, &errs()));
+ }
+}
+
+TEST(InsertPHIStrategy, PHIWithSameIncomingBlock) {
+ LLVMContext Ctx;
+ StringRef Source = "\n\
+ define void @test(i32 %I) { \n\
+ Entry: \n\
+ switch i32 %I, label %Exit [ \n\
+ i32 1, label %IdentCase \n\
+ i32 2, label %IdentCase \n\
+ i32 3, label %IdentCase \n\
+ i32 4, label %IdentCase \n\
+ ] \n\
+ IdentCase: \n\
+ br label %Exit \n\
+ Exit: \n\
+ ret void \n\
+ }";
+ auto IPS = std::make_unique<InsertPHIStrategy>();
+ RandomIRBuilder IB(Seed, {IntegerType::getInt32Ty(Ctx)});
+ auto M = parseAssembly(Source.data(), Ctx);
+ Function &F = *M->begin();
+ for (auto &BB : F) {
+ IPS->mutate(BB, IB);
+ ASSERT_FALSE(verifyModule(*M, &errs()));
+ }
+}
+
TEST(SinkInstructionStrategy, Operand) {
LLVMContext Ctx;
StringRef Source = "\n\
More information about the llvm-commits
mailing list