[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