Skip to content

Commit 23481bf

Browse files
committed
[FuzzMutate] Update InstModifierStrategy
We can randomly switch two operands of an instruction now Signed-off-by: Peter Rong <PeterRong96@gmail.com>
1 parent 06e2b44 commit 23481bf

File tree

2 files changed

+136
-20
lines changed

2 files changed

+136
-20
lines changed

llvm/lib/FuzzMutate/IRMutator.cpp

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,8 @@ void InstModificationIRStrategy::mutate(Instruction &Inst,
218218
case Instruction::Mul:
219219
case Instruction::Sub:
220220
case Instruction::Shl:
221-
Modifications.push_back([&Inst]() { Inst.setHasNoSignedWrap(true); }),
222-
Modifications.push_back([&Inst]() { Inst.setHasNoSignedWrap(false); });
221+
Modifications.push_back([&Inst]() { Inst.setHasNoSignedWrap(true); });
222+
Modifications.push_back([&Inst]() { Inst.setHasNoSignedWrap(false); });
223223
Modifications.push_back([&Inst]() { Inst.setHasNoUnsignedWrap(true); });
224224
Modifications.push_back([&Inst]() { Inst.setHasNoUnsignedWrap(false); });
225225

@@ -244,6 +244,54 @@ void InstModificationIRStrategy::mutate(Instruction &Inst,
244244
break;
245245
}
246246

247+
// Randomly switch operands of instructions
248+
std::pair<int, int> NoneItem({-1, -1}), ShuffleItems(NoneItem);
249+
switch (Inst.getOpcode()) {
250+
case Instruction::SDiv:
251+
case Instruction::UDiv:
252+
case Instruction::SRem:
253+
case Instruction::URem:
254+
case Instruction::FDiv:
255+
case Instruction::FRem: {
256+
// Verify that the after shuffle the second operand is not
257+
// constant 0.
258+
Value *Operand = Inst.getOperand(0);
259+
if (Constant *C = dyn_cast<Constant>(Operand)) {
260+
if (!C->isZeroValue()) {
261+
ShuffleItems = {0, 1};
262+
}
263+
}
264+
break;
265+
}
266+
case Instruction::Select:
267+
ShuffleItems = {1, 2};
268+
break;
269+
case Instruction::Add:
270+
case Instruction::Sub:
271+
case Instruction::Mul:
272+
case Instruction::Shl:
273+
case Instruction::LShr:
274+
case Instruction::AShr:
275+
case Instruction::And:
276+
case Instruction::Or:
277+
case Instruction::Xor:
278+
case Instruction::FAdd:
279+
case Instruction::FSub:
280+
case Instruction::FMul:
281+
case Instruction::ICmp:
282+
case Instruction::FCmp:
283+
case Instruction::ShuffleVector:
284+
ShuffleItems = {0, 1};
285+
break;
286+
}
287+
if (ShuffleItems != NoneItem) {
288+
Modifications.push_back([&Inst, &ShuffleItems]() {
289+
Value *Op0 = Inst.getOperand(ShuffleItems.first);
290+
Inst.setOperand(ShuffleItems.first, Inst.getOperand(ShuffleItems.second));
291+
Inst.setOperand(ShuffleItems.second, Op0);
292+
});
293+
}
294+
247295
auto RS = makeSampler(IB.Rand, Modifications);
248296
if (RS)
249297
RS.getSelection()();

llvm/unittests/FuzzMutate/StrategiesTest.cpp

Lines changed: 86 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,24 +37,13 @@ std::unique_ptr<IRMutator> createInjectorMutator() {
3737
return std::make_unique<IRMutator>(std::move(Types), std::move(Strategies));
3838
}
3939

40-
std::unique_ptr<IRMutator> createDeleterMutator() {
40+
template <class Strategy> std::unique_ptr<IRMutator> createMutator() {
4141
std::vector<TypeGetter> Types{
4242
Type::getInt1Ty, Type::getInt8Ty, Type::getInt16Ty, Type::getInt32Ty,
4343
Type::getInt64Ty, Type::getFloatTy, Type::getDoubleTy};
4444

4545
std::vector<std::unique_ptr<IRMutationStrategy>> Strategies;
46-
Strategies.push_back(std::make_unique<InstDeleterIRStrategy>());
47-
48-
return std::make_unique<IRMutator>(std::move(Types), std::move(Strategies));
49-
}
50-
51-
std::unique_ptr<IRMutator> createInstModifierMutator() {
52-
std::vector<TypeGetter> Types{
53-
Type::getInt1Ty, Type::getInt8Ty, Type::getInt16Ty, Type::getInt32Ty,
54-
Type::getInt64Ty, Type::getFloatTy, Type::getDoubleTy};
55-
56-
std::vector<std::unique_ptr<IRMutationStrategy>> Strategies;
57-
Strategies.push_back(std::make_unique<InstModificationIRStrategy>());
46+
Strategies.push_back(std::make_unique<Strategy>());
5847

5948
return std::make_unique<IRMutator>(std::move(Types), std::move(Strategies));
6049
}
@@ -113,7 +102,7 @@ TEST(InstDeleterIRStrategyTest, EmptyFunction) {
113102
"ret i32 %L6\n"
114103
"}\n";
115104

116-
auto Mutator = createDeleterMutator();
105+
auto Mutator = createMutator<InstDeleterIRStrategy>();
117106
ASSERT_TRUE(Mutator);
118107

119108
IterateOnSource(Source, *Mutator);
@@ -139,7 +128,7 @@ TEST(InstDeleterIRStrategyTest, PhiNodes) {
139128
ret i32 %a.0\n\
140129
}";
141130

142-
auto Mutator = createDeleterMutator();
131+
auto Mutator = createMutator<InstDeleterIRStrategy>();
143132
ASSERT_TRUE(Mutator);
144133

145134
IterateOnSource(Source, *Mutator);
@@ -154,7 +143,7 @@ static void checkModifyNoUnsignedAndNoSignedWrap(StringRef Opc) {
154143
ret i32 %a\n\
155144
}");
156145

157-
auto Mutator = createInstModifierMutator();
146+
auto Mutator = createMutator<InstModificationIRStrategy>();
158147
ASSERT_TRUE(Mutator);
159148

160149
auto M = parseAssembly(Source.data(), Ctx);
@@ -198,7 +187,7 @@ TEST(InstModificationIRStrategyTest, ICmp) {
198187
ret i1 %a\n\
199188
}";
200189

201-
auto Mutator = createInstModifierMutator();
190+
auto Mutator = createMutator<InstModificationIRStrategy>();
202191
ASSERT_TRUE(Mutator);
203192

204193
auto M = parseAssembly(Source.data(), Ctx);
@@ -223,7 +212,7 @@ TEST(InstModificationIRStrategyTest, GEP) {
223212
ret i32* %gep\n\
224213
}";
225214

226-
auto Mutator = createInstModifierMutator();
215+
auto Mutator = createMutator<InstModificationIRStrategy>();
227216
ASSERT_TRUE(Mutator);
228217

229218
auto M = parseAssembly(Source.data(), Ctx);
@@ -239,4 +228,83 @@ TEST(InstModificationIRStrategyTest, GEP) {
239228

240229
EXPECT_TRUE(FoundInbounds);
241230
}
231+
232+
/// The caller has to guarantee that function argument are used in the SAME
233+
/// place as the operand.
234+
void VerfyOperandShuffled(StringRef Source, std::pair<int, int> ShuffleItems) {
235+
LLVMContext Ctx;
236+
auto Mutator = createMutator<InstModificationIRStrategy>();
237+
ASSERT_TRUE(Mutator);
238+
239+
auto M = parseAssembly(Source.data(), Ctx);
240+
auto &F = *M->begin();
241+
Instruction *Inst = &*F.begin()->begin();
242+
ASSERT_TRUE(M && !verifyModule(*M, &errs()));
243+
ASSERT_TRUE(Inst->getOperand(ShuffleItems.first) ==
244+
dyn_cast<Value>(F.getArg(ShuffleItems.first)));
245+
ASSERT_TRUE(Inst->getOperand(ShuffleItems.second) ==
246+
dyn_cast<Value>(F.getArg(ShuffleItems.second)));
247+
248+
Mutator->mutateModule(*M, 0, Source.size(), Source.size() + 100);
249+
EXPECT_TRUE(!verifyModule(*M, &errs()));
250+
251+
EXPECT_TRUE(Inst->getOperand(ShuffleItems.first) ==
252+
dyn_cast<Value>(F.getArg(ShuffleItems.second)));
253+
EXPECT_TRUE(Inst->getOperand(ShuffleItems.second) ==
254+
dyn_cast<Value>(F.getArg(ShuffleItems.first)));
255+
}
256+
257+
TEST(InstModificationIRStrategyTest, ShuffleFAdd) {
258+
StringRef Source = "\n\
259+
define float @test(float %0, float %1) {\n\
260+
%add = fadd float %0, %1\n\
261+
ret float %add\n\
262+
}";
263+
VerfyOperandShuffled(Source, {0, 1});
264+
}
265+
TEST(InstModificationIRStrategyTest, ShuffleSelect) {
266+
StringRef Source = "\n\
267+
define float @test(i1 %0, float %1, float %2) {\n\
268+
%select = select i1 %0, float %1, float %2\n\
269+
ret float %select\n\
270+
}";
271+
VerfyOperandShuffled(Source, {1, 2});
272+
}
273+
274+
void VerfyDivDidntShuffle(StringRef Source) {
275+
LLVMContext Ctx;
276+
auto Mutator = createMutator<InstModificationIRStrategy>();
277+
ASSERT_TRUE(Mutator);
278+
279+
auto M = parseAssembly(Source.data(), Ctx);
280+
auto &F = *M->begin();
281+
Instruction *Inst = &*F.begin()->begin();
282+
ASSERT_TRUE(M && !verifyModule(*M, &errs()));
283+
284+
EXPECT_TRUE(isa<Constant>(Inst->getOperand(0)));
285+
EXPECT_TRUE(Inst->getOperand(1) == dyn_cast<Value>(F.getArg(0)));
286+
287+
Mutator->mutateModule(*M, Seed, Source.size(), Source.size() + 100);
288+
EXPECT_TRUE(!verifyModule(*M, &errs()));
289+
290+
// Didn't shuffle.
291+
EXPECT_TRUE(isa<Constant>(Inst->getOperand(0)));
292+
EXPECT_TRUE(Inst->getOperand(1) == dyn_cast<Value>(F.getArg(0)));
293+
}
294+
TEST(InstModificationIRStrategyTest, DidntShuffleSDiv) {
295+
StringRef Source = "\n\
296+
define i32 @test(i32 %0) {\n\
297+
%div = sdiv i32 0, %0\n\
298+
ret i32 %div\n\
299+
}";
300+
VerfyDivDidntShuffle(Source);
301+
}
302+
TEST(InstModificationIRStrategyTest, DidntShuffleFRem) {
303+
StringRef Source = "\n\
304+
define <2 x double> @test(<2 x double> %0) {\n\
305+
%div = frem <2 x double> <double 0.0, double 0.0>, %0\n\
306+
ret <2 x double> %div\n\
307+
}";
308+
VerfyDivDidntShuffle(Source);
309+
}
242310
} // namespace

0 commit comments

Comments
 (0)