Skip to content

Commit bd2430b

Browse files
authored
[IR] Allow type change in ValueAsMetadata::handleRAUW (#76969)
`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.
1 parent a7f9e92 commit bd2430b

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

llvm/lib/IR/Metadata.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,7 @@ void ValueAsMetadata::handleRAUW(Value *From, Value *To) {
530530
assert(From && "Expected valid value");
531531
assert(To && "Expected valid value");
532532
assert(From != To && "Expected changed value");
533-
assert(From->getType() == To->getType() && "Unexpected type change");
533+
assert(&From->getContext() == &To->getContext() && "Expected same context");
534534

535535
LLVMContext &Context = From->getType()->getContext();
536536
auto &Store = Context.pImpl->ValuesAsMetadata;

llvm/unittests/IR/MetadataTest.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -3724,6 +3724,25 @@ TEST_F(ValueAsMetadataTest, UpdatesOnRAUW) {
37243724
EXPECT_TRUE(MD->getValue() == GV1.get());
37253725
}
37263726

3727+
TEST_F(ValueAsMetadataTest, handleRAUWWithTypeChange) {
3728+
// Test that handleRAUW supports type changes.
3729+
// This is helpful in cases where poison values are used to encode
3730+
// types in metadata, e.g. in type annotations.
3731+
// Changing the type stored in metadata requires to change the type of
3732+
// the stored poison value.
3733+
auto *I32Poison = PoisonValue::get(Type::getInt32Ty(Context));
3734+
auto *I64Poison = PoisonValue::get(Type::getInt64Ty(Context));
3735+
auto *MD = ConstantAsMetadata::get(I32Poison);
3736+
3737+
EXPECT_EQ(MD->getValue(), I32Poison);
3738+
EXPECT_NE(MD->getValue(), I64Poison);
3739+
3740+
ValueAsMetadata::handleRAUW(I32Poison, I64Poison);
3741+
3742+
EXPECT_NE(MD->getValue(), I32Poison);
3743+
EXPECT_EQ(MD->getValue(), I64Poison);
3744+
}
3745+
37273746
TEST_F(ValueAsMetadataTest, TempTempReplacement) {
37283747
// Create a constant.
37293748
ConstantAsMetadata *CI =

0 commit comments

Comments
 (0)