[llvm] 93a1470 - [InstCombine] Remove redundant alignment assumptions. (#123348)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 12 05:45:41 PDT 2025
Author: Florian Hahn
Date: 2025-09-12T13:45:36+01:00
New Revision: 93a1470a97ec2c57247824ff2a59437831fea6de
URL: https://github.com/llvm/llvm-project/commit/93a1470a97ec2c57247824ff2a59437831fea6de
DIFF: https://github.com/llvm/llvm-project/commit/93a1470a97ec2c57247824ff2a59437831fea6de.diff
LOG: [InstCombine] Remove redundant alignment assumptions. (#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
PR: https://github.com/llvm/llvm-project/pull/123348
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
llvm/test/Analysis/BasicAA/featuretest.ll
llvm/test/Transforms/InstCombine/assume-align.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 33b66aeaffe60..11bac7bdb6eb2 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3385,12 +3385,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) {
@@ -3404,6 +3405,32 @@ 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 = getKnowledgeFromOperandInAssume(
+ *cast<AssumeInst>(II), II->arg_size() + Idx);
+ if (!RK || RK.AttrKind != Attribute::Alignment ||
+ !isPowerOf2_64(RK.ArgValue) || !isa<ConstantInt>(RK.IRArgValue))
+ continue;
+
+ // Don't try to remove align assumptions for pointers derived from
+ // arguments. We might lose information if the function gets inline and
+ // the align argument attribute disappears.
+ Value *UO = getUnderlyingObject(RK.WasOn);
+ if (!UO || isa<Argument>(UO))
+ continue;
+
+ // Compute known bits for the pointer, passing nullptr as context to
+ // avoid computeKnownBits using the assumption we are about to remove
+ // for reasoning.
+ KnownBits Known = computeKnownBits(RK.WasOn, /*CtxI=*/nullptr);
+ unsigned TZ = std::min(Known.countMinTrailingZeros(),
+ Value::MaxAlignmentExponent);
+ if ((1ULL << TZ) < RK.ArgValue)
+ continue;
+ return CallBase::removeOperandBundle(II, OBU.getTagID());
+ }
}
// Convert nonnull assume like:
diff --git a/llvm/test/Analysis/BasicAA/featuretest.ll b/llvm/test/Analysis/BasicAA/featuretest.ll
index e4cb009f0c633..04c4725d26c1d 100644
--- a/llvm/test/Analysis/BasicAA/featuretest.ll
+++ b/llvm/test/Analysis/BasicAA/featuretest.ll
@@ -15,24 +15,14 @@ declare void @llvm.assume(i1)
; operations on another array. Important for scientific codes.
;
define i32 @
diff erent_array_test(i64 %A, i64 %B) {
-; NO_ASSUME-LABEL: @
diff erent_array_test(
-; NO_ASSUME-NEXT: [[ARRAY11:%.*]] = alloca [100 x i32], align 4
-; NO_ASSUME-NEXT: [[ARRAY22:%.*]] = alloca [200 x i32], align 4
-; NO_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ARRAY11]], i32 4) ]
-; NO_ASSUME-NEXT: call void @external(ptr nonnull [[ARRAY11]])
-; NO_ASSUME-NEXT: call void @external(ptr nonnull [[ARRAY22]])
-; NO_ASSUME-NEXT: [[POINTER2:%.*]] = getelementptr i32, ptr [[ARRAY22]], i64 [[B:%.*]]
-; NO_ASSUME-NEXT: store i32 7, ptr [[POINTER2]], align 4
-; NO_ASSUME-NEXT: ret i32 0
-;
-; USE_ASSUME-LABEL: @
diff erent_array_test(
-; USE_ASSUME-NEXT: [[ARRAY11:%.*]] = alloca [100 x i32], align 4
-; USE_ASSUME-NEXT: [[ARRAY22:%.*]] = alloca [200 x i32], align 4
-; USE_ASSUME-NEXT: call void @external(ptr nonnull [[ARRAY11]])
-; USE_ASSUME-NEXT: call void @external(ptr nonnull [[ARRAY22]])
-; USE_ASSUME-NEXT: [[POINTER2:%.*]] = getelementptr i32, ptr [[ARRAY22]], i64 [[B:%.*]]
-; USE_ASSUME-NEXT: store i32 7, ptr [[POINTER2]], align 4
-; USE_ASSUME-NEXT: ret i32 0
+; CHECK-LABEL: @
diff erent_array_test(
+; CHECK-NEXT: [[ARRAY11:%.*]] = alloca [100 x i32], align 4
+; CHECK-NEXT: [[ARRAY22:%.*]] = alloca [200 x i32], align 4
+; CHECK-NEXT: call void @external(ptr nonnull [[ARRAY11]])
+; CHECK-NEXT: call void @external(ptr nonnull [[ARRAY22]])
+; CHECK-NEXT: [[POINTER2:%.*]] = getelementptr i32, ptr [[ARRAY22]], i64 [[B:%.*]]
+; CHECK-NEXT: store i32 7, ptr [[POINTER2]], align 4
+; CHECK-NEXT: ret i32 0
;
%Array1 = alloca i32, i32 100
%Array2 = alloca i32, i32 200
diff --git a/llvm/test/Transforms/InstCombine/assume-align.ll b/llvm/test/Transforms/InstCombine/assume-align.ll
index f0e0257433086..274632658496b 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]]
;
@@ -250,6 +248,19 @@ define ptr @redundant_assume_align_8_via_asume(ptr %p) {
}
declare void @foo(ptr)
+
+; !align must have a constant integer alignment.
+define ptr @assume_load_pointer_result(ptr %p, i64 %align) {
+; CHECK-LABEL: @assume_load_pointer_result(
+; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P:%.*]], align 8
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P2]], i64 [[ALIGN:%.*]]) ]
+; CHECK-NEXT: ret ptr [[P2]]
+;
+ %p2 = load ptr, ptr %p
+ call void @llvm.assume(i1 true) [ "align"(ptr %p2, i64 %align) ]
+ ret ptr %p2
+}
+
;.
; CHECK: [[META0]] = !{i64 8}
;.
More information about the llvm-commits
mailing list