[FuzzMutate] Don't insert instructions after musttail call
authorNikita Popov <npopov@redhat.com>
Wed, 16 Mar 2022 15:10:24 +0000 (16:10 +0100)
committerNikita Popov <npopov@redhat.com>
Wed, 16 Mar 2022 15:58:33 +0000 (16:58 +0100)
llvm/lib/FuzzMutate/IRMutator.cpp
llvm/unittests/FuzzMutate/StrategiesTest.cpp

index 105f8bc..0f93bf9 100644 (file)
@@ -116,6 +116,16 @@ void InjectorIRStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {
   auto InstsBefore = makeArrayRef(Insts).slice(0, IP);
   auto InstsAfter = makeArrayRef(Insts).slice(IP);
 
+  if (!InstsBefore.empty()) {
+    // Don't insert instructions after a musttail call.
+    Instruction *InstBefore = InstsBefore.back();
+    if (isa<BitCastInst>(InstBefore))
+      InstBefore = InstBefore->getPrevNode();
+    CallBase *CallBefore = dyn_cast_or_null<CallBase>(InstBefore);
+    if (CallBefore && CallBefore->isMustTailCall())
+      return;
+  }
+
   // Choose a source, which will be used to constrain the operation selection.
   SmallVector<Value *, 2> Srcs;
   Srcs.push_back(IB.findOrCreateSource(BB, InstsBefore));
index 562d08b..9954a63 100644 (file)
@@ -100,6 +100,36 @@ TEST(InjectorIRStrategyTest, EmptyModule) {
   EXPECT_TRUE(!verifyModule(*M, &errs()));
 }
 
+TEST(InjectorIRStrategyTest, MustTailCall) {
+  // Test that we don't insert after a musttail call.
+  StringRef Source = ""
+      "define i32 @func() {\n"
+        "%v = musttail call i32 @func()\n"
+        "ret i32 %v\n"
+      "}\n";
+
+  auto Mutator = createInjectorMutator();
+  ASSERT_TRUE(Mutator);
+
+  IterateOnSource(Source, *Mutator);
+}
+
+TEST(InjectorIRStrategyTest, MustTailCallBitCast) {
+  // Test that we don't insert after a musttail call bitcast.
+  StringRef Source = ""
+      "declare i32* @func2()\n"
+      "define i8* @func() {\n"
+        "%v = musttail call i32* @func2()\n"
+        "%v2 = bitcast i32* %v to i8*\n"
+        "ret i8* %v2\n"
+      "}\n";
+
+  auto Mutator = createInjectorMutator();
+  ASSERT_TRUE(Mutator);
+
+  IterateOnSource(Source, *Mutator);
+}
+
 TEST(InstDeleterIRStrategyTest, EmptyFunction) {
   // Test that we don't crash even if we can't remove from one of the functions.