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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 21 additions & 62 deletions llvm/include/llvm/IR/BasicBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand All @@ -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).
Expand Down
4 changes: 1 addition & 3 deletions llvm/lib/IR/BasicBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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++;
}
Expand Down
8 changes: 4 additions & 4 deletions llvm/lib/IR/Constants.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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) {
Expand All @@ -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.
Expand Down