[llvm] [InstCombine] Preserve access groups in mergeStoreIntoSuccessor (PR #214509)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 11 01:51:00 PDT 2026
https://github.com/mikaoP updated https://github.com/llvm/llvm-project/pull/214509
>From 63eb22ffed06dd45b4185ff824aa17f107734978 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ra=C3=BAl=20Pe=C3=B1acoba=20Veigas?= <rpenacob at bsc.es>
Date: Thu, 6 Aug 2026 16:52:25 +0200
Subject: [PATCH] [InstCombine] Preserve access groups in
mergeStoreIntoSuccessor
mergeStoreIntoSuccessor builds a fresh StoreInst and copies only AAMDNodes,
so !llvm.access.group is dropped even when both original stores carry the
same group.
llvm.loop.parallel_accesses is all-or-nothing: isAnnotatedParallel() requires
every memory operation in the loop to be a member, so one untagged store
de-parallelises the whole loop and LoopVectorize can refuse a loop that is
parallel by construction.
---
.../InstCombineLoadStoreAlloca.cpp | 5 ++
.../InstCombine/storemerge-access-group.ll | 77 +++++++++++++++++++
2 files changed, 82 insertions(+)
create mode 100644 llvm/test/Transforms/InstCombine/storemerge-access-group.ll
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
index 14ccd6b2dfa24..cafabdd489e82 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
@@ -16,6 +16,7 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/Loads.h"
+#include "llvm/Analysis/VectorUtils.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
@@ -1753,6 +1754,10 @@ bool InstCombinerImpl::mergeStoreIntoSuccessor(StoreInst &SI) {
if (AATags)
NewSI->setAAMetadata(AATags.merge(OtherStore->getAAMetadata()));
+ // If the two stores had access groups, intersect them.
+ NewSI->setMetadata(LLVMContext::MD_access_group,
+ intersectAccessGroups(&SI, OtherStore));
+
// Nuke the old stores.
eraseInstFromFunction(SI);
eraseInstFromFunction(*OtherStore);
diff --git a/llvm/test/Transforms/InstCombine/storemerge-access-group.ll b/llvm/test/Transforms/InstCombine/storemerge-access-group.ll
new file mode 100644
index 0000000000000..9fac55f4473cd
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/storemerge-access-group.ll
@@ -0,0 +1,77 @@
+; RUN: opt -passes=instcombine -S < %s | FileCheck %s
+
+; The store mergeStoreIntoSuccessor creates must keep the access groups both
+; original stores agree on, or the loop stops being annotated-parallel.
+
+; CHECK-LABEL: @merged_store_keeps_shared_access_group(
+; CHECK: store double %storemerge, ptr %q, align 8, !llvm.access.group [[ACC:![0-9]+]]
+define void @merged_store_keeps_shared_access_group(ptr noalias %dst, ptr noalias %src, i64 %n) {
+entry:
+ %guard = icmp sgt i64 %n, 0
+ br i1 %guard, label %loop, label %exit
+
+loop:
+ %i = phi i64 [ 0, %entry ], [ %i.next, %latch ]
+ %p = getelementptr inbounds double, ptr %src, i64 %i
+ %v = load double, ptr %p, align 8, !llvm.access.group !0
+ %q = getelementptr inbounds double, ptr %dst, i64 %i
+ %c = fcmp ogt double %v, 0.000000e+00
+ br i1 %c, label %then, label %else
+
+then:
+ store double %v, ptr %q, align 8, !llvm.access.group !0
+ br label %latch
+
+else:
+ store double 1.000000e+00, ptr %q, align 8, !llvm.access.group !0
+ br label %latch
+
+latch:
+ %i.next = add nuw nsw i64 %i, 1
+ %done = icmp eq i64 %i.next, %n
+ br i1 %done, label %exit, label %loop, !llvm.loop !1
+
+exit:
+ ret void
+}
+
+; If only one store is in the group, the merged store must not claim it.
+
+; CHECK-LABEL: @merged_store_drops_unshared_access_group(
+; CHECK: store double %storemerge, ptr %q, align 8
+; CHECK-NOT: !llvm.access.group
+define void @merged_store_drops_unshared_access_group(ptr noalias %dst, ptr noalias %src, i64 %n) {
+entry:
+ %guard = icmp sgt i64 %n, 0
+ br i1 %guard, label %loop, label %exit
+
+loop:
+ %i = phi i64 [ 0, %entry ], [ %i.next, %latch ]
+ %p = getelementptr inbounds double, ptr %src, i64 %i
+ %v = load double, ptr %p, align 8
+ %q = getelementptr inbounds double, ptr %dst, i64 %i
+ %c = fcmp ogt double %v, 0.000000e+00
+ br i1 %c, label %then, label %else
+
+then:
+ store double %v, ptr %q, align 8, !llvm.access.group !0
+ br label %latch
+
+else:
+ store double 1.000000e+00, ptr %q, align 8
+ br label %latch
+
+latch:
+ %i.next = add nuw nsw i64 %i, 1
+ %done = icmp eq i64 %i.next, %n
+ br i1 %done, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+; CHECK: [[ACC]] = distinct !{}
+
+!0 = distinct !{}
+!1 = distinct !{!1, !2}
+!2 = !{!"llvm.loop.parallel_accesses", !0}
More information about the llvm-commits
mailing list