summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Blaikie <dblaikie@gmail.com>2020-02-06 14:37:23 -0800
committerHans Wennborg <hans@chromium.org>2020-02-11 10:36:46 +0100
commit4e6ec0fff658cbe29e70f46491917202baa061c0 (patch)
tree596d33ed5e36fb0cc44ca8315a81835ae165a243
parent699e2a6c5551eacf10be7e64f579120954f55b10 (diff)
downloadbcm5719-llvm-4e6ec0fff658cbe29e70f46491917202baa061c0.tar.gz
bcm5719-llvm-4e6ec0fff658cbe29e70f46491917202baa061c0.zip
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 ba9cae58bbdd41451ee67773c9d0f90a01756f12)
-rw-r--r--llvm/docs/LangRef.rst4
-rw-r--r--llvm/lib/Linker/IRMover.cpp70
-rw-r--r--llvm/test/Linker/Inputs/module-max-warn.ll3
-rw-r--r--llvm/test/Linker/module-max-warn.ll12
4 files changed, 65 insertions, 24 deletions
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index a64974c2d90..0ae374de4b6 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -6114,7 +6114,9 @@ The following behaviors are supported:
* - 2
- **Warning**
Emits a warning if two values disagree. The result value will be the
- operand for the flag from the first module being linked.
+ operand for the flag from the first module being linked, or the max
+ if the other module uses **Max** (in which case the resulting flag
+ will be **Max**).
* - 3
- **Require**
diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp
index e13656ed1c1..af934cc8b9b 100644
--- a/llvm/lib/Linker/IRMover.cpp
+++ b/llvm/lib/Linker/IRMover.cpp
@@ -1277,11 +1277,17 @@ Error IRLinker::linkModuleFlagsMetadata() {
}
// Diagnose inconsistent merge behavior types.
- if (SrcBehaviorValue != DstBehaviorValue)
- return stringErr("linking module flags '" + ID->getString() +
- "': IDs have conflicting behaviors in '" +
- SrcM->getModuleIdentifier() + "' and '" +
- DstM.getModuleIdentifier() + "'");
+ if (SrcBehaviorValue != DstBehaviorValue) {
+ bool MaxAndWarn = (SrcBehaviorValue == Module::Max &&
+ DstBehaviorValue == Module::Warning) ||
+ (DstBehaviorValue == Module::Max &&
+ SrcBehaviorValue == Module::Warning);
+ if (!MaxAndWarn)
+ return stringErr("linking module flags '" + ID->getString() +
+ "': IDs have conflicting behaviors in '" +
+ SrcM->getModuleIdentifier() + "' and '" +
+ DstM.getModuleIdentifier() + "'");
+ }
auto replaceDstValue = [&](MDNode *New) {
Metadata *FlagOps[] = {DstOp->getOperand(0), ID, New};
@@ -1290,6 +1296,40 @@ Error IRLinker::linkModuleFlagsMetadata() {
Flags[ID].first = Flag;
};
+ // Emit a warning if the values differ and either source or destination
+ // request Warning behavior.
+ if ((DstBehaviorValue == Module::Warning ||
+ SrcBehaviorValue == Module::Warning) &&
+ SrcOp->getOperand(2) != DstOp->getOperand(2)) {
+ std::string Str;
+ raw_string_ostream(Str)
+ << "linking module flags '" << ID->getString()
+ << "': IDs have conflicting values ('" << *SrcOp->getOperand(2)
+ << "' from " << SrcM->getModuleIdentifier() << " with '"
+ << *DstOp->getOperand(2) << "' from " << DstM.getModuleIdentifier()
+ << ')';
+ emitWarning(Str);
+ }
+
+ // Choose the maximum if either source or destination request Max behavior.
+ if (DstBehaviorValue == Module::Max || SrcBehaviorValue == Module::Max) {
+ ConstantInt *DstValue =
+ mdconst::extract<ConstantInt>(DstOp->getOperand(2));
+ ConstantInt *SrcValue =
+ mdconst::extract<ConstantInt>(SrcOp->getOperand(2));
+
+ // The resulting flag should have a Max behavior, and contain the maximum
+ // value from between the source and destination values.
+ Metadata *FlagOps[] = {
+ (DstBehaviorValue != Module::Max ? SrcOp : DstOp)->getOperand(0), ID,
+ (SrcValue->getZExtValue() > DstValue->getZExtValue() ? SrcOp : DstOp)
+ ->getOperand(2)};
+ MDNode *Flag = MDNode::get(DstM.getContext(), FlagOps);
+ DstModFlags->setOperand(DstIndex, Flag);
+ Flags[ID].first = Flag;
+ continue;
+ }
+
// Perform the merge for standard behavior types.
switch (SrcBehaviorValue) {
case Module::Require:
@@ -1305,26 +1345,9 @@ Error IRLinker::linkModuleFlagsMetadata() {
continue;
}
case Module::Warning: {
- // Emit a warning if the values differ.
- if (SrcOp->getOperand(2) != DstOp->getOperand(2)) {
- std::string str;
- raw_string_ostream(str)
- << "linking module flags '" << ID->getString()
- << "': IDs have conflicting values ('" << *SrcOp->getOperand(2)
- << "' from " << SrcM->getModuleIdentifier() << " with '"
- << *DstOp->getOperand(2) << "' from " << DstM.getModuleIdentifier()
- << ')';
- emitWarning(str);
- }
- continue;
+ break;
}
case Module::Max: {
- ConstantInt *DstValue =
- mdconst::extract<ConstantInt>(DstOp->getOperand(2));
- ConstantInt *SrcValue =
- mdconst::extract<ConstantInt>(SrcOp->getOperand(2));
- if (SrcValue->getZExtValue() > DstValue->getZExtValue())
- overrideDstValue();
break;
}
case Module::Append: {
@@ -1350,6 +1373,7 @@ Error IRLinker::linkModuleFlagsMetadata() {
break;
}
}
+
}
// Check all of the requirements.
diff --git a/llvm/test/Linker/Inputs/module-max-warn.ll b/llvm/test/Linker/Inputs/module-max-warn.ll
new file mode 100644
index 00000000000..2d6a1004d19
--- /dev/null
+++ b/llvm/test/Linker/Inputs/module-max-warn.ll
@@ -0,0 +1,3 @@
+!llvm.module.flags = !{!0, !1}
+!0 = !{i32 2, !"Combine Max and Warn", i32 4}
+!1 = !{i32 7, !"Combine Warn and Max", i32 5}
diff --git a/llvm/test/Linker/module-max-warn.ll b/llvm/test/Linker/module-max-warn.ll
new file mode 100644
index 00000000000..b05688446ed
--- /dev/null
+++ b/llvm/test/Linker/module-max-warn.ll
@@ -0,0 +1,12 @@
+; RUN: llvm-link %s %p/Inputs/module-max-warn.ll -S -o - 2>&1 | FileCheck %s
+
+; 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)
+; 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)
+
+
+; CHECK: !0 = !{i32 7, !"Combine Max and Warn", i32 4}
+; CHECK: !1 = !{i32 7, !"Combine Warn and Max", i32 5}
+
+!llvm.module.flags = !{!0, !1}
+!0 = !{i32 7, !"Combine Max and Warn", i32 2}
+!1 = !{i32 2, !"Combine Warn and Max", i32 3}
OpenPOWER on IntegriCloud