[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