[BOLT] Add isParentOf and isParentOrChildOf BF checks
authorAmir Ayupov <aaupov@fb.com>
Fri, 19 May 2023 18:33:21 +0000 (11:33 -0700)
committerAmir Ayupov <aaupov@fb.com>
Sat, 20 May 2023 00:51:54 +0000 (17:51 -0700)
Add helper methods and simplify cases where we want to check if two functions
are parent-child of each other (function-fragment relationship).

Reviewed By: #bolt, rafauler

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

bolt/include/bolt/Core/BinaryFunction.h
bolt/lib/Core/BinaryContext.cpp
bolt/lib/Core/Exceptions.cpp

index a54492c..60d079c 100644 (file)
@@ -1757,6 +1757,16 @@ public:
     return ParentFragments.contains(&Other);
   }
 
+  /// Returns if this function is a parent of \p Other function.
+  bool isParentOf(const BinaryFunction &Other) const {
+    return llvm::is_contained(Fragments, &Other);
+  }
+
+  /// Returns if this function is a parent or child of \p Other function.
+  bool isParentOrChildOf(const BinaryFunction &Other) const {
+    return isChildOf(Other) || isParentOf(Other);
+  }
+
   /// Set the profile data for the number of times the function was called.
   BinaryFunction &setExecutionCount(uint64_t Count) {
     ExecutionCount = Count;
index 6a9e35e..d81b669 100644 (file)
@@ -506,17 +506,6 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address,
       EntriesAsAddress->emplace_back(EntryAddress);
   };
 
-  auto doesBelongToFunction = [&](const uint64_t Addr,
-                                  const BinaryFunction *TargetBF) -> bool {
-    if (BF.containsAddress(Addr))
-      return true;
-    // Nothing to do if we failed to identify the containing function.
-    if (!TargetBF)
-      return false;
-    // Check if BF is a fragment of TargetBF or vice versa.
-    return BF.isChildOf(*TargetBF) || TargetBF->isChildOf(BF);
-  };
-
   ErrorOr<const BinarySection &> Section = getSectionForAddress(Address);
   if (!Section)
     return false;
@@ -576,8 +565,11 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address,
     // Function or one of its fragments.
     const BinaryFunction *TargetBF = getBinaryFunctionContainingAddress(Value);
 
+    bool DoesBelongToFunction = BF.containsAddress(Value) ||
+                                (TargetBF && TargetBF->isParentOrChildOf(BF));
+
     // We assume that a jump table cannot have function start as an entry.
-    if (!doesBelongToFunction(Value, TargetBF) || Value == BF.getAddress()) {
+    if (!DoesBelongToFunction || Value == BF.getAddress()) {
       LLVM_DEBUG({
         if (!BF.containsAddress(Value)) {
           dbgs() << "FAIL: function doesn't contain this address\n";
@@ -766,8 +758,7 @@ BinaryContext::getOrCreateJumpTable(BinaryFunction &Function, uint64_t Address,
     // Prevent associating a jump table to a specific fragment twice.
     // This simple check arises from the assumption: no more than 2 fragments.
     if (JT->Parents.size() == 1 && JT->Parents[0] != &Function) {
-      assert((JT->Parents[0]->isChildOf(Function) ||
-              Function.isChildOf(*JT->Parents[0])) &&
+      assert(JT->Parents[0]->isParentOrChildOf(Function) &&
              "cannot re-use jump table of a different function");
       // Duplicate the entry for the parent function for easy access
       JT->Parents.push_back(&Function);
index d01c528..667f175 100644 (file)
@@ -188,9 +188,8 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
              "BOLT-ERROR: cannot find landing pad fragment");
       BC.addInterproceduralReference(this, Fragment->getAddress());
       BC.processInterproceduralReferences();
-      assert((isChildOf(*Fragment) || Fragment->isChildOf(*this)) &&
-             "BOLT-ERROR: cannot have landing pads in different "
-             "functions");
+      assert(isParentOrChildOf(*Fragment) &&
+             "BOLT-ERROR: cannot have landing pads in different functions");
       setHasIndirectTargetToSplitFragment(true);
       BC.addFragmentsToSkip(this);
       return;