[llvm] [Triple] Ignore the vendor field for MinGW, wrt LTO/IR compatibility (PR #122801)
Martin Storsjö via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 13 13:48:07 PST 2025
https://github.com/mstorsjo created https://github.com/llvm/llvm-project/pull/122801
For MinGW environments, the regular C/C++ toolchains usually use "w64" for the vendor field in triples, while Rust toolchains usually use "pc" in the vendor field.
The differences in the vendor field have no bearing on whether the IR is compatible on this platform. (This probably goes for most other OSes as well, but limiting the scope of the change to the specific case.)
Add a unit test for the isCompatibleWith, including some existing test cases found in existing tests.
>From 94c70dbcd4743e0bbe846a5f31386be1c340051f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin at martin.st>
Date: Mon, 13 Jan 2025 00:08:12 +0200
Subject: [PATCH] [Triple] Ignore the vendor field for MinGW, wrt LTO/IR
compatibility
For MinGW environments, the regular C/C++ toolchains usually use
"w64" for the vendor field in triples, while Rust toolchains usually
use "pc" in the vendor field.
The differences in the vendor field have no bearing on whether the
IR is compatible on this platform. (This probably goes for most other
OSes as well, but limiting the scope of the change to the specific case.)
Add a unit test for the isCompatibleWith, including some existing
test cases found in existing tests.
---
llvm/lib/TargetParser/Triple.cpp | 21 +++++++++---
llvm/unittests/TargetParser/TripleTest.cpp | 38 ++++++++++++++++++++++
2 files changed, 54 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index 4c1de09e91f21c..855889ac05620d 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -2024,6 +2024,10 @@ bool Triple::isLittleEndian() const {
}
bool Triple::isCompatibleWith(const Triple &Other) const {
+ // On MinGW, C code is usually built with a "w64" vendor, while Rust
+ // often uses a "pc" vendor.
+ bool IgnoreVendor = isWindowsGNUEnvironment();
+
// ARM and Thumb triples are compatible, if subarch, vendor and OS match.
if ((getArch() == Triple::thumb && Other.getArch() == Triple::arm) ||
(getArch() == Triple::arm && Other.getArch() == Triple::thumb) ||
@@ -2034,17 +2038,24 @@ bool Triple::isCompatibleWith(const Triple &Other) const {
getVendor() == Other.getVendor() && getOS() == Other.getOS();
else
return getSubArch() == Other.getSubArch() &&
- getVendor() == Other.getVendor() && getOS() == Other.getOS() &&
+ (getVendor() == Other.getVendor() || IgnoreVendor) &&
+ getOS() == Other.getOS() &&
getEnvironment() == Other.getEnvironment() &&
getObjectFormat() == Other.getObjectFormat();
}
- // If vendor is apple, ignore the version number.
+ // If vendor is apple, ignore the version number (the environment field)
+ // and the object format.
if (getVendor() == Triple::Apple)
return getArch() == Other.getArch() && getSubArch() == Other.getSubArch() &&
- getVendor() == Other.getVendor() && getOS() == Other.getOS();
-
- return *this == Other;
+ (getVendor() == Other.getVendor() || IgnoreVendor) &&
+ getOS() == Other.getOS();
+
+ return getArch() == Other.getArch() && getSubArch() == Other.getSubArch() &&
+ (getVendor() == Other.getVendor() || IgnoreVendor) &&
+ getOS() == Other.getOS() &&
+ getEnvironment() == Other.getEnvironment() &&
+ getObjectFormat() == Other.getObjectFormat();
}
std::string Triple::merge(const Triple &Other) const {
diff --git a/llvm/unittests/TargetParser/TripleTest.cpp b/llvm/unittests/TargetParser/TripleTest.cpp
index 7fb7625f8c2d10..3217014aa69af7 100644
--- a/llvm/unittests/TargetParser/TripleTest.cpp
+++ b/llvm/unittests/TargetParser/TripleTest.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/TargetParser/Triple.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/VersionTuple.h"
#include "gtest/gtest.h"
@@ -2737,4 +2738,41 @@ TEST(TripleTest, DXILNormaizeWithVersion) {
EXPECT_EQ("dxilv1.0-pc-shadermodel5.0-compute",
Triple::normalize("dxil-shadermodel5.0-pc-compute"));
}
+
+TEST(TripleTest, isCompatibleWith) {
+ struct {
+ const char *A;
+ const char *B;
+ bool Result;
+ } Cases[] = {
+ {"armv7-linux-gnueabihf", "thumbv7-linux-gnueabihf", true},
+ {"armv4-none-unknown-eabi", "thumbv6-unknown-linux-gnueabihf", false},
+ {"x86_64-apple-macosx10.9.0", "x86_64-apple-macosx10.10.0", true},
+ {"x86_64-apple-macosx10.9.0", "i386-apple-macosx10.9.0", false},
+ {"x86_64-apple-macosx10.9.0", "x86_64h-apple-macosx10.9.0", true},
+ {"x86_64-unknown-linux-gnu", "x86_64-unknown-linux-gnu", true},
+ {"x86_64-unknown-linux-gnu", "i386-unknown-linux-gnu", false},
+ {"x86_64-unknown-linux-gnu", "x86_64h-unknown-linux-gnu", true},
+ {"x86_64-pc-windows-gnu", "x86_64-pc-windows-msvc", false},
+ {"x86_64-pc-windows-msvc", "x86_64-pc-windows-msvc-elf", false},
+ {"i686-w64-windows-gnu", "i386-w64-windows-gnu", true},
+ {"x86_64-w64-windows-gnu", "x86_64-pc-windows-gnu", true},
+ {"armv7-w64-windows-gnu", "thumbv7-pc-windows-gnu", true},
+ };
+
+ auto DoTest = [](const char *A, const char *B,
+ bool Result) -> testing::AssertionResult {
+ if (Triple(A).isCompatibleWith(Triple(B)) != Result) {
+ return testing::AssertionFailure()
+ << llvm::formatv("Triple {0} and {1} were expected to be {2}", A,
+ B, Result ? "compatible" : "incompatible");
+ }
+ return testing::AssertionSuccess();
+ };
+ for (const auto &C : Cases) {
+ EXPECT_TRUE(DoTest(C.A, C.B, C.Result));
+ // Test that the comparison is commutative.
+ EXPECT_TRUE(DoTest(C.B, C.A, C.Result));
+ }
+}
} // end anonymous namespace
More information about the llvm-commits
mailing list