[FuzzMutate] Update InstModifierStrategy
We can randomly switch two operands of an instruction now Signed-off-by: Peter Rong <PeterRong96@gmail.com>
This commit is contained in:
parent
06e2b44c46
commit
23481bfe5a
|
@ -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()();
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue