[llvm] [SimplifyCFG] Enable sinking stores and loads with differing alignments (PR #215858)

Sayan Sivakumaran via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 12 11:50:06 PDT 2026


https://github.com/sivakusayan updated https://github.com/llvm/llvm-project/pull/215858

>From 9e13c19cb7fcc52d608b8a7166a5684745047b71 Mon Sep 17 00:00:00 2001
From: Sayan Sivakumaran <sivakusayan at gmail.com>
Date: Wed, 12 Aug 2026 13:12:12 -0500
Subject: [PATCH] [SimplifyCFG] Enable sinking stores and loads with differing
 alignments

---
 llvm/include/llvm/IR/Instruction.h        |  4 ++++
 llvm/lib/IR/Instruction.cpp               | 19 +++++++++++++++++++
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp |  5 +++--
 3 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h
index 13646ec66d6b3..3cbf109adc9fd 100644
--- a/llvm/include/llvm/IR/Instruction.h
+++ b/llvm/include/llvm/IR/Instruction.h
@@ -724,6 +724,10 @@ class Instruction : public User,
   /// V and this instruction.
   LLVM_ABI void andIRFlags(const Value *V);
 
+  /// Logical 'and' of any supported wrapping, exact, and fast-math flags of
+  /// V and this instruction, as well as finding a common alignment.
+  LLVM_ABI void andIRAnnotations(const Value *V);
+
   /// Merge 2 debug locations and apply it to the Instruction. If the
   /// instruction is a CallIns, we need to traverse the inline chain to find
   /// the common scope. This is not efficient for N-way merging as each time
diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp
index 099a54e684c96..030d168af99a2 100644
--- a/llvm/lib/IR/Instruction.cpp
+++ b/llvm/lib/IR/Instruction.cpp
@@ -768,6 +768,25 @@ void Instruction::copyIRFlags(const Value *V, bool IncludeWrapFlags) {
       DestICmp->setSameSign(SrcICmp->hasSameSign());
 }
 
+void Instruction::andIRAnnotations(const Value *V) {
+  andIRFlags(V);
+
+  auto HasLoadStoreAlignment = [](const Value *V) {
+    return isa<LoadInst>(V) || isa<StoreInst>(V);
+  };
+  if (HasLoadStoreAlignment(this) && HasLoadStoreAlignment(V)) {
+    Align ThisAlign = getLoadStoreAlignment(this);
+    Align OtherAlign = getLoadStoreAlignment(V);
+    Align Common = std::min(ThisAlign, OtherAlign);
+
+    assert(isAligned(Common, OtherAlign.value()) &&
+           "Common alignment doesn't satisfy other value's alignment?");
+    assert(isAligned(Common, ThisAlign.value()) &&
+           "Common alignment doesn't satisfy this value's alignment?");
+    setLoadStoreAlignment(this, Common);
+  }
+}
+
 void Instruction::andIRFlags(const Value *V) {
   if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) {
     if (isa<OverflowingBinaryOperator>(this)) {
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 089892dc573f3..950ec304affcc 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -2248,7 +2248,8 @@ static bool canSinkInstructions(
   const Instruction *I0 = Insts.front();
   const auto I0MMRA = MMRAMetadata(*I0);
   for (auto *I : Insts) {
-    if (!I->isSameOperationAs(I0, Instruction::CompareUsingIntersectedAttrs))
+    if (!I->isSameOperationAs(I0, Instruction::CompareUsingIntersectedAttrs |
+                                      Instruction::CompareIgnoringAlignment))
       return false;
 
     // Treat MMRAs conservatively. This pass can be quite aggressive and
@@ -2379,7 +2380,7 @@ static void sinkLastInstruction(ArrayRef<BasicBlock*> Blocks) {
       // instead of using complex API for N-way merge.
       I0->applyMergedLocation(I0->getDebugLoc(), I->getDebugLoc());
       combineMetadataForCSE(I0, I, true);
-      I0->andIRFlags(I);
+      I0->andIRAnnotations(I);
       if (auto *CB = dyn_cast<CallBase>(I0)) {
         bool Success = CB->tryIntersectAttributes(cast<CallBase>(I));
         assert(Success && "We should not be trying to sink callbases "



More information about the llvm-commits mailing list