Skip to content

Commit

Permalink
Add a new WeakVH value handle; NFC (#6703)
Browse files Browse the repository at this point in the history
Originally @lizhengxing's PR. Retargeting main.

This PR pulls 2 upstream changes, Add a new WeakVH value handle; NFC
(llvm/llvm-project@f1c0eaf)
and Use a 2 bit pointer in ValueHandleBase::PrevPair; NFC
(llvm/llvm-project@b297bff),
into DXC.

Here's the summary of the changes:

Add a new WeakVH value handle; NFC 
> WeakVH nulls itself out if the value it was tracking gets deleted, but
it does not track RAUW.
> 
>       Reviewers: dblaikie, davide
> 
>       Subscribers: mcrosier, llvm-commits
> 
>       Differential Revision: https://reviews.llvm.org/D32267

Use a 2 bit pointer in ValueHandleBase::PrevPair; NFC

> This was an omission in r301813. I had made the supporting changes to
make this happen, but I forgot to actually update the
> 
> PrevPair declaration.

This is part 4 and 5 of the fix for #6659.
  • Loading branch information
adam-yang authored Jun 21, 2024
1 parent 8b18659 commit b197bec
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 2 deletions.
33 changes: 32 additions & 1 deletion include/llvm/IR/ValueHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class ValueHandleBase {
///
/// This is to avoid having a vtable for the light-weight handle pointers. The
/// fully general Callback version does have a vtable.
enum HandleBaseKind { Assert, Callback, WeakTracking };
enum HandleBaseKind { Assert, Callback, Weak, WeakTracking };

private:
PointerIntPair<ValueHandleBase**, 2, HandleBaseKind> PrevPair;
Expand Down Expand Up @@ -134,6 +134,37 @@ class ValueHandleBase {
void RemoveFromUseList();
};

/// \brief A nullable Value handle that is nullable.
///
/// This is a value handle that points to a value, and nulls itself
/// out if that value is deleted.
class WeakVH : public ValueHandleBase {
public:
WeakVH() : ValueHandleBase(Weak) {}
WeakVH(Value *P) : ValueHandleBase(Weak, P) {}
WeakVH(const WeakVH &RHS) : ValueHandleBase(Weak, RHS) {}

WeakVH &operator=(const WeakVH &RHS) = default;

Value *operator=(Value *RHS) { return ValueHandleBase::operator=(RHS); }
Value *operator=(const ValueHandleBase &RHS) {
return ValueHandleBase::operator=(RHS);
}

operator Value *() const { return getValPtr(); }
};

// Specialize simplify_type to allow WeakVH to participate in
// dyn_cast, isa, etc.
template <> struct simplify_type<WeakVH> {
typedef Value *SimpleType;
static SimpleType getSimplifiedValue(WeakVH &WVH) { return WVH; }
};
template <> struct simplify_type<const WeakVH> {
typedef Value *SimpleType;
static SimpleType getSimplifiedValue(const WeakVH &WVH) { return WVH; }
};

/// \brief Value handle that is nullable, but tries to track the Value.
///
/// This is a value handle that tries hard to point to a Value, even across
Expand Down
4 changes: 3 additions & 1 deletion lib/IR/Value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,7 @@ void ValueHandleBase::ValueIsDeleted(Value *V) {
switch (Entry->getKind()) {
case Assert:
break;
case Weak:
case WeakTracking:
// WeakTracking just goes to null, which will unlink it from the list.
Entry->operator=(nullptr);
Expand Down Expand Up @@ -722,7 +723,8 @@ void ValueHandleBase::ValueIsRAUWd(Value *Old, Value *New) {

switch (Entry->getKind()) {
case Assert:
// Asserting handle does not follow RAUW implicitly.
case Weak:
// Asserting and Weak handles do not follow RAUW implicitly.
break;
case WeakTracking:
// Weak goes to the new value, which will unlink it from Old's list.
Expand Down
18 changes: 18 additions & 0 deletions unittests/IR/ValueHandleTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,24 @@ class ConcreteCallbackVH : public CallbackVH {
ConcreteCallbackVH(Value *V) : CallbackVH(V) {}
};

TEST_F(ValueHandle, WeakVH_BasicOperation) {
WeakVH WVH(BitcastV.get());
EXPECT_EQ(BitcastV.get(), WVH);
WVH = ConstantV;
EXPECT_EQ(ConstantV, WVH);

// Make sure I can call a method on the underlying Value. It
// doesn't matter which method.
EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), WVH->getType());
EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*WVH).getType());

WVH = BitcastV.get();
BitcastV->replaceAllUsesWith(ConstantV);
EXPECT_EQ(WVH, BitcastV.get());
BitcastV.reset();
EXPECT_EQ(WVH, nullptr);
}

TEST_F(ValueHandle, WeakTrackingVH_BasicOperation) {
WeakTrackingVH WVH(BitcastV.get());
EXPECT_EQ(BitcastV.get(), WVH);
Expand Down

0 comments on commit b197bec

Please sign in to comment.