[llvm] [InstCombine] Remove redundant alignment assumptions. (PR #123348)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 17 06:23:27 PST 2025


https://github.com/fhahn created https://github.com/llvm/llvm-project/pull/123348

Use known bits to remove redundant alignment assumptions.

Libc++ now adds alignment assumptions for std::vector::begin() and std::vector::end(), so I  expect we will see quite a bit more assumptions in C++ [1]. Try to clean up some redundant ones to start with.

[1] https://github.com/llvm/llvm-project/pull/108961

>From 18fce217abfe1c8a6ec96c45a3ea96dfd9abb60b Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Tue, 17 Sep 2024 10:50:09 +0100
Subject: [PATCH] [InstCombine] Remove redundant alignment assumptions.

Use known bits to remove redundant alignment assumptions.

Libc++ now adds alignment assumptions for std::vector::begin() and
std::vector::end(), so I  expect we will see quite a bit more
assumptions in C++ [1]. Try to clean up some redundant ones to start
with.

[1] https://github.com/llvm/llvm-project/pull/108961
---
 .../InstCombine/InstCombineCalls.cpp          | 31 ++++++++++++++++---
 .../Transforms/InstCombine/assume-align.ll    |  5 +--
 2 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 842881156dc67f..ab628e94235913 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3199,12 +3199,13 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
       // TODO: apply range metadata for range check patterns?
     }
 
-    // Separate storage assumptions apply to the underlying allocations, not any
-    // particular pointer within them. When evaluating the hints for AA purposes
-    // we getUnderlyingObject them; by precomputing the answers here we can
-    // avoid having to do so repeatedly there.
     for (unsigned Idx = 0; Idx < II->getNumOperandBundles(); Idx++) {
       OperandBundleUse OBU = II->getOperandBundleAt(Idx);
+
+      // Separate storage assumptions apply to the underlying allocations, not
+      // any particular pointer within them. When evaluating the hints for AA
+      // purposes we getUnderlyingObject them; by precomputing the answers here
+      // we can avoid having to do so repeatedly there.
       if (OBU.getTagName() == "separate_storage") {
         assert(OBU.Inputs.size() == 2);
         auto MaybeSimplifyHint = [&](const Use &U) {
@@ -3218,6 +3219,28 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
         MaybeSimplifyHint(OBU.Inputs[0]);
         MaybeSimplifyHint(OBU.Inputs[1]);
       }
+
+      // Try to remove redundant alignment assumptions.
+      if (OBU.getTagName() == "align" && OBU.Inputs.size() == 2) {
+        RetainedKnowledge RK = getKnowledgeFromBundle(
+            *cast<AssumeInst>(II), II->bundle_op_info_begin()[Idx]);
+        if (!RK || RK.AttrKind != Attribute::Alignment ||
+            !isPowerOf2_64(RK.ArgValue))
+          continue;
+
+        // Try to get the instruction before the assumption to use as context.
+        Instruction *CtxI = nullptr;
+        if (CtxI && II->getParent()->begin() != II->getIterator())
+          CtxI = II->getPrevNode();
+
+        auto Known = computeKnownBits(RK.WasOn, 1, CtxI);
+        unsigned KnownAlign = 1 << Known.countMinTrailingZeros();
+        if (KnownAlign < RK.ArgValue)
+          continue;
+
+        auto *New = CallBase::removeOperandBundle(II, OBU.getTagID());
+        return New;
+      }
     }
 
     // Convert nonnull assume like:
diff --git a/llvm/test/Transforms/InstCombine/assume-align.ll b/llvm/test/Transforms/InstCombine/assume-align.ll
index f0e02574330861..962ad4f792a0d1 100644
--- a/llvm/test/Transforms/InstCombine/assume-align.ll
+++ b/llvm/test/Transforms/InstCombine/assume-align.ll
@@ -175,7 +175,6 @@ define ptr @dont_fold_assume_align_zero_of_loaded_pointer_into_align_metadata(pt
 define ptr @redundant_assume_align_1(ptr %p) {
 ; CHECK-LABEL: @redundant_assume_align_1(
 ; CHECK-NEXT:    [[P2:%.*]] = load ptr, ptr [[P:%.*]], align 8
-; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[P2]], i32 1) ]
 ; CHECK-NEXT:    call void @foo(ptr [[P2]])
 ; CHECK-NEXT:    ret ptr [[P2]]
 ;
@@ -189,7 +188,6 @@ define ptr @redundant_assume_align_1(ptr %p) {
 define ptr @redundant_assume_align_8_via_align_metadata(ptr %p) {
 ; CHECK-LABEL: @redundant_assume_align_8_via_align_metadata(
 ; CHECK-NEXT:    [[P2:%.*]] = load ptr, ptr [[P:%.*]], align 8, !align [[META0:![0-9]+]]
-; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[P2]], i32 8) ]
 ; CHECK-NEXT:    call void @foo(ptr [[P2]])
 ; CHECK-NEXT:    ret ptr [[P2]]
 ;
@@ -214,8 +212,7 @@ define ptr @assume_align_16_via_align_metadata(ptr %p) {
 
 define ptr @redundant_assume_align_8_via_align_attribute(ptr align 8 %p) {
 ; CHECK-LABEL: @redundant_assume_align_8_via_align_attribute(
-; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[P:%.*]], i32 8) ]
-; CHECK-NEXT:    call void @foo(ptr [[P]])
+; CHECK-NEXT:    call void @foo(ptr [[P:%.*]])
 ; CHECK-NEXT:    ret ptr [[P]]
 ;
   call void @llvm.assume(i1 true) [ "align"(ptr %p, i32 8) ]



More information about the llvm-commits mailing list