Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[IR] Replace blockaddress refcount with single flag #138239

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 2, 2025

Conversation

nikic
Copy link
Contributor

@nikic nikic commented May 2, 2025

BasicBlock currently has a blockaddress refcount. However, blockaddresses are uniqued, which means that there can only be a single blockaddress for a given BasicBlock. Prior to #137958 there were some edge case exceptions to this, but now it always holds. As such, replace the refcount with a single flag.

As we're now just tracking two bits, I've dropped the BasicBlockBits structure, as I found it more annoying than useful (esp with the weird AIX workarounds). Instead handle the subclass data the same way we do in Operators.

BasicBlock currently has a blockaddress refcount. However,
blockaddresses are uniqued, which means that there can only be a
single blockaddress for a given BasicBlock. Prior to llvm#137958 there
were some edge case exceptions to this, but now it always holds.
As such, replace the refcount with a single flag.

As we're now just tracking two bits, I've dropped the BasicBlockBits
structure, as I found it more annoying than useful (esp with the
weird AIX workarounds). Instead handle the subclass data the same
way we do in Operators.
@nikic nikic requested review from arsenm, dtcxzyw and efriedma-quic May 2, 2025 08:18
@llvmbot llvmbot added the llvm:ir label May 2, 2025
@llvmbot
Copy link
Member

llvmbot commented May 2, 2025

@llvm/pr-subscribers-llvm-ir

Author: Nikita Popov (nikic)

Changes

BasicBlock currently has a blockaddress refcount. However, blockaddresses are uniqued, which means that there can only be a single blockaddress for a given BasicBlock. Prior to #137958 there were some edge case exceptions to this, but now it always holds. As such, replace the refcount with a single flag.

As we're now just tracking two bits, I've dropped the BasicBlockBits structure, as I found it more annoying than useful (esp with the weird AIX workarounds). Instead handle the subclass data the same way we do in Operators.


Full diff: https://github.com/llvm/llvm-project/pull/138239.diff

3 Files Affected:

  • (modified) llvm/include/llvm/IR/BasicBlock.h (+21-62)
  • (modified) llvm/lib/IR/BasicBlock.cpp (+1-3)
  • (modified) llvm/lib/IR/Constants.cpp (+4-4)
diff --git a/llvm/include/llvm/IR/BasicBlock.h b/llvm/include/llvm/IR/BasicBlock.h
index c9169cb601809..9ee0bacb5c258 100644
--- a/llvm/include/llvm/IR/BasicBlock.h
+++ b/llvm/include/llvm/IR/BasicBlock.h
@@ -564,6 +564,24 @@ class BasicBlock final : public Value, // Basic blocks are data objects also
                            BasicBlock::iterator FromBeginIt,
                            BasicBlock::iterator FromEndIt);
 
+  enum {
+    HasAddressTaken = 1 << 0,
+    InstrOrderValid = 1 << 1,
+  };
+
+  void setHasAddressTaken(bool B) {
+    if (B)
+      SubclassOptionalData |= HasAddressTaken;
+    else
+      SubclassOptionalData &= ~HasAddressTaken;
+  }
+
+  /// Shadow Value::setValueSubclassData with a private forwarding method so
+  /// that any future subclasses cannot accidentally use it.
+  void setValueSubclassData(unsigned short D) {
+    Value::setValueSubclassData(D);
+  }
+
 public:
   /// Returns a pointer to the symbol table if one exists.
   ValueSymbolTable *getValueSymbolTable();
@@ -669,7 +687,7 @@ class BasicBlock final : public Value, // Basic blocks are data objects also
   /// Returns true if there are any uses of this basic block other than
   /// direct branches, switches, etc. to it.
   bool hasAddressTaken() const {
-    return getBasicBlockBits().BlockAddressRefCount != 0;
+    return SubclassOptionalData & HasAddressTaken;
   }
 
   /// Update all phi nodes in this basic block to refer to basic block \p New
@@ -711,15 +729,13 @@ class BasicBlock final : public Value, // Basic blocks are data objects also
 
   /// Returns true if the Order field of child Instructions is valid.
   bool isInstrOrderValid() const {
-    return getBasicBlockBits().InstrOrderValid;
+    return SubclassOptionalData & InstrOrderValid;
   }
 
   /// Mark instruction ordering invalid. Done on every instruction insert.
   void invalidateOrders() {
     validateInstrOrdering();
-    BasicBlockBits Bits = getBasicBlockBits();
-    Bits.InstrOrderValid = false;
-    setBasicBlockBits(Bits);
+    SubclassOptionalData &= ~InstrOrderValid;
   }
 
   /// Renumber instructions and mark the ordering as valid.
@@ -734,63 +750,6 @@ class BasicBlock final : public Value, // Basic blocks are data objects also
   /// each ordering to ensure that transforms have the same algorithmic
   /// complexity when asserts are enabled as when they are disabled.
   void validateInstrOrdering() const;
-
-private:
-#if defined(_AIX) && (!defined(__GNUC__) || defined(__clang__))
-// Except for GCC; by default, AIX compilers store bit-fields in 4-byte words
-// and give the `pack` pragma push semantics.
-#define BEGIN_TWO_BYTE_PACK() _Pragma("pack(2)")
-#define END_TWO_BYTE_PACK() _Pragma("pack(pop)")
-#else
-#define BEGIN_TWO_BYTE_PACK()
-#define END_TWO_BYTE_PACK()
-#endif
-
-  BEGIN_TWO_BYTE_PACK()
-  /// Bitfield to help interpret the bits in Value::SubclassData.
-  struct BasicBlockBits {
-    unsigned short BlockAddressRefCount : 15;
-    unsigned short InstrOrderValid : 1;
-  };
-  END_TWO_BYTE_PACK()
-
-#undef BEGIN_TWO_BYTE_PACK
-#undef END_TWO_BYTE_PACK
-
-  /// Safely reinterpret the subclass data bits to a more useful form.
-  BasicBlockBits getBasicBlockBits() const {
-    static_assert(sizeof(BasicBlockBits) == sizeof(unsigned short),
-                  "too many bits for Value::SubclassData");
-    unsigned short ValueData = getSubclassDataFromValue();
-    BasicBlockBits AsBits;
-    memcpy(&AsBits, &ValueData, sizeof(AsBits));
-    return AsBits;
-  }
-
-  /// Reinterpret our subclass bits and store them back into Value.
-  void setBasicBlockBits(BasicBlockBits AsBits) {
-    unsigned short D;
-    memcpy(&D, &AsBits, sizeof(D));
-    Value::setValueSubclassData(D);
-  }
-
-  /// Increment the internal refcount of the number of BlockAddresses
-  /// referencing this BasicBlock by \p Amt.
-  ///
-  /// This is almost always 0, sometimes one possibly, but almost never 2, and
-  /// inconceivably 3 or more.
-  void AdjustBlockAddressRefCount(int Amt) {
-    BasicBlockBits Bits = getBasicBlockBits();
-    Bits.BlockAddressRefCount += Amt;
-    setBasicBlockBits(Bits);
-    assert(Bits.BlockAddressRefCount < 255 && "Refcount wrap-around");
-  }
-
-  /// Shadow Value::setValueSubclassData with a private forwarding method so
-  /// that any future subclasses cannot accidentally use it.
-  void setValueSubclassData(unsigned short D) {
-    Value::setValueSubclassData(D);
-  }
 };
 
 // Create wrappers for C Binding types (see CBindingWrapping.h).
diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp
index c632b1b2dc2ab..b4c16447bc686 100644
--- a/llvm/lib/IR/BasicBlock.cpp
+++ b/llvm/lib/IR/BasicBlock.cpp
@@ -732,9 +732,7 @@ void BasicBlock::renumberInstructions() {
     I.Order = Order++;
 
   // Set the bit to indicate that the instruction order valid and cached.
-  BasicBlockBits Bits = getBasicBlockBits();
-  Bits.InstrOrderValid = true;
-  setBasicBlockBits(Bits);
+  SubclassOptionalData |= InstrOrderValid;
 
   NumInstrRenumberings++;
 }
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 49107a421149e..d7c847e541052 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -1911,7 +1911,7 @@ BlockAddress *BlockAddress::get(Function *F, BasicBlock *BB) {
 BlockAddress::BlockAddress(Type *Ty, BasicBlock *BB)
     : Constant(Ty, Value::BlockAddressVal, AllocMarker) {
   setOperand(0, BB);
-  BB->AdjustBlockAddressRefCount(1);
+  BB->setHasAddressTaken(true);
 }
 
 BlockAddress *BlockAddress::lookup(const BasicBlock *BB) {
@@ -1926,7 +1926,7 @@ BlockAddress *BlockAddress::lookup(const BasicBlock *BB) {
 /// Remove the constant from the constant table.
 void BlockAddress::destroyConstantImpl() {
   getType()->getContext().pImpl->BlockAddresses.erase(getBasicBlock());
-  getBasicBlock()->AdjustBlockAddressRefCount(-1);
+  getBasicBlock()->setHasAddressTaken(false);
 }
 
 Value *BlockAddress::handleOperandChangeImpl(Value *From, Value *To) {
@@ -1939,14 +1939,14 @@ Value *BlockAddress::handleOperandChangeImpl(Value *From, Value *To) {
   if (NewBA)
     return NewBA;
 
-  getBasicBlock()->AdjustBlockAddressRefCount(-1);
+  getBasicBlock()->setHasAddressTaken(false);
 
   // Remove the old entry, this can't cause the map to rehash (just a
   // tombstone will get added).
   getContext().pImpl->BlockAddresses.erase(getBasicBlock());
   NewBA = this;
   setOperand(0, NewBB);
-  getBasicBlock()->AdjustBlockAddressRefCount(1);
+  getBasicBlock()->setHasAddressTaken(true);
 
   // If we just want to keep the existing value, then return null.
   // Callers know that this means we shouldn't delete this value.

@nikic nikic merged commit 7f5c34b into llvm:main May 2, 2025
13 checks passed
@nikic nikic deleted the block-address-refcount branch May 2, 2025 11:03
@llvm-ci
Copy link
Collaborator

llvm-ci commented May 2, 2025

LLVM Buildbot has detected a new failure on builder ml-opt-dev-x86-64 running on ml-opt-dev-x86-64-b2 while building llvm at step 4 "cmake-configure".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/137/builds/17839

Here is the relevant piece of the build log for the reference
Step 4 (cmake-configure) failure: cmake (failure)
...
-- Targeting XCore
-- Registering ExampleIRTransforms as a pass plugin (static build: OFF)
-- Registering Bye as a pass plugin (static build: OFF)
-- Failed to find LLVM FileCheck
-- Google Benchmark version: v0.0.0, normalized to 0.0.0
-- Looking for shm_open in rt
-- Looking for shm_open in rt - found
-- Performing Test HAVE_CXX_FLAG_WALL
-- Performing Test HAVE_CXX_FLAG_WALL - Success
-- Performing Test HAVE_CXX_FLAG_WEXTRA
-- Performing Test HAVE_CXX_FLAG_WEXTRA - Success
-- Performing Test HAVE_CXX_FLAG_WSHADOW
-- Performing Test HAVE_CXX_FLAG_WSHADOW - Success
-- Performing Test HAVE_CXX_FLAG_WFLOAT_EQUAL
-- Performing Test HAVE_CXX_FLAG_WFLOAT_EQUAL - Success
-- Performing Test HAVE_CXX_FLAG_WOLD_STYLE_CAST
-- Performing Test HAVE_CXX_FLAG_WOLD_STYLE_CAST - Success
-- Performing Test HAVE_CXX_FLAG_WSUGGEST_OVERRIDE
-- Performing Test HAVE_CXX_FLAG_WSUGGEST_OVERRIDE - Success
-- Performing Test HAVE_CXX_FLAG_PEDANTIC
-- Performing Test HAVE_CXX_FLAG_PEDANTIC - Success
-- Performing Test HAVE_CXX_FLAG_PEDANTIC_ERRORS
-- Performing Test HAVE_CXX_FLAG_PEDANTIC_ERRORS - Success
-- Performing Test HAVE_CXX_FLAG_WSHORTEN_64_TO_32
-- Performing Test HAVE_CXX_FLAG_WSHORTEN_64_TO_32 - Failed
-- Performing Test HAVE_CXX_FLAG_FSTRICT_ALIASING
-- Performing Test HAVE_CXX_FLAG_FSTRICT_ALIASING - Success
-- Performing Test HAVE_CXX_FLAG_WNO_DEPRECATED_DECLARATIONS
-- Performing Test HAVE_CXX_FLAG_WNO_DEPRECATED_DECLARATIONS - Success
-- Performing Test HAVE_CXX_FLAG_FNO_EXCEPTIONS
-- Performing Test HAVE_CXX_FLAG_FNO_EXCEPTIONS - Success
-- Performing Test HAVE_CXX_FLAG_WSTRICT_ALIASING
-- Performing Test HAVE_CXX_FLAG_WSTRICT_ALIASING - Success
-- Performing Test HAVE_CXX_FLAG_WD654
-- Performing Test HAVE_CXX_FLAG_WD654 - Failed
-- Performing Test HAVE_CXX_FLAG_WTHREAD_SAFETY
-- Performing Test HAVE_CXX_FLAG_WTHREAD_SAFETY - Failed
-- Performing Test HAVE_CXX_FLAG_COVERAGE
-- Performing Test HAVE_CXX_FLAG_COVERAGE - Success
-- Compiling and running to test HAVE_GNU_POSIX_REGEX
-- Performing Test HAVE_GNU_POSIX_REGEX -- failed to compile
-- Compiling and running to test HAVE_POSIX_REGEX
-- Performing Test HAVE_POSIX_REGEX -- success
-- Compiling and running to test HAVE_STEADY_CLOCK
-- Performing Test HAVE_STEADY_CLOCK -- success
-- Compiling and running to test HAVE_PTHREAD_AFFINITY
-- Performing Test HAVE_PTHREAD_AFFINITY -- failed to compile
-- Configuring incomplete, errors occurred!
See also "/b/ml-opt-dev-x86-64-b1/build/CMakeFiles/CMakeOutput.log".
See also "/b/ml-opt-dev-x86-64-b1/build/CMakeFiles/CMakeError.log".

IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
BasicBlock currently has a blockaddress refcount. However,
blockaddresses are uniqued, which means that there can only be a single
blockaddress for a given BasicBlock. Prior to llvm#137958 there were some
edge case exceptions to this, but now it always holds. As such, replace
the refcount with a single flag.

As we're now just tracking two bits, I've dropped the BasicBlockBits
structure, as I found it more annoying than useful (esp with the weird
AIX workarounds). Instead handle the subclass data the same way we do in
Operators.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
BasicBlock currently has a blockaddress refcount. However,
blockaddresses are uniqued, which means that there can only be a single
blockaddress for a given BasicBlock. Prior to llvm#137958 there were some
edge case exceptions to this, but now it always holds. As such, replace
the refcount with a single flag.

As we're now just tracking two bits, I've dropped the BasicBlockBits
structure, as I found it more annoying than useful (esp with the weird
AIX workarounds). Instead handle the subclass data the same way we do in
Operators.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
BasicBlock currently has a blockaddress refcount. However,
blockaddresses are uniqued, which means that there can only be a single
blockaddress for a given BasicBlock. Prior to llvm#137958 there were some
edge case exceptions to this, but now it always holds. As such, replace
the refcount with a single flag.

As we're now just tracking two bits, I've dropped the BasicBlockBits
structure, as I found it more annoying than useful (esp with the weird
AIX workarounds). Instead handle the subclass data the same way we do in
Operators.
GeorgeARM pushed a commit to GeorgeARM/llvm-project that referenced this pull request May 7, 2025
BasicBlock currently has a blockaddress refcount. However,
blockaddresses are uniqued, which means that there can only be a single
blockaddress for a given BasicBlock. Prior to llvm#137958 there were some
edge case exceptions to this, but now it always holds. As such, replace
the refcount with a single flag.

As we're now just tracking two bits, I've dropped the BasicBlockBits
structure, as I found it more annoying than useful (esp with the weird
AIX workarounds). Instead handle the subclass data the same way we do in
Operators.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants