Skip to content

Commit

Permalink
[IR] Allow type change in ValueAsMetadata::handleRAUW (#76969)
Browse files Browse the repository at this point in the history
`ValueAsMetadata::handleRAUW` is a mechanism to replace all metadata
referring to one value by a different value.

Relax an assert that used to enforce the old and new value to have the
same type.
This seems to be a sanity plausibility assert only, as the
implementation actually supports mismatching types.

This is motivated by a downstream mechanism where we use poison
ValueAsMetadata values to annotate pointee types of opaque pointer
function arguments.

When replacing one type with a different one to work around DXIL vs LLVM
incompatibilities, we need to update type annotations, and handleRAUW is
more efficient than creating new MD nodes.
  • Loading branch information
jasilvanus committed Jan 18, 2024
1 parent a7f9e92 commit bd2430b
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 1 deletion.
2 changes: 1 addition & 1 deletion llvm/lib/IR/Metadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ void ValueAsMetadata::handleRAUW(Value *From, Value *To) {
assert(From && "Expected valid value");
assert(To && "Expected valid value");
assert(From != To && "Expected changed value");
assert(From->getType() == To->getType() && "Unexpected type change");
assert(&From->getContext() == &To->getContext() && "Expected same context");

LLVMContext &Context = From->getType()->getContext();
auto &Store = Context.pImpl->ValuesAsMetadata;
Expand Down
19 changes: 19 additions & 0 deletions llvm/unittests/IR/MetadataTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3724,6 +3724,25 @@ TEST_F(ValueAsMetadataTest, UpdatesOnRAUW) {
EXPECT_TRUE(MD->getValue() == GV1.get());
}

TEST_F(ValueAsMetadataTest, handleRAUWWithTypeChange) {
// Test that handleRAUW supports type changes.
// This is helpful in cases where poison values are used to encode
// types in metadata, e.g. in type annotations.
// Changing the type stored in metadata requires to change the type of
// the stored poison value.
auto *I32Poison = PoisonValue::get(Type::getInt32Ty(Context));
auto *I64Poison = PoisonValue::get(Type::getInt64Ty(Context));
auto *MD = ConstantAsMetadata::get(I32Poison);

EXPECT_EQ(MD->getValue(), I32Poison);
EXPECT_NE(MD->getValue(), I64Poison);

ValueAsMetadata::handleRAUW(I32Poison, I64Poison);

EXPECT_NE(MD->getValue(), I32Poison);
EXPECT_EQ(MD->getValue(), I64Poison);
}

TEST_F(ValueAsMetadataTest, TempTempReplacement) {
// Create a constant.
ConstantAsMetadata *CI =
Expand Down

0 comments on commit bd2430b

Please sign in to comment.