[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