Skip to content

Commit 4e6ec0f

Browse files
dwblaikiezmodem
authored andcommitted
IR Linking: Support merging Warning+Max module metadata flags
Summary: Debug Info Version was changed to use "Max" instead of "Warning" per the original design intent - but this maxes old/new IR unlinkable, since mismatched merge styles are a linking failure. It seems possible/maybe reasonable to actually support the combination of these two flags: Warn, but then use the maximum value rather than the first value/earlier module's value. Reviewers: tejohnson Differential Revision: https://reviews.llvm.org/D74257 (cherry picked from commit ba9cae5)
1 parent 699e2a6 commit 4e6ec0f

File tree

4 files changed

+65
-24
lines changed

4 files changed

+65
-24
lines changed

llvm/docs/LangRef.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6114,7 +6114,9 @@ The following behaviors are supported:
61146114
* - 2
61156115
- **Warning**
61166116
Emits a warning if two values disagree. The result value will be the
6117-
operand for the flag from the first module being linked.
6117+
operand for the flag from the first module being linked, or the max
6118+
if the other module uses **Max** (in which case the resulting flag
6119+
will be **Max**).
61186120

61196121
* - 3
61206122
- **Require**

llvm/lib/Linker/IRMover.cpp

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,11 +1277,17 @@ Error IRLinker::linkModuleFlagsMetadata() {
12771277
}
12781278

12791279
// Diagnose inconsistent merge behavior types.
1280-
if (SrcBehaviorValue != DstBehaviorValue)
1281-
return stringErr("linking module flags '" + ID->getString() +
1282-
"': IDs have conflicting behaviors in '" +
1283-
SrcM->getModuleIdentifier() + "' and '" +
1284-
DstM.getModuleIdentifier() + "'");
1280+
if (SrcBehaviorValue != DstBehaviorValue) {
1281+
bool MaxAndWarn = (SrcBehaviorValue == Module::Max &&
1282+
DstBehaviorValue == Module::Warning) ||
1283+
(DstBehaviorValue == Module::Max &&
1284+
SrcBehaviorValue == Module::Warning);
1285+
if (!MaxAndWarn)
1286+
return stringErr("linking module flags '" + ID->getString() +
1287+
"': IDs have conflicting behaviors in '" +
1288+
SrcM->getModuleIdentifier() + "' and '" +
1289+
DstM.getModuleIdentifier() + "'");
1290+
}
12851291

12861292
auto replaceDstValue = [&](MDNode *New) {
12871293
Metadata *FlagOps[] = {DstOp->getOperand(0), ID, New};
@@ -1290,6 +1296,40 @@ Error IRLinker::linkModuleFlagsMetadata() {
12901296
Flags[ID].first = Flag;
12911297
};
12921298

1299+
// Emit a warning if the values differ and either source or destination
1300+
// request Warning behavior.
1301+
if ((DstBehaviorValue == Module::Warning ||
1302+
SrcBehaviorValue == Module::Warning) &&
1303+
SrcOp->getOperand(2) != DstOp->getOperand(2)) {
1304+
std::string Str;
1305+
raw_string_ostream(Str)
1306+
<< "linking module flags '" << ID->getString()
1307+
<< "': IDs have conflicting values ('" << *SrcOp->getOperand(2)
1308+
<< "' from " << SrcM->getModuleIdentifier() << " with '"
1309+
<< *DstOp->getOperand(2) << "' from " << DstM.getModuleIdentifier()
1310+
<< ')';
1311+
emitWarning(Str);
1312+
}
1313+
1314+
// Choose the maximum if either source or destination request Max behavior.
1315+
if (DstBehaviorValue == Module::Max || SrcBehaviorValue == Module::Max) {
1316+
ConstantInt *DstValue =
1317+
mdconst::extract<ConstantInt>(DstOp->getOperand(2));
1318+
ConstantInt *SrcValue =
1319+
mdconst::extract<ConstantInt>(SrcOp->getOperand(2));
1320+
1321+
// The resulting flag should have a Max behavior, and contain the maximum
1322+
// value from between the source and destination values.
1323+
Metadata *FlagOps[] = {
1324+
(DstBehaviorValue != Module::Max ? SrcOp : DstOp)->getOperand(0), ID,
1325+
(SrcValue->getZExtValue() > DstValue->getZExtValue() ? SrcOp : DstOp)
1326+
->getOperand(2)};
1327+
MDNode *Flag = MDNode::get(DstM.getContext(), FlagOps);
1328+
DstModFlags->setOperand(DstIndex, Flag);
1329+
Flags[ID].first = Flag;
1330+
continue;
1331+
}
1332+
12931333
// Perform the merge for standard behavior types.
12941334
switch (SrcBehaviorValue) {
12951335
case Module::Require:
@@ -1305,26 +1345,9 @@ Error IRLinker::linkModuleFlagsMetadata() {
13051345
continue;
13061346
}
13071347
case Module::Warning: {
1308-
// Emit a warning if the values differ.
1309-
if (SrcOp->getOperand(2) != DstOp->getOperand(2)) {
1310-
std::string str;
1311-
raw_string_ostream(str)
1312-
<< "linking module flags '" << ID->getString()
1313-
<< "': IDs have conflicting values ('" << *SrcOp->getOperand(2)
1314-
<< "' from " << SrcM->getModuleIdentifier() << " with '"
1315-
<< *DstOp->getOperand(2) << "' from " << DstM.getModuleIdentifier()
1316-
<< ')';
1317-
emitWarning(str);
1318-
}
1319-
continue;
1348+
break;
13201349
}
13211350
case Module::Max: {
1322-
ConstantInt *DstValue =
1323-
mdconst::extract<ConstantInt>(DstOp->getOperand(2));
1324-
ConstantInt *SrcValue =
1325-
mdconst::extract<ConstantInt>(SrcOp->getOperand(2));
1326-
if (SrcValue->getZExtValue() > DstValue->getZExtValue())
1327-
overrideDstValue();
13281351
break;
13291352
}
13301353
case Module::Append: {
@@ -1350,6 +1373,7 @@ Error IRLinker::linkModuleFlagsMetadata() {
13501373
break;
13511374
}
13521375
}
1376+
13531377
}
13541378

13551379
// Check all of the requirements.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
!llvm.module.flags = !{!0, !1}
2+
!0 = !{i32 2, !"Combine Max and Warn", i32 4}
3+
!1 = !{i32 7, !"Combine Warn and Max", i32 5}

llvm/test/Linker/module-max-warn.ll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
; RUN: llvm-link %s %p/Inputs/module-max-warn.ll -S -o - 2>&1 | FileCheck %s
2+
3+
; CHECK: warning: linking module flags 'Combine Max and Warn': IDs have conflicting values ('i32 4' from {{.*}}/test/Linker/Inputs/module-max-warn.ll with 'i32 2' from llvm-link)
4+
; CHECK: warning: linking module flags 'Combine Warn and Max': IDs have conflicting values ('i32 5' from {{.*}}/test/Linker/Inputs/module-max-warn.ll with 'i32 3' from llvm-link)
5+
6+
7+
; CHECK: !0 = !{i32 7, !"Combine Max and Warn", i32 4}
8+
; CHECK: !1 = !{i32 7, !"Combine Warn and Max", i32 5}
9+
10+
!llvm.module.flags = !{!0, !1}
11+
!0 = !{i32 7, !"Combine Max and Warn", i32 2}
12+
!1 = !{i32 2, !"Combine Warn and Max", i32 3}

0 commit comments

Comments
 (0)