[llvm] [InferAlign] Eliminate `and ptr, -align` pattern (PR #171147)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 8 07:07:44 PST 2025


https://github.com/nikic created https://github.com/llvm/llvm-project/pull/171147

To complement the `and ptr, align-1 -> 0` pattern, also fold `and ptr, -align` to `ptr`.

>From f0a25df24df8695a6c2996a7b7f80e39a4d300fe Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Mon, 8 Dec 2025 16:06:08 +0100
Subject: [PATCH] [InferAlign] Eliminate `and ptr, -align` pattern

To complement the `and ptr, align-1 -> 0` pattern, also fold
`and ptr, -align` to `ptr`.
---
 llvm/lib/Transforms/Scalar/InferAlignment.cpp |  5 +++
 .../Transforms/InferAlignment/ptrtoint.ll     | 42 +++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/llvm/lib/Transforms/Scalar/InferAlignment.cpp b/llvm/lib/Transforms/Scalar/InferAlignment.cpp
index c0a147ed78231..93de58f7c8062 100644
--- a/llvm/lib/Transforms/Scalar/InferAlignment.cpp
+++ b/llvm/lib/Transforms/Scalar/InferAlignment.cpp
@@ -50,6 +50,11 @@ static bool tryToImproveAlign(
       I->replaceAllUsesWith(Constant::getNullValue(I->getType()));
       return true;
     }
+    if (Const->uge(
+            APInt::getBitsSetFrom(Const->getBitWidth(), Log2(ActualAlign)))) {
+      I->replaceAllUsesWith(I->getOperand(0));
+      return true;
+    }
   }
 
   IntrinsicInst *II = dyn_cast<IntrinsicInst>(I);
diff --git a/llvm/test/Transforms/InferAlignment/ptrtoint.ll b/llvm/test/Transforms/InferAlignment/ptrtoint.ll
index 3eb1f95d9c026..e4b30330e2220 100644
--- a/llvm/test/Transforms/InferAlignment/ptrtoint.ll
+++ b/llvm/test/Transforms/InferAlignment/ptrtoint.ll
@@ -62,3 +62,45 @@ define i64 @ptrtoaddr(ptr %ptr) {
   %v5 = and i64 %v3, 2
   ret i64 %v5
 }
+
+define i64 @redundant_mask(ptr %ptr) {
+; CHECK-LABEL: define i64 @redundant_mask(
+; CHECK-SAME: ptr [[PTR:%.*]]) {
+; CHECK-NEXT:    [[LOAD:%.*]] = load i32, ptr [[PTR]], align 4
+; CHECK-NEXT:    [[INT:%.*]] = ptrtoint ptr [[PTR]] to i64
+; CHECK-NEXT:    [[MASK:%.*]] = and i64 [[INT]], -4
+; CHECK-NEXT:    ret i64 [[INT]]
+;
+  %load = load i32, ptr %ptr, align 4
+  %int = ptrtoint ptr %ptr to i64
+  %mask = and i64 %int, -4
+  ret i64 %mask
+}
+
+define i64 @redundant_mask2(ptr %ptr) {
+; CHECK-LABEL: define i64 @redundant_mask2(
+; CHECK-SAME: ptr [[PTR:%.*]]) {
+; CHECK-NEXT:    [[LOAD:%.*]] = load i32, ptr [[PTR]], align 4
+; CHECK-NEXT:    [[INT:%.*]] = ptrtoint ptr [[PTR]] to i64
+; CHECK-NEXT:    [[MASK:%.*]] = and i64 [[INT]], -3
+; CHECK-NEXT:    ret i64 [[INT]]
+;
+  %load = load i32, ptr %ptr, align 4
+  %int = ptrtoint ptr %ptr to i64
+  %mask = and i64 %int, -3
+  ret i64 %mask
+}
+
+define i64 @not_redundant_mask(ptr %ptr) {
+; CHECK-LABEL: define i64 @not_redundant_mask(
+; CHECK-SAME: ptr [[PTR:%.*]]) {
+; CHECK-NEXT:    [[LOAD:%.*]] = load i32, ptr [[PTR]], align 4
+; CHECK-NEXT:    [[INT:%.*]] = ptrtoint ptr [[PTR]] to i64
+; CHECK-NEXT:    [[MASK:%.*]] = and i64 [[INT]], -5
+; CHECK-NEXT:    ret i64 [[MASK]]
+;
+  %load = load i32, ptr %ptr, align 4
+  %int = ptrtoint ptr %ptr to i64
+  %mask = and i64 %int, -5
+  ret i64 %mask
+}



More information about the llvm-commits mailing list