git: a4e0cb2fd99a - main - devel/llvm18: fix host dependent compiler output for i386

From: Brooks Davis <brooks_at_FreeBSD.org>
Date: Thu, 25 Jul 2024 22:00:39 UTC
The branch main has been updated by brooks:

URL: https://cgit.FreeBSD.org/ports/commit/?id=a4e0cb2fd99adef4cbd4f778be729a079a5f2dea

commit a4e0cb2fd99adef4cbd4f778be729a079a5f2dea
Author:     Brooks Davis <brooks@FreeBSD.org>
AuthorDate: 2024-07-25 22:00:32 +0000
Commit:     Brooks Davis <brooks@FreeBSD.org>
CommitDate: 2024-07-25 22:00:32 +0000

    devel/llvm18: fix host dependent compiler output for i386
    
    Merge fixes for a couple cases where the compiler generated different
    i386 code depending on the host.  In the base system this showed up as
    very small differences in a couple object files in buildworld for i386
    depending on the host architecture (i386 or amd64).
    
    PR:             276961
---
 devel/llvm18/Makefile                              |   2 +-
 .../files/patch-backport-freebsd-397c2693fa6       |  43 +++++++
 .../files/patch-backport-freebsd-55a2a91c5e1       | 128 +++++++++++++++++++++
 3 files changed, 172 insertions(+), 1 deletion(-)

diff --git a/devel/llvm18/Makefile b/devel/llvm18/Makefile
index 5148732975be..7f85ff1cdd4f 100644
--- a/devel/llvm18/Makefile
+++ b/devel/llvm18/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	llvm
 DISTVERSION=	18.1.8
-PORTREVISION=	0
+PORTREVISION=	1
 CATEGORIES=	devel lang
 MASTER_SITES=	https://github.com/llvm/llvm-project/releases/download/llvmorg-${DISTVERSION:S/rc/-rc/}/
 PKGNAMESUFFIX=	${LLVM_SUFFIX}
diff --git a/devel/llvm18/files/patch-backport-freebsd-397c2693fa6 b/devel/llvm18/files/patch-backport-freebsd-397c2693fa6
new file mode 100644
index 000000000000..f000829474ba
--- /dev/null
+++ b/devel/llvm18/files/patch-backport-freebsd-397c2693fa6
@@ -0,0 +1,43 @@
+commit 397c2693fa66508cb5e6b173650a1f3bc6c4dd4f
+Author: Dimitry Andric <dim@FreeBSD.org>
+Date:   Sun Jul 21 22:37:27 2024 +0200
+
+    Fix llvm register allocator for native/cross build differences
+    
+    Work around an issue in LLVM's register allocator, which can cause
+    slightly different i386 object files, when produced by a native or cross
+    build of clang.
+    
+    This adds another volatile qualifier to a float variable declaration in
+    the weightCalcHelper() function, which otherwise produces slightly
+    different float results on amd64 and i386 hosts. In turn, this can lead
+    to different (but equivalent) register choices, and thus non-identical
+    assembly code.
+    
+    See https://github.com/llvm/llvm-project/issues/99396 for more details.
+    
+    Note this is a temporary fix, meant to merge in time for 13.4. As soon
+    as upstream has a permanent solution we will import that.
+    
+    PR:             276961
+    Reported by:    cperciva
+    MFC after:      3 days
+
+diff --git llvm/lib/CodeGen/CalcSpillWeights.cpp llvm/lib/CodeGen/CalcSpillWeights.cpp
+index f3cb7fa5af61..afde8d001f88 100644
+--- llvm/lib/CodeGen/CalcSpillWeights.cpp
++++ llvm/lib/CodeGen/CalcSpillWeights.cpp
+@@ -256,7 +256,12 @@ float VirtRegAuxInfo::weightCalcHelper(LiveInterval &LI, SlotIndex *Start,
+       return -1.0f;
+     }
+ 
+-    float Weight = 1.0f;
++    // FreeBSD customization: similar to the HWeight declaration below, add a
++    // volatile qualifier to avoid slightly different weight results on amd64
++    // and i386 hosts, and possibly choosing different registers in the register
++    // allocator. See <https://github.com/llvm/llvm-project/issues/99396> for
++    // more details.
++    volatile float Weight = 1.0f;
+     if (IsSpillable) {
+       // Get loop info for mi.
+       if (MI->getParent() != MBB) {
diff --git a/devel/llvm18/files/patch-backport-freebsd-55a2a91c5e1 b/devel/llvm18/files/patch-backport-freebsd-55a2a91c5e1
new file mode 100644
index 000000000000..8843d3749348
--- /dev/null
+++ b/devel/llvm18/files/patch-backport-freebsd-55a2a91c5e1
@@ -0,0 +1,128 @@
+commit 55a2a91c5e1bb39dd625ba56597608883fbcb318
+Author: Dimitry Andric <dim@FreeBSD.org>
+Date:   Thu Jul 25 13:13:45 2024 +0200
+
+    Merge commit 28a2b85602a5 from llvm-project (by Kazu Hirata):
+    
+      [DeadStoreElimination] Use SmallSetVector (NFC) (#79410)
+    
+      The use of SmallSetVector saves 0.58% of heap allocations during the
+      compilation of a large preprocessed file, namely X86ISelLowering.cpp,
+      for the X86 target.  During the experiment, the final size of ToCheck
+      was 8 or less 88% of the time.
+    
+    Merge commit 9e95c4947d31 from llvm-project (by Nikita Popov):
+    
+      [DSE] Fix non-determinism due to address reuse (#84943)
+    
+      The malloc->calloc fold creates a new MemoryAccess, which may end of at
+      the same address as a previously deleted access inside SkipStores.
+    
+      To the most part, this is not a problem, because SkipStores is normally
+      only used together with MemDefs. Neither the old malloc access nor the
+      new calloc access will be part of MemDefs, so there is no problem here.
+    
+      However, SkipStores is also used in one more place: In the main DSE
+      loop, ToCheck entries are checked against it. Fix this by not using
+      SkipStores here, and instead using a separate set to track deletions
+      inside this loop. This way it is not affected by the calloc optimization
+      that happens outside it.
+    
+      This is all pretty ugly, but I haven't found another good way to fix it.
+      Suggestions welcome.
+    
+      No test case as I don't have a reliable DSE-only test-case for this.
+    
+      Fixes https://github.com/llvm/llvm-project/issues/84458.
+    
+    This fixes another possible difference in output when building i386
+    object files with a native or cross build of clang. (Specifically, the
+    file sbin/ipf/ipmon/ipmon.o.)
+    
+    PR:             276961
+    Reported by:    cperciva
+    MFC after:      3 days
+
+diff --git llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+index 380d65836553..f0f0f5f28025 100644
+--- llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
++++ llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+@@ -1697,7 +1697,9 @@ struct DSEState {
+ 
+   /// Delete dead memory defs and recursively add their operands to ToRemove if
+   /// they became dead.
+-  void deleteDeadInstruction(Instruction *SI) {
++  void
++  deleteDeadInstruction(Instruction *SI,
++                        SmallPtrSetImpl<MemoryAccess *> *Deleted = nullptr) {
+     MemorySSAUpdater Updater(&MSSA);
+     SmallVector<Instruction *, 32> NowDeadInsts;
+     NowDeadInsts.push_back(SI);
+@@ -1718,6 +1720,8 @@ struct DSEState {
+         if (IsMemDef) {
+           auto *MD = cast<MemoryDef>(MA);
+           SkipStores.insert(MD);
++          if (Deleted)
++            Deleted->insert(MD);
+           if (auto *SI = dyn_cast<StoreInst>(MD->getMemoryInst())) {
+             if (SI->getValueOperand()->getType()->isPointerTy()) {
+               const Value *UO = getUnderlyingObject(SI->getValueOperand());
+@@ -2111,7 +2115,12 @@ static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA,
+     unsigned WalkerStepLimit = MemorySSAUpwardsStepLimit;
+     unsigned PartialLimit = MemorySSAPartialStoreLimit;
+     // Worklist of MemoryAccesses that may be killed by KillingDef.
+-    SetVector<MemoryAccess *> ToCheck;
++    SmallSetVector<MemoryAccess *, 8> ToCheck;
++    // Track MemoryAccesses that have been deleted in the loop below, so we can
++    // skip them. Don't use SkipStores for this, which may contain reused
++    // MemoryAccess addresses.
++    SmallPtrSet<MemoryAccess *, 8> Deleted;
++    [[maybe_unused]] unsigned OrigNumSkipStores = State.SkipStores.size();
+     ToCheck.insert(KillingDef->getDefiningAccess());
+ 
+     bool Shortend = false;
+@@ -2119,7 +2128,7 @@ static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA,
+     // Check if MemoryAccesses in the worklist are killed by KillingDef.
+     for (unsigned I = 0; I < ToCheck.size(); I++) {
+       MemoryAccess *Current = ToCheck[I];
+-      if (State.SkipStores.count(Current))
++      if (Deleted.contains(Current))
+         continue;
+ 
+       std::optional<MemoryAccess *> MaybeDeadAccess = State.getDomMemoryDef(
+@@ -2166,7 +2175,7 @@ static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA,
+           continue;
+         LLVM_DEBUG(dbgs() << "DSE: Remove Dead Store:\n  DEAD: " << *DeadI
+                           << "\n  KILLER: " << *KillingI << '\n');
+-        State.deleteDeadInstruction(DeadI);
++        State.deleteDeadInstruction(DeadI, &Deleted);
+         ++NumFastStores;
+         MadeChange = true;
+       } else {
+@@ -2203,7 +2212,7 @@ static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA,
+               Shortend = true;
+               // Remove killing store and remove any outstanding overlap
+               // intervals for the updated store.
+-              State.deleteDeadInstruction(KillingSI);
++              State.deleteDeadInstruction(KillingSI, &Deleted);
+               auto I = State.IOLs.find(DeadSI->getParent());
+               if (I != State.IOLs.end())
+                 I->second.erase(DeadSI);
+@@ -2215,13 +2224,16 @@ static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA,
+         if (OR == OW_Complete) {
+           LLVM_DEBUG(dbgs() << "DSE: Remove Dead Store:\n  DEAD: " << *DeadI
+                             << "\n  KILLER: " << *KillingI << '\n');
+-          State.deleteDeadInstruction(DeadI);
++          State.deleteDeadInstruction(DeadI, &Deleted);
+           ++NumFastStores;
+           MadeChange = true;
+         }
+       }
+     }
+ 
++    assert(State.SkipStores.size() - OrigNumSkipStores == Deleted.size() &&
++           "SkipStores and Deleted out of sync?");
++
+     // Check if the store is a no-op.
+     if (!Shortend && State.storeIsNoop(KillingDef, KillingUndObj)) {
+       LLVM_DEBUG(dbgs() << "DSE: Remove No-Op Store:\n  DEAD: " << *KillingI