Skip to content

Commit 1d6c697

Browse files
committed
Add early-exit AMDGPU loop fuzzing
1 parent d94e0a1 commit 1d6c697

2 files changed

Lines changed: 40 additions & 10 deletions

File tree

‎amdgpu/README.md‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ structured two-way branches, wider multi-way switches, and deeper bounded
2323
nested acyclic subgraphs with `i32` phi joins. It also generates counted loops
2424
with small bounded constant or dynamically masked trip counts whose bodies can
2525
contain nested diamonds and switches. Some generated loops carry two independent
26-
`i32` accumulator phis and combine them after the loop, so corpus entries
27-
exercise both expression simplification and CFG and loop transforms. CFG arms
28-
include the same scalar integer, bit, boolean, narrowing, saturating,
29-
funnel-shift, and vector expression families as the linear mutator.
26+
`i32` accumulator phis, combine them after the loop, or take a guarded early
27+
exit from the loop body through an exit phi, so corpus entries exercise both
28+
expression simplification and CFG and loop transforms. CFG arms include the same
29+
scalar integer, bit, boolean, narrowing, saturating, funnel-shift, and vector
30+
expression families as the linear mutator.
3031
Corpus files can be inspected directly with `opt -S corpus-entry -o -`.
3132

3233
## Requirements

‎amdgpu/fuzzer/llvm_amdgpu_diff_fuzzer.cpp‎

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2192,6 +2192,7 @@ void mutateIRAddCountedLoop(Module &M, std::minstd_rand &Gen) {
21922192
Value *Current = Store->getValueOperand();
21932193
Value *Other = chooseI32Value(Store, Gen);
21942194
bool UseSecondAccumulator = (Gen() % 3) == 0;
2195+
bool UseEarlyExit = (Gen() % 4) == 0;
21952196

21962197
BasicBlock *Preheader = Store->getParent();
21972198
BasicBlock *Exit =
@@ -2242,16 +2243,44 @@ void mutateIRAddCountedLoop(Module &M, std::minstd_rand &Gen) {
22422243
"fuzz.loop.acc2.mix");
22432244
}
22442245

2245-
IRBuilder<NoFolder> BodyTailB(FinalFrag.Tail);
2246+
Value *NextAcc = BodyFrag.Result;
2247+
Value *BreakValue = nullptr;
2248+
BasicBlock *Backedge = FinalFrag.Tail;
2249+
if (UseEarlyExit) {
2250+
IRBuilder<NoFolder> BreakB(FinalFrag.Tail);
2251+
BreakValue = NextAcc;
2252+
if (Acc2)
2253+
BreakValue =
2254+
BreakB.CreateAdd(NextAcc, NextAcc2, "fuzz.loop.break.value");
2255+
Value *BreakCond = BreakB.CreateICmp(randomICmpPredicate(Gen), BreakValue,
2256+
chooseCFGValue(Ctx, Other, Gen),
2257+
"fuzz.loop.break");
2258+
Backedge = BasicBlock::Create(Ctx, "fuzz.loop.continue", F, Exit);
2259+
BreakB.CreateCondBr(BreakCond, Exit, Backedge);
2260+
}
2261+
2262+
IRBuilder<NoFolder> BodyTailB(Backedge);
22462263
Value *NextIndex =
22472264
BodyTailB.CreateAdd(Index, ci32(Ctx, 1), "fuzz.loop.next");
22482265
BodyTailB.CreateBr(Header);
2249-
Index->addIncoming(NextIndex, FinalFrag.Tail);
2250-
Acc->addIncoming(BodyFrag.Result, FinalFrag.Tail);
2266+
Index->addIncoming(NextIndex, Backedge);
2267+
Acc->addIncoming(NextAcc, Backedge);
22512268
if (Acc2)
2252-
Acc2->addIncoming(NextAcc2, FinalFrag.Tail);
2253-
2254-
if (Acc2) {
2269+
Acc2->addIncoming(NextAcc2, Backedge);
2270+
2271+
if (UseEarlyExit) {
2272+
Value *NaturalExitValue = Acc;
2273+
if (Acc2) {
2274+
IRBuilder<NoFolder> HeaderExitB(Header->getTerminator());
2275+
NaturalExitValue =
2276+
HeaderExitB.CreateAdd(Acc, Acc2, "fuzz.loop.natural.value");
2277+
}
2278+
PHINode *ExitValue =
2279+
PHINode::Create(I32, 2, "fuzz.loop.exit.value", Exit->begin());
2280+
ExitValue->addIncoming(NaturalExitValue, Header);
2281+
ExitValue->addIncoming(BreakValue, FinalFrag.Tail);
2282+
Store->setOperand(0, ExitValue);
2283+
} else if (Acc2) {
22552284
IRBuilder<NoFolder> ExitB(Store);
22562285
Value *Mixed = ExitB.CreateAdd(Acc, Acc2, "fuzz.loop.acc.mix");
22572286
Store->setOperand(0, Mixed);

0 commit comments

Comments
 (0)