Skip to content

Commit 6ed814a

Browse files
authored
[IR] Fix Module::setModuleFlag for uniqued metadata (#164580)
`Module::setModuleFlag` is supposed to change a single module. However, when an `MDNode` has the same value in more than one module in the same `LLVMContext`, such `MDNode` is shared (uniqued) across all of them. Therefore `MDNode::replaceOperandWith` changes all modules that share the same `MDNode`. This used to cause problems for #86212, where a module is marked as "upgraded" via a module flag. When this flag is shared across multiple modules, all of them are marked, yet some may not have been processed at all. After the patch we now construct a new `MDNode` and replace the old one.
1 parent 169626f commit 6ed814a

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

llvm/lib/IR/Module.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -403,9 +403,14 @@ void Module::setModuleFlag(ModFlagBehavior Behavior, StringRef Key,
403403
Metadata *Val) {
404404
NamedMDNode *ModFlags = getOrInsertModuleFlagsMetadata();
405405
// Replace the flag if it already exists.
406-
for (MDNode *Flag : ModFlags->operands()) {
406+
for (unsigned i = 0; i < ModFlags->getNumOperands(); ++i) {
407+
MDNode *Flag = ModFlags->getOperand(i);
407408
if (cast<MDString>(Flag->getOperand(1))->getString() == Key) {
408-
Flag->replaceOperandWith(2, Val);
409+
Type *Int32Ty = Type::getInt32Ty(Context);
410+
Metadata *Ops[3] = {
411+
ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Behavior)),
412+
MDString::get(Context, Key), Val};
413+
ModFlags->setOperand(i, MDNode::get(Context, Ops));
409414
return;
410415
}
411416
}

llvm/unittests/IR/ModuleTest.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,36 @@ TEST(ModuleTest, setModuleFlagInt) {
103103
EXPECT_EQ(Val2, A2->getZExtValue());
104104
}
105105

106+
TEST(ModuleTest, setModuleFlagTwoMod) {
107+
LLVMContext Context;
108+
Module MA("MA", Context);
109+
Module MB("MB", Context);
110+
StringRef Key = "Key";
111+
uint32_t Val1 = 1;
112+
uint32_t Val2 = 2;
113+
114+
// Set a flag to MA
115+
EXPECT_EQ(nullptr, MA.getModuleFlag(Key));
116+
MA.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val1);
117+
auto A1 = mdconst::extract_or_null<ConstantInt>(MA.getModuleFlag(Key));
118+
EXPECT_EQ(Val1, A1->getZExtValue());
119+
120+
// Set a flag to MB
121+
EXPECT_EQ(nullptr, MB.getModuleFlag(Key));
122+
MB.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val1);
123+
auto B1 = mdconst::extract_or_null<ConstantInt>(MB.getModuleFlag(Key));
124+
EXPECT_EQ(Val1, B1->getZExtValue());
125+
126+
// Change the flag of MA
127+
MA.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val2);
128+
auto A2 = mdconst::extract_or_null<ConstantInt>(MA.getModuleFlag(Key));
129+
EXPECT_EQ(Val2, A2->getZExtValue());
130+
131+
// MB should keep the original flag value
132+
auto B2 = mdconst::extract_or_null<ConstantInt>(MB.getModuleFlag(Key));
133+
EXPECT_EQ(Val1, B2->getZExtValue());
134+
}
135+
106136
const char *IRString = R"IR(
107137
!llvm.module.flags = !{!0}
108138

0 commit comments

Comments
 (0)