[llvm] 29e8b8c - [bugpoint] Reduce metadata that does not contribute to crash.

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 30 08:12:59 PDT 2019


Author: Florian Hahn
Date: 2019-10-30T15:11:56Z
New Revision: 29e8b8ce6697414759f9314255d0165edbb3e454

URL: https://github.com/llvm/llvm-project/commit/29e8b8ce6697414759f9314255d0165edbb3e454
DIFF: https://github.com/llvm/llvm-project/commit/29e8b8ce6697414759f9314255d0165edbb3e454.diff

LOG: [bugpoint] Reduce metadata that does not contribute to crash.

Add a new reducer that drops metadata that does not contribute to the
crash from instructions.

It adjusts the metadata.ll test case, as now also the instruction level
metadata will get dropped.

Reviewers: davide, reames, modocache

Reviewed By: reames

Differential Revision: https://reviews.llvm.org/D69234

Added: 
    llvm/test/BugPoint/retain-crashing-metadata.ll

Modified: 
    llvm/test/BugPoint/metadata.ll
    llvm/tools/bugpoint-passes/TestPasses.cpp
    llvm/tools/bugpoint/CrashDebugger.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/BugPoint/metadata.ll b/llvm/test/BugPoint/metadata.ll
index a090bbde1de0..9cc4659b5767 100644
--- a/llvm/test/BugPoint/metadata.ll
+++ b/llvm/test/BugPoint/metadata.ll
@@ -8,22 +8,18 @@
 ; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t-notype -bugpoint-crashcalls -silence-passes -disable-namedmd-remove -disable-strip-debuginfo > /dev/null
 ; RUN: llvm-dis %t-notype-reduced-simplified.bc -o - | FileCheck %s --check-prefix=NOTYPE
 ;
-; Bugpoint should keep the call's metadata attached to the call.
+; Bugpoint can drop the metadata on the call, as it does not contrinute to the crash.
 
-; CHECK: call void @foo(), !dbg ![[LOC:[0-9]+]], !attach ![[CALL:[0-9]+]]
-; NODEBUG: call void @foo(), !attach ![[CALL:[0-9]+]]
-; NOTYPE: call void @foo(), !dbg ![[LOC:[0-9]+]], !attach ![[CALL:[0-9]+]]
-; NODEBUG-NOT: call void @foo(), !attach ![[CALL:[0-9]+]]
+; CHECK: call void @foo()
+; NODEBUG: call void @foo()
+; NOTYPE: call void @foo()
+; NODEBUG-NOT: call void @foo()
 ; NOTYPE-NOT: !DIBasicType
 ; NOTYPE: !DICompileUnit
 ; NOTYPE-NOT: !DIBasicType
-; CHECK-DAG: ![[LOC]] = !DILocation(line: 104, column: 105, scope: ![[SCOPE:[0-9]+]])
-; CHECK-DAG: ![[SCOPE]] = distinct !DISubprogram(name: "test",{{.*}}file: ![[FILE:[0-9]+]]
-; CHECK-DAG: ![[FILE]] = !DIFile(filename: "source.c", directory: "/dir")
-; CHECK-DAG: ![[CALL]] = !{!"the call to foo"}
 
 %rust_task = type {}
-define void @test(i32* %a, i8* %b) {
+define void @test(i32* %a, i8* %b) !dbg !9 {
     %s = mul i8 22, 9, !attach !0, !dbg !10
     store i8 %s, i8* %b, !attach !1, !dbg !11
     call void @foo(), !attach !2, !dbg !12

diff  --git a/llvm/test/BugPoint/retain-crashing-metadata.ll b/llvm/test/BugPoint/retain-crashing-metadata.ll
new file mode 100644
index 000000000000..ddceb807848e
--- /dev/null
+++ b/llvm/test/BugPoint/retain-crashing-metadata.ll
@@ -0,0 +1,22 @@
+; REQUIRES: plugins
+; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t-notype -bugpoint-crashmetadata -silence-passes > /dev/null
+; RUN: llvm-dis %t-notype-reduced-simplified.bc -o - | FileCheck %s
+;
+; Make sure BugPoint retains metadata contributing to a crash.
+
+; CHECK-LABEL: define void @test2(float %f) {
+; CHECK-NEXT: %arg = fadd float %f, 1.000000e+01
+; CHECK-NOT: !fpmath
+; CHECK-NEXT: %x = call float @llvm.fabs.f32(float %arg), !fpmath [[FPMATH:![0-9]+]]
+; CHECK-NEXT: ret void
+
+; CHECK: [[FPMATH]] = !{float 2.500000e+00}
+define void @test2(float %f) {
+    %arg = fadd float %f, 1.000000e+01, !fpmath !0
+    %x = call float @llvm.fabs.f32(float %arg), !fpmath !0
+    ret void
+}
+
+declare float @llvm.fabs.f32(float)
+
+!0 = !{float 2.500000e+00}

diff  --git a/llvm/tools/bugpoint-passes/TestPasses.cpp b/llvm/tools/bugpoint-passes/TestPasses.cpp
index 6340a3ec5c6c..d11a605fa88e 100644
--- a/llvm/tools/bugpoint-passes/TestPasses.cpp
+++ b/llvm/tools/bugpoint-passes/TestPasses.cpp
@@ -1,5 +1,6 @@
 //===- TestPasses.cpp - "buggy" passes used to test bugpoint --------------===//
 //
+//
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@@ -13,11 +14,14 @@
 
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/Constant.h"
+#include "llvm/IR/InstIterator.h"
 #include "llvm/IR/InstVisitor.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Type.h"
 #include "llvm/Pass.h"
 
+#include "llvm/IR/PatternMatch.h"
+using namespace llvm::PatternMatch;
 using namespace llvm;
 
 namespace {
@@ -147,3 +151,33 @@ char CrashOnFunctionAttribute::ID = 0;
 static RegisterPass<CrashOnFunctionAttribute>
     B("bugpoint-crashfuncattr", "BugPoint Test Pass - Intentionally crash on "
                                 "function attribute 'bugpoint-crash'");
+
+namespace {
+class CrashOnMetadata : public FunctionPass {
+public:
+  static char ID; // Pass ID, replacement for typeid
+  CrashOnMetadata() : FunctionPass(ID) {}
+
+private:
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.setPreservesAll();
+  }
+
+  // Crash on fabs calls with fpmath metdata and an fadd as argument. This
+  // ensures the fadd instruction sticks around and we can check that the
+  // metadata there is dropped correctly.
+  bool runOnFunction(Function &F) override {
+    for (Instruction &I : instructions(F))
+      if (match(&I, m_FAbs(m_FAdd(m_Value(), m_Value()))) &&
+          I.hasMetadata("fpmath"))
+        abort();
+    return false;
+  }
+};
+} // namespace
+
+char CrashOnMetadata::ID = 0;
+static RegisterPass<CrashOnMetadata>
+    C("bugpoint-crashmetadata",
+      "BugPoint Test Pass - Intentionally crash on "
+      "fabs calls with fpmath metadata and an fadd as argument");

diff  --git a/llvm/tools/bugpoint/CrashDebugger.cpp b/llvm/tools/bugpoint/CrashDebugger.cpp
index de86fc27f225..6e9563044365 100644
--- a/llvm/tools/bugpoint/CrashDebugger.cpp
+++ b/llvm/tools/bugpoint/CrashDebugger.cpp
@@ -16,11 +16,11 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
-#include "llvm/Transforms/Utils/Local.h"
 #include "llvm/IR/CFG.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/InstIterator.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/Module.h"
@@ -32,6 +32,7 @@
 #include "llvm/Transforms/Scalar.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/Transforms/Utils/Local.h"
 #include <set>
 using namespace llvm;
 
@@ -805,6 +806,78 @@ bool ReduceCrashingInstructions::TestInsts(
   return false;
 }
 
+namespace {
+/// ReduceCrashingMetadata reducer - This works by removing all metadata from
+/// the specified instructions.
+///
+class ReduceCrashingMetadata : public ListReducer<Instruction *> {
+  BugDriver &BD;
+  BugTester TestFn;
+
+public:
+  ReduceCrashingMetadata(BugDriver &bd, BugTester testFn)
+      : BD(bd), TestFn(testFn) {}
+
+  Expected<TestResult> doTest(std::vector<Instruction *> &Prefix,
+                              std::vector<Instruction *> &Kept) override {
+    if (!Kept.empty() && TestInsts(Kept))
+      return KeepSuffix;
+    if (!Prefix.empty() && TestInsts(Prefix))
+      return KeepPrefix;
+    return NoFailure;
+  }
+
+  bool TestInsts(std::vector<Instruction *> &Prefix);
+};
+} // namespace
+
+bool ReduceCrashingMetadata::TestInsts(std::vector<Instruction *> &Insts) {
+  // Clone the program to try hacking it apart...
+  ValueToValueMapTy VMap;
+  std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
+
+  // Convert list to set for fast lookup...
+  SmallPtrSet<Instruction *, 32> Instructions;
+  for (Instruction *I : Insts)
+    Instructions.insert(cast<Instruction>(VMap[I]));
+
+  outs() << "Checking for crash with metadata retained from "
+         << Instructions.size();
+  if (Instructions.size() == 1)
+    outs() << " instruction: ";
+  else
+    outs() << " instructions: ";
+
+  // Try to drop instruction metadata from all instructions, except the ones
+  // selected in Instructions.
+  for (Function &F : *M)
+    for (Instruction &Inst : instructions(F)) {
+      if (Instructions.find(&Inst) == Instructions.end()) {
+        Inst.dropUnknownNonDebugMetadata();
+        Inst.setDebugLoc({});
+      }
+    }
+
+  // Verify that this is still valid.
+  legacy::PassManager Passes;
+  Passes.add(createVerifierPass(/*FatalErrors=*/false));
+  Passes.run(*M);
+
+  // Try running on the hacked up program...
+  if (TestFn(BD, M.get())) {
+    BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
+
+    // Make sure to use instruction pointers that point into the now-current
+    // module, and that they don't include any deleted blocks.
+    Insts.clear();
+    for (Instruction *I : Instructions)
+      Insts.push_back(I);
+    return true;
+  }
+  // It didn't crash, try something else.
+  return false;
+}
+
 namespace {
 // Reduce the list of Named Metadata nodes. We keep this as a list of
 // names to avoid having to convert back and forth every time.
@@ -1081,6 +1154,21 @@ static Error ReduceInsts(BugDriver &BD, BugTester TestFn) {
     }
 
   } while (Simplification);
+
+  // Attempt to drop metadata from instructions that does not contribute to the
+  // crash.
+  if (!BugpointIsInterrupted) {
+    std::vector<Instruction *> Insts;
+    for (Function &F : BD.getProgram())
+      for (Instruction &I : instructions(F))
+        Insts.push_back(&I);
+
+    Expected<bool> Result =
+        ReduceCrashingMetadata(BD, TestFn).reduceList(Insts);
+    if (Error E = Result.takeError())
+      return E;
+  }
+
   BD.EmitProgressBitcode(BD.getProgram(), "reduced-instructions");
   return Error::success();
 }


        


More information about the llvm-commits mailing list