[llvm] 23481bf - [FuzzMutate] Update InstModifierStrategy

Peter Rong via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 18 15:57:24 PST 2022


Author: Peter Rong
Date: 2022-11-18T15:54:22-08:00
New Revision: 23481bfe5a09e96931a4712cc236075a3ae3a5c9

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

LOG: [FuzzMutate] Update InstModifierStrategy

We can randomly switch two operands of an instruction now

Signed-off-by: Peter Rong <PeterRong96 at gmail.com>

Added: 
    

Modified: 
    llvm/lib/FuzzMutate/IRMutator.cpp
    llvm/unittests/FuzzMutate/StrategiesTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/FuzzMutate/IRMutator.cpp b/llvm/lib/FuzzMutate/IRMutator.cpp
index a879b09112623..9e4517b91a324 100644
--- a/llvm/lib/FuzzMutate/IRMutator.cpp
+++ b/llvm/lib/FuzzMutate/IRMutator.cpp
@@ -218,8 +218,8 @@ void InstModificationIRStrategy::mutate(Instruction &Inst,
   case Instruction::Mul:
   case Instruction::Sub:
   case Instruction::Shl:
-    Modifications.push_back([&Inst]() { Inst.setHasNoSignedWrap(true); }),
-        Modifications.push_back([&Inst]() { Inst.setHasNoSignedWrap(false); });
+    Modifications.push_back([&Inst]() { Inst.setHasNoSignedWrap(true); });
+    Modifications.push_back([&Inst]() { Inst.setHasNoSignedWrap(false); });
     Modifications.push_back([&Inst]() { Inst.setHasNoUnsignedWrap(true); });
     Modifications.push_back([&Inst]() { Inst.setHasNoUnsignedWrap(false); });
 
@@ -244,6 +244,54 @@ void InstModificationIRStrategy::mutate(Instruction &Inst,
     break;
   }
 
+  // Randomly switch operands of instructions
+  std::pair<int, int> NoneItem({-1, -1}), ShuffleItems(NoneItem);
+  switch (Inst.getOpcode()) {
+  case Instruction::SDiv:
+  case Instruction::UDiv:
+  case Instruction::SRem:
+  case Instruction::URem:
+  case Instruction::FDiv:
+  case Instruction::FRem: {
+    // Verify that the after shuffle the second operand is not
+    // constant 0.
+    Value *Operand = Inst.getOperand(0);
+    if (Constant *C = dyn_cast<Constant>(Operand)) {
+      if (!C->isZeroValue()) {
+        ShuffleItems = {0, 1};
+      }
+    }
+    break;
+  }
+  case Instruction::Select:
+    ShuffleItems = {1, 2};
+    break;
+  case Instruction::Add:
+  case Instruction::Sub:
+  case Instruction::Mul:
+  case Instruction::Shl:
+  case Instruction::LShr:
+  case Instruction::AShr:
+  case Instruction::And:
+  case Instruction::Or:
+  case Instruction::Xor:
+  case Instruction::FAdd:
+  case Instruction::FSub:
+  case Instruction::FMul:
+  case Instruction::ICmp:
+  case Instruction::FCmp:
+  case Instruction::ShuffleVector:
+    ShuffleItems = {0, 1};
+    break;
+  }
+  if (ShuffleItems != NoneItem) {
+    Modifications.push_back([&Inst, &ShuffleItems]() {
+      Value *Op0 = Inst.getOperand(ShuffleItems.first);
+      Inst.setOperand(ShuffleItems.first, Inst.getOperand(ShuffleItems.second));
+      Inst.setOperand(ShuffleItems.second, Op0);
+    });
+  }
+
   auto RS = makeSampler(IB.Rand, Modifications);
   if (RS)
     RS.getSelection()();

diff  --git a/llvm/unittests/FuzzMutate/StrategiesTest.cpp b/llvm/unittests/FuzzMutate/StrategiesTest.cpp
index 3f3f3c56c0386..33aa73eb9ba28 100644
--- a/llvm/unittests/FuzzMutate/StrategiesTest.cpp
+++ b/llvm/unittests/FuzzMutate/StrategiesTest.cpp
@@ -37,24 +37,13 @@ std::unique_ptr<IRMutator> createInjectorMutator() {
   return std::make_unique<IRMutator>(std::move(Types), std::move(Strategies));
 }
 
-std::unique_ptr<IRMutator> createDeleterMutator() {
+template <class Strategy> std::unique_ptr<IRMutator> createMutator() {
   std::vector<TypeGetter> Types{
       Type::getInt1Ty,  Type::getInt8Ty,  Type::getInt16Ty, Type::getInt32Ty,
       Type::getInt64Ty, Type::getFloatTy, Type::getDoubleTy};
 
   std::vector<std::unique_ptr<IRMutationStrategy>> Strategies;
-  Strategies.push_back(std::make_unique<InstDeleterIRStrategy>());
-
-  return std::make_unique<IRMutator>(std::move(Types), std::move(Strategies));
-}
-
-std::unique_ptr<IRMutator> createInstModifierMutator() {
-  std::vector<TypeGetter> Types{
-      Type::getInt1Ty,  Type::getInt8Ty,  Type::getInt16Ty, Type::getInt32Ty,
-      Type::getInt64Ty, Type::getFloatTy, Type::getDoubleTy};
-
-  std::vector<std::unique_ptr<IRMutationStrategy>> Strategies;
-  Strategies.push_back(std::make_unique<InstModificationIRStrategy>());
+  Strategies.push_back(std::make_unique<Strategy>());
 
   return std::make_unique<IRMutator>(std::move(Types), std::move(Strategies));
 }
@@ -113,7 +102,7 @@ TEST(InstDeleterIRStrategyTest, EmptyFunction) {
                      "ret i32 %L6\n"
                      "}\n";
 
-  auto Mutator = createDeleterMutator();
+  auto Mutator = createMutator<InstDeleterIRStrategy>();
   ASSERT_TRUE(Mutator);
 
   IterateOnSource(Source, *Mutator);
@@ -139,7 +128,7 @@ TEST(InstDeleterIRStrategyTest, PhiNodes) {
         ret i32 %a.0\n\
       }";
 
-  auto Mutator = createDeleterMutator();
+  auto Mutator = createMutator<InstDeleterIRStrategy>();
   ASSERT_TRUE(Mutator);
 
   IterateOnSource(Source, *Mutator);
@@ -154,7 +143,7 @@ static void checkModifyNoUnsignedAndNoSignedWrap(StringRef Opc) {
         ret i32 %a\n\
       }");
 
-  auto Mutator = createInstModifierMutator();
+  auto Mutator = createMutator<InstModificationIRStrategy>();
   ASSERT_TRUE(Mutator);
 
   auto M = parseAssembly(Source.data(), Ctx);
@@ -198,7 +187,7 @@ TEST(InstModificationIRStrategyTest, ICmp) {
         ret i1 %a\n\
       }";
 
-  auto Mutator = createInstModifierMutator();
+  auto Mutator = createMutator<InstModificationIRStrategy>();
   ASSERT_TRUE(Mutator);
 
   auto M = parseAssembly(Source.data(), Ctx);
@@ -223,7 +212,7 @@ TEST(InstModificationIRStrategyTest, GEP) {
         ret i32* %gep\n\
       }";
 
-  auto Mutator = createInstModifierMutator();
+  auto Mutator = createMutator<InstModificationIRStrategy>();
   ASSERT_TRUE(Mutator);
 
   auto M = parseAssembly(Source.data(), Ctx);
@@ -239,4 +228,83 @@ TEST(InstModificationIRStrategyTest, GEP) {
 
   EXPECT_TRUE(FoundInbounds);
 }
+
+/// The caller has to guarantee that function argument are used in the SAME
+/// place as the operand.
+void VerfyOperandShuffled(StringRef Source, std::pair<int, int> ShuffleItems) {
+  LLVMContext Ctx;
+  auto Mutator = createMutator<InstModificationIRStrategy>();
+  ASSERT_TRUE(Mutator);
+
+  auto M = parseAssembly(Source.data(), Ctx);
+  auto &F = *M->begin();
+  Instruction *Inst = &*F.begin()->begin();
+  ASSERT_TRUE(M && !verifyModule(*M, &errs()));
+  ASSERT_TRUE(Inst->getOperand(ShuffleItems.first) ==
+              dyn_cast<Value>(F.getArg(ShuffleItems.first)));
+  ASSERT_TRUE(Inst->getOperand(ShuffleItems.second) ==
+              dyn_cast<Value>(F.getArg(ShuffleItems.second)));
+
+  Mutator->mutateModule(*M, 0, Source.size(), Source.size() + 100);
+  EXPECT_TRUE(!verifyModule(*M, &errs()));
+
+  EXPECT_TRUE(Inst->getOperand(ShuffleItems.first) ==
+              dyn_cast<Value>(F.getArg(ShuffleItems.second)));
+  EXPECT_TRUE(Inst->getOperand(ShuffleItems.second) ==
+              dyn_cast<Value>(F.getArg(ShuffleItems.first)));
+}
+
+TEST(InstModificationIRStrategyTest, ShuffleFAdd) {
+  StringRef Source = "\n\
+      define float @test(float %0, float %1) {\n\
+        %add = fadd float %0, %1\n\
+        ret float %add\n\
+      }";
+  VerfyOperandShuffled(Source, {0, 1});
+}
+TEST(InstModificationIRStrategyTest, ShuffleSelect) {
+  StringRef Source = "\n\
+      define float @test(i1 %0, float %1, float %2) {\n\
+        %select = select i1 %0, float %1, float %2\n\
+        ret float %select\n\
+      }";
+  VerfyOperandShuffled(Source, {1, 2});
+}
+
+void VerfyDivDidntShuffle(StringRef Source) {
+  LLVMContext Ctx;
+  auto Mutator = createMutator<InstModificationIRStrategy>();
+  ASSERT_TRUE(Mutator);
+
+  auto M = parseAssembly(Source.data(), Ctx);
+  auto &F = *M->begin();
+  Instruction *Inst = &*F.begin()->begin();
+  ASSERT_TRUE(M && !verifyModule(*M, &errs()));
+
+  EXPECT_TRUE(isa<Constant>(Inst->getOperand(0)));
+  EXPECT_TRUE(Inst->getOperand(1) == dyn_cast<Value>(F.getArg(0)));
+
+  Mutator->mutateModule(*M, Seed, Source.size(), Source.size() + 100);
+  EXPECT_TRUE(!verifyModule(*M, &errs()));
+
+  // Didn't shuffle.
+  EXPECT_TRUE(isa<Constant>(Inst->getOperand(0)));
+  EXPECT_TRUE(Inst->getOperand(1) == dyn_cast<Value>(F.getArg(0)));
+}
+TEST(InstModificationIRStrategyTest, DidntShuffleSDiv) {
+  StringRef Source = "\n\
+      define i32 @test(i32 %0) {\n\
+        %div = sdiv i32 0, %0\n\
+        ret i32 %div\n\
+      }";
+  VerfyDivDidntShuffle(Source);
+}
+TEST(InstModificationIRStrategyTest, DidntShuffleFRem) {
+  StringRef Source = "\n\
+      define <2 x double> @test(<2 x double> %0) {\n\
+        %div = frem <2 x double> <double 0.0, double 0.0>, %0\n\
+        ret <2 x double> %div\n\
+      }";
+  VerfyDivDidntShuffle(Source);
+}
 } // namespace


        


More information about the llvm-commits mailing list