diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp index 515893d079b8c..bdfbd8829186d 100644 --- a/llvm/lib/IR/Metadata.cpp +++ b/llvm/lib/IR/Metadata.cpp @@ -503,7 +503,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; diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp index 1570631287b2a..767dd1a59d2b9 100644 --- a/llvm/unittests/IR/MetadataTest.cpp +++ b/llvm/unittests/IR/MetadataTest.cpp @@ -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 =