[llvm] [llvm] Optimize MachineMemOperand::getAlign with KnownBits information (PR #143872)

Acthinks Yang via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 12 04:16:36 PDT 2025


https://github.com/Acthinks created https://github.com/llvm/llvm-project/pull/143872

When using the `align_value` attribute, the original getAlign calculation (BaseAlign + Offset) cannot capture more precise alignment information after the load/store legalization phases (specifically after `expandUnalignedLoad`/`expandUnalignedStore` generate new load/store instructions).

Fixes#143215

>From 3bd2d07687b6953749cbb6e1a2b82793f7863cd3 Mon Sep 17 00:00:00 2001
From: Acthinks <yangzhh at mail.ustc.edu.cn>
Date: Thu, 12 Jun 2025 18:16:59 +0800
Subject: [PATCH] [llvm] Optimize MachineMemOperand::getAlign with KnownBits
 information

When using the `align_value` attribute, the original getAlign calculation
(BaseAlign + Offset) cannot capture more precise alignment information
after the load/store legalization phases (specifically after
`expandUnalignedLoad`/`expandUnalignedStore` generate new load/store
instructions).

Fixes#143215
---
 llvm/lib/CodeGen/MachineOperand.cpp           | 16 +++++++++++++++-
 .../SelectionDAG/SelectionDAGBuilder.cpp      |  4 ++++
 .../CodeGen/RISCV/unaligned-load-store.ll     | 19 +++++++++++++++++++
 3 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/MachineOperand.cpp b/llvm/lib/CodeGen/MachineOperand.cpp
index 0d251697f2567..0a5663a7e4ab2 100644
--- a/llvm/lib/CodeGen/MachineOperand.cpp
+++ b/llvm/lib/CodeGen/MachineOperand.cpp
@@ -14,6 +14,7 @@
 #include "llvm/ADT/StableHashing.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Analysis/Loads.h"
+#include "llvm/Analysis/ValueTracking.h"
 #include "llvm/CodeGen/MIRFormatter.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineJumpTableInfo.h"
@@ -1136,7 +1137,20 @@ void MachineMemOperand::refineAlignment(const MachineMemOperand *MMO) {
 /// getAlign - Return the minimum known alignment in bytes of the
 /// actual memory reference.
 Align MachineMemOperand::getAlign() const {
-  return commonAlignment(getBaseAlign(), getOffset());
+  Align RetAlign = commonAlignment(getBaseAlign(), getOffset());
+  if (const Value *V = getValue()) {
+    if (auto *I = dyn_cast<Instruction>(V)) {
+      DataLayout DL = I->getDataLayout();
+      unsigned PtrWidth = DL.getPointerTypeSizeInBits(V->getType());
+      KnownBits Known(PtrWidth);
+      llvm::computeKnownBits(V, Known, DL);
+      Known = KnownBits::add(
+          Known, KnownBits::makeConstant(APInt(PtrWidth, getOffset())));
+      unsigned AlignBits = Known.countMinTrailingZeros();
+      RetAlign = std::max(Align(1ull << std::min(31U, AlignBits)), RetAlign);
+    }
+  }
+  return RetAlign;
 }
 
 void MachineMemOperand::print(raw_ostream &OS, ModuleSlotTracker &MST,
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index e6a1dc930685c..278a3a12bfbc6 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -11848,6 +11848,10 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
           OutVal = DAG.getNode(ISD::AssertNoFPClass, dl, OutVal.getValueType(),
                                OutVal, SDNoFPClass);
         }
+        if (Arg.hasAttribute(Attribute::Alignment)) {
+          OutVal =
+              DAG.getAssertAlign(dl, OutVal, Arg.getParamAlign().valueOrOne());
+        }
         ArgValues.push_back(OutVal);
       }
 
diff --git a/llvm/test/CodeGen/RISCV/unaligned-load-store.ll b/llvm/test/CodeGen/RISCV/unaligned-load-store.ll
index c9c49e8f7f532..af83f434171c1 100644
--- a/llvm/test/CodeGen/RISCV/unaligned-load-store.ll
+++ b/llvm/test/CodeGen/RISCV/unaligned-load-store.ll
@@ -578,5 +578,24 @@ define void @store_large_constant(ptr %x) {
   store i64 18364758544493064720, ptr %x, align 1
   ret void
 }
+
+define void @store_const_with_align_attribute(ptr align 2 %p) {
+; SLOW-LABEL: store_const_with_align_attribute:
+; SLOW:       # %bb.0: # %entry
+; SLOW-NEXT:    sb zero, 3(a0)
+; SLOW-NEXT:    sh zero, 4(a0)
+; SLOW-NEXT:    sb zero, 6(a0)
+; SLOW-NEXT:    ret
+;
+; FAST-LABEL: store_const_with_align_attribute:
+; FAST:       # %bb.0: # %entry
+; FAST-NEXT:    sw zero, 3(a0)
+; FAST-NEXT:    ret
+entry:
+  %len = getelementptr inbounds nuw i8, ptr %p, i32 3
+  store i32 0, ptr %len, align 1
+  ret void
+}
+
 ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
 ; SLOWZBKB: {{.*}}



More information about the llvm-commits mailing list