[llvm] 80760e9 - [FuzzMutate] InstModificationStrategy, add FastMath flags and exact flags to instructions.

Peter Rong via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 12 15:22:19 PST 2022


Author: Peter Rong
Date: 2022-12-12T15:22:13-08:00
New Revision: 80760e91746ec44b49fcfea4c44bf768b845c64d

URL: https://github.com/llvm/llvm-project/commit/80760e91746ec44b49fcfea4c44bf768b845c64d
DIFF: https://github.com/llvm/llvm-project/commit/80760e91746ec44b49fcfea4c44bf768b845c64d.diff

LOG: [FuzzMutate] InstModificationStrategy, add FastMath flags and exact flags to instructions.

I think there are more attributes, flags we can add to `call`, functions declarations and global variables. Let's start with these two flags.

Reviewed By: arsenm

Differential Revision: https://reviews.llvm.org/D139594

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 cb4717c6d30f8..6c0c2ddc0d6c1 100644
--- a/llvm/lib/FuzzMutate/IRMutator.cpp
+++ b/llvm/lib/FuzzMutate/IRMutator.cpp
@@ -17,10 +17,12 @@
 #include "llvm/FuzzMutate/Random.h"
 #include "llvm/FuzzMutate/RandomIRBuilder.h"
 #include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/FMF.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/InstIterator.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Module.h"
+#include "llvm/IR/Operator.h"
 #include "llvm/IR/Verifier.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/SourceMgr.h"
@@ -217,6 +219,7 @@ void InstModificationIRStrategy::mutate(Instruction &Inst,
   switch (Inst.getOpcode()) {
   default:
     break;
+  // Add nsw, nuw flag
   case Instruction::Add:
   case Instruction::Mul:
   case Instruction::Sub:
@@ -225,26 +228,60 @@ void InstModificationIRStrategy::mutate(Instruction &Inst,
     Modifications.push_back([&Inst]() { Inst.setHasNoSignedWrap(false); });
     Modifications.push_back([&Inst]() { Inst.setHasNoUnsignedWrap(true); });
     Modifications.push_back([&Inst]() { Inst.setHasNoUnsignedWrap(false); });
-
     break;
   case Instruction::ICmp:
     CI = cast<ICmpInst>(&Inst);
-    Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_EQ); });
-    Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_NE); });
-    Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_UGT); });
-    Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_UGE); });
-    Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_ULT); });
-    Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_ULE); });
-    Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_SGT); });
-    Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_SGE); });
-    Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_SLT); });
-    Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_SLE); });
+    for (unsigned p = CmpInst::FIRST_ICMP_PREDICATE;
+         p <= CmpInst::LAST_ICMP_PREDICATE; p++) {
+      Modifications.push_back(
+          [CI, p]() { CI->setPredicate(static_cast<CmpInst::Predicate>(p)); });
+    }
     break;
+  // Add inbound flag.
   case Instruction::GetElementPtr:
     GEP = cast<GetElementPtrInst>(&Inst);
     Modifications.push_back([GEP]() { GEP->setIsInBounds(true); });
     Modifications.push_back([GEP]() { GEP->setIsInBounds(false); });
     break;
+  // Add exact flag.
+  case Instruction::UDiv:
+  case Instruction::SDiv:
+  case Instruction::LShr:
+  case Instruction::AShr:
+    Modifications.push_back([&Inst] { Inst.setIsExact(!Inst.isExact()); });
+    break;
+
+  case Instruction::FCmp:
+    CI = cast<ICmpInst>(&Inst);
+    for (unsigned p = CmpInst::FIRST_FCMP_PREDICATE;
+         p <= CmpInst::LAST_FCMP_PREDICATE; p++) {
+      Modifications.push_back(
+          [CI, p]() { CI->setPredicate(static_cast<CmpInst::Predicate>(p)); });
+    }
+    break;
+  }
+
+  // Add fast math flag if possible.
+  if (isa<FPMathOperator>(&Inst)) {
+    // Try setting everything unless they are already on.
+    Modifications.push_back(
+        [&Inst] { Inst.setFast(!Inst.getFastMathFlags().all()); });
+    // Try unsetting everything unless they are already off.
+    Modifications.push_back(
+        [&Inst] { Inst.setFast(!Inst.getFastMathFlags().none()); });
+    // Individual setting by flipping the bit
+    Modifications.push_back(
+        [&Inst] { Inst.setHasAllowReassoc(!Inst.hasAllowReassoc()); });
+    Modifications.push_back([&Inst] { Inst.setHasNoNaNs(!Inst.hasNoNaNs()); });
+    Modifications.push_back([&Inst] { Inst.setHasNoInfs(!Inst.hasNoInfs()); });
+    Modifications.push_back(
+        [&Inst] { Inst.setHasNoSignedZeros(!Inst.hasNoSignedZeros()); });
+    Modifications.push_back(
+        [&Inst] { Inst.setHasAllowReciprocal(!Inst.hasAllowReciprocal()); });
+    Modifications.push_back(
+        [&Inst] { Inst.setHasAllowContract(!Inst.hasAllowContract()); });
+    Modifications.push_back(
+        [&Inst] { Inst.setHasApproxFunc(!Inst.hasApproxFunc()); });
   }
 
   // Randomly switch operands of instructions

diff  --git a/llvm/unittests/FuzzMutate/StrategiesTest.cpp b/llvm/unittests/FuzzMutate/StrategiesTest.cpp
index 68a7676e28963..9208a9b45fb1c 100644
--- a/llvm/unittests/FuzzMutate/StrategiesTest.cpp
+++ b/llvm/unittests/FuzzMutate/StrategiesTest.cpp
@@ -13,6 +13,7 @@
 #include "llvm/FuzzMutate/IRMutator.h"
 #include "llvm/FuzzMutate/Operations.h"
 #include "llvm/FuzzMutate/RandomIRBuilder.h"
+#include "llvm/IR/FMF.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
@@ -249,27 +250,27 @@ void VerfyOperandShuffled(StringRef Source, std::pair<int, int> ShuffleItems) {
               dyn_cast<Value>(F.getArg(ShuffleItems.second)));
 
   Mutator->mutateModule(*M, 0, Source.size(), Source.size() + 100);
-  EXPECT_TRUE(!verifyModule(*M, &errs()));
+  ASSERT_TRUE(!verifyModule(*M, &errs()));
 
-  EXPECT_TRUE(Inst->getOperand(ShuffleItems.first) ==
+  ASSERT_TRUE(Inst->getOperand(ShuffleItems.first) ==
               dyn_cast<Value>(F.getArg(ShuffleItems.second)));
-  EXPECT_TRUE(Inst->getOperand(ShuffleItems.second) ==
+  ASSERT_TRUE(Inst->getOperand(ShuffleItems.second) ==
               dyn_cast<Value>(F.getArg(ShuffleItems.first)));
 }
 
-TEST(InstModificationIRStrategyTest, ShuffleFAdd) {
+TEST(InstModificationIRStrategyTest, ShuffleAnd) {
   StringRef Source = "\n\
-      define float @test(float %0, float %1) {\n\
-        %add = fadd float %0, %1\n\
-        ret float %add\n\
+      define i32 @test(i32 %0, i32 %1) {\n\
+        %add = and i32 %0, %1\n\
+        ret i32 %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\
+      define i32 @test(i1 %0, i32 %1, i32 %2) {\n\
+        %select = select i1 %0, i32 %1, i32 %2\n\
+        ret i32 %select\n\
       }";
   VerfyOperandShuffled(Source, {1, 2});
 }
@@ -310,6 +311,79 @@ TEST(InstModificationIRStrategyTest, DidntShuffleFRem) {
       }";
   VerfyDivDidntShuffle(Source);
 }
+TEST(InstModificationIRStrategy, Exact) {
+  LLVMContext Ctx;
+  StringRef Source = "\n\
+      define i32 @test(i32 %a, i32 %b) {\n\
+        %c = ashr i32 %a, %b \n\
+        ret i32 %c\n\
+      }";
+
+  auto Mutator = createMutator<InstModificationIRStrategy>();
+  ASSERT_TRUE(Mutator);
+
+  std::unique_ptr<Module> M = parseAssembly(Source.data(), Ctx);
+  std::mt19937 mt(Seed);
+  std::uniform_int_distribution<int> RandInt(INT_MIN, INT_MAX);
+  auto &F = *M->begin();
+  BinaryOperator *AShr = cast<BinaryOperator>(&*F.begin()->begin());
+  bool FoundExact = false;
+  for (int i = 0; i < 100; ++i) {
+    Mutator->mutateModule(*M, RandInt(mt), Source.size(), Source.size() + 100);
+    ASSERT_FALSE(verifyModule(*M, &errs()));
+    FoundExact |= AShr->isExact();
+  }
+
+  EXPECT_TRUE(FoundExact);
+}
+TEST(InstModificationIRStrategy, FastMath) {
+  LLVMContext Ctx;
+  StringRef Source = "\n\
+      declare [4 x <4 x double>] @vecdouble(double)  \n\
+      define double @test(i1 %C, double %a, double %b) {  \n\
+      Entry:  \n\
+        br i1 %C, label %True, label %False  \n\
+      True:  \n\
+        br label %Exit  \n\
+      False:  \n\
+        br label %Exit  \n\
+      Exit:  \n\
+        %PHIi32 = phi i32 [1, %True], [2, %False]  \n\
+        %PHIdouble = phi double [%a, %True], [%b, %False]  \n\
+        %Call = call [4 x <4 x double>] @vecdouble(double %PHIdouble)  \n\
+        %c = fneg double %PHIdouble  \n\
+        %s = select i1 %C, double %a, double %b  \n\
+        %d = fadd double %s, %c  \n\
+        ret double %d \n\
+      }";
+
+  auto Mutator = createMutator<InstModificationIRStrategy>();
+  ASSERT_TRUE(Mutator);
+
+  std::unique_ptr<Module> M = parseAssembly(Source.data(), Ctx);
+  std::mt19937 mt(Seed);
+  std::uniform_int_distribution<int> RandInt(INT_MIN, INT_MAX);
+  DenseMap<Instruction *, bool> FPOpsHasFastMath;
+  for (auto &F : *M) {
+    for (auto &BB : F) {
+      for (auto &I : BB) {
+        Type *Ty = I.getType();
+        if (Ty->isFPOrFPVectorTy() || Ty->isArrayTy()) {
+          FPOpsHasFastMath[&I] = false;
+        }
+      }
+    }
+  }
+  ASSERT_TRUE(M && !verifyModule(*M, &errs()));
+  for (int i = 0; i < 300; ++i) {
+    Mutator->mutateModule(*M, RandInt(mt), Source.size(), Source.size() + 100);
+    for (auto p : FPOpsHasFastMath)
+      FPOpsHasFastMath[p.first] |= p.first->getFastMathFlags().any();
+    ASSERT_FALSE(verifyModule(*M, &errs()));
+  }
+  for (auto p : FPOpsHasFastMath)
+    ASSERT_TRUE(p.second);
+}
 
 template <class Strategy>
 static void mutateAndVerifyModule(StringRef Source, int repeat = 100) {


        


More information about the llvm-commits mailing list