Skip to content

Commit 67162d1

Browse files
committed
[FuzzMutate] Properly handle intrinsics and avoid illegal code generation
1 parent 7360ed0 commit 67162d1

File tree

2 files changed

+63
-4
lines changed

2 files changed

+63
-4
lines changed

llvm/lib/FuzzMutate/IRMutator.cpp

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include "llvm/IR/Function.h"
2121
#include "llvm/IR/InstIterator.h"
2222
#include "llvm/IR/Instructions.h"
23+
#include "llvm/IR/IntrinsicInst.h"
24+
#include "llvm/IR/IntrinsicsAMDGPU.h"
2325
#include "llvm/IR/Module.h"
2426
#include "llvm/IR/Operator.h"
2527
#include "llvm/IR/PassInstrumentation.h"
@@ -115,9 +117,41 @@ InjectorIRStrategy::chooseOperation(Value *Src, RandomIRBuilder &IB) {
115117
return *RS;
116118
}
117119

120+
static inline Instruction *getEffectiveTerminator(BasicBlock &BB) {
121+
if (Instruction *I = BB.getTerminatingMustTailCall()) {
122+
return I;
123+
} else {
124+
// Certain intrinsics, such as @llvm.amdgcn.cs.chain, must be immediately
125+
// followed by an unreachable instruction..
126+
if (UnreachableInst *UI = dyn_cast<UnreachableInst>(BB.getTerminator())) {
127+
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(UI->getPrevNode())) {
128+
return II;
129+
}
130+
}
131+
}
132+
133+
return BB.getTerminator();
134+
}
135+
136+
static inline BasicBlock::iterator getEndIterator(BasicBlock &BB) {
137+
auto End = BB.end();
138+
139+
if (BB.empty()) {
140+
return End;
141+
}
142+
143+
Instruction *EffectiveTerminator = getEffectiveTerminator(BB);
144+
if (EffectiveTerminator != BB.getTerminator()) {
145+
// Adjust range for special cases such as tail call.
146+
End = std::prev(BB.end());
147+
}
148+
149+
return End;
150+
}
151+
118152
static inline iterator_range<BasicBlock::iterator>
119153
getInsertionRange(BasicBlock &BB) {
120-
auto End = BB.getTerminatingMustTailCall() ? std::prev(BB.end()) : BB.end();
154+
auto End = getEndIterator(BB);
121155
return make_range(BB.getFirstInsertionPt(), End);
122156
}
123157

@@ -409,6 +443,12 @@ static bool isUnsupportedFunction(Function *F) {
409443
return true;
410444
}
411445

446+
// This intrinsic has specific requirements for its parameters and the caller
447+
// must adhere to certain calling conventions.
448+
if (F->isIntrinsic() && F->getIntrinsicID() == Intrinsic::amdgcn_cs_chain) {
449+
return true;
450+
}
451+
412452
return false;
413453
}
414454

@@ -641,8 +681,9 @@ void ShuffleBlockStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {
641681
std::map<size_t, Instruction *> AliveInsts;
642682
std::map<Instruction *, size_t> AliveInstsLookup;
643683
size_t InsertIdx = 0;
644-
for (auto &I : make_early_inc_range(make_range(
645-
BB.getFirstInsertionPt(), BB.getTerminator()->getIterator()))) {
684+
for (auto &I : make_early_inc_range(
685+
make_range(BB.getFirstInsertionPt(),
686+
getEffectiveTerminator(BB)->getIterator()))) {
646687
// First gather all instructions that can be shuffled. Don't take
647688
// terminator.
648689
AliveInsts.insert({InsertIdx, &I});
@@ -702,7 +743,7 @@ void ShuffleBlockStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {
702743
}
703744
}
704745

705-
Instruction *Terminator = BB.getTerminator();
746+
Instruction *Terminator = getEffectiveTerminator(BB);
706747
// Then put instructions back.
707748
for (Instruction *I : Insts) {
708749
I->insertBefore(Terminator->getIterator());

llvm/unittests/FuzzMutate/StrategiesTest.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,4 +745,22 @@ TEST(AllStrategies, SkipEHPad) {
745745
mutateAndVerifyModule<InjectorIRStrategy>(Source);
746746
mutateAndVerifyModule<InstModificationIRStrategy>(Source);
747747
}
748+
749+
TEST(AllStrategies, SpecialTerminator) {
750+
StringRef Source = "\n\
751+
declare amdgpu_cs_chain void @callee(<3 x i32> inreg, { i32, ptr addrspace(5), i32, i32 })\n\
752+
define amdgpu_cs_chain void @chain_to_chain(<3 x i32> inreg %sgpr, { i32, ptr addrspace(5), i32, i32 } %vgpr) {\n\
753+
call void(ptr, i64, <3 x i32>, { i32, ptr addrspace(5), i32, i32 }, i32, ...) @llvm.amdgcn.cs.chain(ptr @callee, i64 -1, <3 x i32> inreg %sgpr, { i32, ptr addrspace(5), i32, i32 } %vgpr, i32 0) \n\
754+
unreachable\n\
755+
}\n\
756+
";
757+
mutateAndVerifyModule<InjectorIRStrategy>(Source);
758+
mutateAndVerifyModule<InsertCFGStrategy>(Source);
759+
mutateAndVerifyModule<InsertFunctionStrategy>(Source);
760+
mutateAndVerifyModule<InsertPHIStrategy>(Source);
761+
mutateAndVerifyModule<InstModificationIRStrategy>(Source);
762+
mutateAndVerifyModule<ShuffleBlockStrategy>(Source);
763+
mutateAndVerifyModule<SinkInstructionStrategy>(Source);
764+
}
765+
748766
} // namespace

0 commit comments

Comments
 (0)