[llvm] [FuzzMutate] Properly handle intrinsics and avoid illegal code genertion (PR #145495)

Manuel Carrasco via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 24 04:56:34 PDT 2025


https://github.com/mgcarrasco updated https://github.com/llvm/llvm-project/pull/145495

>From ee301770e6ab1f2f1d9736aa7daac732e1df14c8 Mon Sep 17 00:00:00 2001
From: Manuel Carrasco <Manuel.Carrasco at amd.com>
Date: Tue, 24 Jun 2025 03:31:39 -0700
Subject: [PATCH] [FuzzMutate] Properly handle intrinsics and avoid illegal
 code generation

---
 llvm/lib/FuzzMutate/IRMutator.cpp            | 49 ++++++++++++++++++--
 llvm/unittests/FuzzMutate/StrategiesTest.cpp | 18 +++++++
 2 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/FuzzMutate/IRMutator.cpp b/llvm/lib/FuzzMutate/IRMutator.cpp
index 0070fc1a6c7e4..d1abf78222c8c 100644
--- a/llvm/lib/FuzzMutate/IRMutator.cpp
+++ b/llvm/lib/FuzzMutate/IRMutator.cpp
@@ -20,6 +20,8 @@
 #include "llvm/IR/Function.h"
 #include "llvm/IR/InstIterator.h"
 #include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/IntrinsicsAMDGPU.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/Operator.h"
 #include "llvm/IR/PassInstrumentation.h"
@@ -115,9 +117,41 @@ InjectorIRStrategy::chooseOperation(Value *Src, RandomIRBuilder &IB) {
   return *RS;
 }
 
+static inline Instruction *getEffectiveTerminator(BasicBlock &BB) {
+  if (Instruction *I = BB.getTerminatingMustTailCall()) {
+    return I;
+  } else {
+    // Certain intrinsics, such as @llvm.amdgcn.cs.chain, must be immediately
+    // followed by an unreachable instruction..
+    if (UnreachableInst *UI = dyn_cast<UnreachableInst>(BB.getTerminator())) {
+      if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(UI->getPrevNode())) {
+        return II;
+      }
+    }
+  }
+
+  return BB.getTerminator();
+}
+
+static inline BasicBlock::iterator getEndIterator(BasicBlock &BB) {
+  auto End = BB.end();
+
+  if (BB.empty()) {
+    return End;
+  }
+
+  Instruction *EffectiveTerminator = getEffectiveTerminator(BB);
+  if (EffectiveTerminator != BB.getTerminator()) {
+    // Adjust range for special cases such as tail call.
+    End = std::prev(BB.end());
+  }
+
+  return End;
+}
+
 static inline iterator_range<BasicBlock::iterator>
 getInsertionRange(BasicBlock &BB) {
-  auto End = BB.getTerminatingMustTailCall() ? std::prev(BB.end()) : BB.end();
+  auto End = getEndIterator(BB);
   return make_range(BB.getFirstInsertionPt(), End);
 }
 
@@ -409,6 +443,12 @@ static bool isUnsupportedFunction(Function *F) {
     return true;
   }
 
+  // This intrinsic has specific requirements for its parameters and the caller
+  // must adhere to certain calling conventions.
+  if (F->isIntrinsic() && F->getIntrinsicID() == Intrinsic::amdgcn_cs_chain) {
+    return true;
+  }
+
   return false;
 }
 
@@ -641,8 +681,9 @@ void ShuffleBlockStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {
   std::map<size_t, Instruction *> AliveInsts;
   std::map<Instruction *, size_t> AliveInstsLookup;
   size_t InsertIdx = 0;
-  for (auto &I : make_early_inc_range(make_range(
-           BB.getFirstInsertionPt(), BB.getTerminator()->getIterator()))) {
+  for (auto &I : make_early_inc_range(
+           make_range(BB.getFirstInsertionPt(),
+                      getEffectiveTerminator(BB)->getIterator()))) {
     // First gather all instructions that can be shuffled. Don't take
     // terminator.
     AliveInsts.insert({InsertIdx, &I});
@@ -702,7 +743,7 @@ void ShuffleBlockStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {
     }
   }
 
-  Instruction *Terminator = BB.getTerminator();
+  Instruction *Terminator = getEffectiveTerminator(BB);
   // Then put instructions back.
   for (Instruction *I : Insts) {
     I->insertBefore(Terminator->getIterator());
diff --git a/llvm/unittests/FuzzMutate/StrategiesTest.cpp b/llvm/unittests/FuzzMutate/StrategiesTest.cpp
index d140aa159a3ee..28d950269b49d 100644
--- a/llvm/unittests/FuzzMutate/StrategiesTest.cpp
+++ b/llvm/unittests/FuzzMutate/StrategiesTest.cpp
@@ -745,4 +745,22 @@ TEST(AllStrategies, SkipEHPad) {
   mutateAndVerifyModule<InjectorIRStrategy>(Source);
   mutateAndVerifyModule<InstModificationIRStrategy>(Source);
 }
+
+TEST(AllStrategies, SpecialTerminator) {
+  StringRef Source = "\n\
+    declare amdgpu_cs_chain void @callee(<3 x i32> inreg, { i32, ptr addrspace(5), i32, i32 })\n\
+    define amdgpu_cs_chain void @chain_to_chain(<3 x i32> inreg %sgpr, { i32, ptr addrspace(5), i32, i32 } %vgpr) {\n\
+      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\
+      unreachable\n\
+    }\n\
+  ";
+  mutateAndVerifyModule<InjectorIRStrategy>(Source);
+  mutateAndVerifyModule<InsertCFGStrategy>(Source);
+  mutateAndVerifyModule<InsertFunctionStrategy>(Source);
+  mutateAndVerifyModule<InsertPHIStrategy>(Source);
+  mutateAndVerifyModule<InstModificationIRStrategy>(Source);
+  mutateAndVerifyModule<ShuffleBlockStrategy>(Source);
+  mutateAndVerifyModule<SinkInstructionStrategy>(Source);
+}
+
 } // namespace



More information about the llvm-commits mailing list