Skip to content

[InstCombine] Always fold alignment assumptions into operand bundles#177597

Merged
philnik777 merged 1 commit intollvm:mainfrom
philnik777:fold_align_assume
Jan 23, 2026
Merged

[InstCombine] Always fold alignment assumptions into operand bundles#177597
philnik777 merged 1 commit intollvm:mainfrom
philnik777:fold_align_assume

Conversation

@philnik777
Copy link
Copy Markdown
Contributor

No description provided.

@philnik777 philnik777 requested a review from nikic as a code owner January 23, 2026 14:48
@llvmbot llvmbot added llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms labels Jan 23, 2026
@llvmbot
Copy link
Copy Markdown
Member

llvmbot commented Jan 23, 2026

@llvm/pr-subscribers-llvm-transforms

Author: Nikolas Klauser (philnik777)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/177597.diff

4 Files Affected:

  • (modified) llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp (+1-2)
  • (modified) llvm/test/Transforms/InstCombine/assume-loop-align.ll (+2-8)
  • (modified) llvm/test/Transforms/InstCombine/assume.ll (+16-48)
  • (modified) llvm/test/Transforms/InstCombine/assume_inevitable.ll (+1-4)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 00b45545178ae..6b18e279e9596 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3671,8 +3671,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
     // into
     // call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64  Constant + 1)]
     uint64_t AlignMask = 1;
-    if (EnableKnowledgeRetention &&
-        (match(IIOperand, m_Not(m_Trunc(m_Value(A)))) ||
+    if ((match(IIOperand, m_Not(m_Trunc(m_Value(A)))) ||
          match(IIOperand,
                m_SpecificICmp(ICmpInst::ICMP_EQ,
                               m_And(m_Value(A), m_ConstantInt(AlignMask)),
diff --git a/llvm/test/Transforms/InstCombine/assume-loop-align.ll b/llvm/test/Transforms/InstCombine/assume-loop-align.ll
index 24fd343d1448e..7669d5bae5b08 100644
--- a/llvm/test/Transforms/InstCombine/assume-loop-align.ll
+++ b/llvm/test/Transforms/InstCombine/assume-loop-align.ll
@@ -10,14 +10,8 @@ target triple = "x86_64-unknown-linux-gnu"
 define void @foo(ptr %a, ptr %b) #0 {
 ; CHECK-LABEL: @foo(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[PTRINT:%.*]] = ptrtoint ptr [[A:%.*]] to i64
-; CHECK-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 63
-; CHECK-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
-; CHECK-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]])
-; CHECK-NEXT:    [[PTRINT1:%.*]] = ptrtoint ptr [[B:%.*]] to i64
-; CHECK-NEXT:    [[MASKEDPTR2:%.*]] = and i64 [[PTRINT1]], 63
-; CHECK-NEXT:    [[MASKCOND3:%.*]] = icmp eq i64 [[MASKEDPTR2]], 0
-; CHECK-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND3]])
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[A:%.*]], i64 64) ]
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[B:%.*]], i64 64) ]
 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
 ; CHECK:       for.body:
 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
diff --git a/llvm/test/Transforms/InstCombine/assume.ll b/llvm/test/Transforms/InstCombine/assume.ll
index cc87d6542fa12..a44c87149a98d 100644
--- a/llvm/test/Transforms/InstCombine/assume.ll
+++ b/llvm/test/Transforms/InstCombine/assume.ll
@@ -11,18 +11,10 @@ declare void @llvm.assume(i1) #1
 ; Check that the assume has not been removed:
 
 define i32 @align_to_bundle(ptr %a) #0 {
-; DEFAULT-LABEL: @align_to_bundle(
-; DEFAULT-NEXT:    [[T0:%.*]] = load i32, ptr [[A:%.*]], align 4
-; DEFAULT-NEXT:    [[PTRINT:%.*]] = ptrtoint ptr [[A]] to i64
-; DEFAULT-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31
-; DEFAULT-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
-; DEFAULT-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]])
-; DEFAULT-NEXT:    ret i32 [[T0]]
-;
-; BUNDLES-LABEL: @align_to_bundle(
-; BUNDLES-NEXT:    [[T0:%.*]] = load i32, ptr [[A:%.*]], align 4
-; BUNDLES-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i64 32) ]
-; BUNDLES-NEXT:    ret i32 [[T0]]
+; CHECK-LABEL: @align_to_bundle(
+; CHECK-NEXT:    [[T0:%.*]] = load i32, ptr [[A:%.*]], align 4
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i64 32) ]
+; CHECK-NEXT:    ret i32 [[T0]]
 ;
   %t0 = load i32, ptr %a, align 4
   %ptrint = ptrtoint ptr %a to i64
@@ -33,18 +25,10 @@ define i32 @align_to_bundle(ptr %a) #0 {
 }
 
 define i32 @align_to_bundle_ptrtoaddr(ptr %a) #0 {
-; DEFAULT-LABEL: @align_to_bundle_ptrtoaddr(
-; DEFAULT-NEXT:    [[T0:%.*]] = load i32, ptr [[A:%.*]], align 4
-; DEFAULT-NEXT:    [[PTRINT:%.*]] = ptrtoaddr ptr [[A]] to i64
-; DEFAULT-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31
-; DEFAULT-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
-; DEFAULT-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]])
-; DEFAULT-NEXT:    ret i32 [[T0]]
-;
-; BUNDLES-LABEL: @align_to_bundle_ptrtoaddr(
-; BUNDLES-NEXT:    [[T0:%.*]] = load i32, ptr [[A:%.*]], align 4
-; BUNDLES-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i64 32) ]
-; BUNDLES-NEXT:    ret i32 [[T0]]
+; CHECK-LABEL: @align_to_bundle_ptrtoaddr(
+; CHECK-NEXT:    [[T0:%.*]] = load i32, ptr [[A:%.*]], align 4
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i64 32) ]
+; CHECK-NEXT:    ret i32 [[T0]]
 ;
   %t0 = load i32, ptr %a, align 4
   %ptrint = ptrtoaddr ptr %a to i64
@@ -55,18 +39,10 @@ define i32 @align_to_bundle_ptrtoaddr(ptr %a) #0 {
 }
 
 define i32 @align_assume_trunc_cond(ptr %a) #0 {
-; DEFAULT-LABEL: @align_assume_trunc_cond(
-; DEFAULT-NEXT:    [[T0:%.*]] = load i32, ptr [[A:%.*]], align 4
-; DEFAULT-NEXT:    [[PTRINT:%.*]] = ptrtoint ptr [[A]] to i64
-; DEFAULT-NEXT:    [[TRUNC:%.*]] = trunc i64 [[PTRINT]] to i1
-; DEFAULT-NEXT:    [[MASKCOND:%.*]] = xor i1 [[TRUNC]], true
-; DEFAULT-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]])
-; DEFAULT-NEXT:    ret i32 [[T0]]
-;
-; BUNDLES-LABEL: @align_assume_trunc_cond(
-; BUNDLES-NEXT:    [[T0:%.*]] = load i32, ptr [[A:%.*]], align 4
-; BUNDLES-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i64 2) ]
-; BUNDLES-NEXT:    ret i32 [[T0]]
+; CHECK-LABEL: @align_assume_trunc_cond(
+; CHECK-NEXT:    [[T0:%.*]] = load i32, ptr [[A:%.*]], align 4
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i64 2) ]
+; CHECK-NEXT:    ret i32 [[T0]]
 ;
   %t0 = load i32, ptr %a, align 4
   %ptrint = ptrtoint ptr %a to i64
@@ -79,18 +55,10 @@ define i32 @align_assume_trunc_cond(ptr %a) #0 {
 ; Same check as in @foo1, but make sure it works if the assume is first too.
 
 define i32 @foo2(ptr %a) #0 {
-; DEFAULT-LABEL: @foo2(
-; DEFAULT-NEXT:    [[PTRINT:%.*]] = ptrtoint ptr [[A:%.*]] to i64
-; DEFAULT-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31
-; DEFAULT-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
-; DEFAULT-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]])
-; DEFAULT-NEXT:    [[T0:%.*]] = load i32, ptr [[A]], align 4
-; DEFAULT-NEXT:    ret i32 [[T0]]
-;
-; BUNDLES-LABEL: @foo2(
-; BUNDLES-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[A:%.*]], i64 32) ]
-; BUNDLES-NEXT:    [[T0:%.*]] = load i32, ptr [[A]], align 4
-; BUNDLES-NEXT:    ret i32 [[T0]]
+; CHECK-LABEL: @foo2(
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[A:%.*]], i64 32) ]
+; CHECK-NEXT:    [[T0:%.*]] = load i32, ptr [[A]], align 4
+; CHECK-NEXT:    ret i32 [[T0]]
 ;
   %ptrint = ptrtoint ptr %a to i64
   %maskedptr = and i64 %ptrint, 31
diff --git a/llvm/test/Transforms/InstCombine/assume_inevitable.ll b/llvm/test/Transforms/InstCombine/assume_inevitable.ll
index 5f27ff1e609ba..f899be41e0584 100644
--- a/llvm/test/Transforms/InstCombine/assume_inevitable.ll
+++ b/llvm/test/Transforms/InstCombine/assume_inevitable.ll
@@ -16,10 +16,7 @@ define i32 @assume_inevitable(ptr %a, ptr %b, ptr %c) {
 ; CHECK-NEXT:    [[M_A:%.*]] = call ptr @llvm.ptr.annotation.p0.p0(ptr nonnull [[M]], ptr nonnull @.str, ptr nonnull @.str1, i32 2, ptr null)
 ; CHECK-NEXT:    [[OBJSZ:%.*]] = call i64 @llvm.objectsize.i64.p0(ptr [[C:%.*]], i1 false, i1 false, i1 false)
 ; CHECK-NEXT:    store i64 [[OBJSZ]], ptr [[M_A]], align 4
-; CHECK-NEXT:    [[PTRINT:%.*]] = ptrtoint ptr [[A]] to i64
-; CHECK-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31
-; CHECK-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
-; CHECK-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]])
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i64 32) ]
 ; CHECK-NEXT:    ret i32 [[TMP0]]
 ;
 entry:

Copy link
Copy Markdown
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@philnik777 philnik777 merged commit b74e1bc into llvm:main Jan 23, 2026
14 checks passed
@philnik777 philnik777 deleted the fold_align_assume branch January 23, 2026 15:54
Harrish92 pushed a commit to Harrish92/llvm-project that referenced this pull request Jan 24, 2026
Icohedron pushed a commit to Icohedron/llvm-project that referenced this pull request Jan 29, 2026
@nico
Copy link
Copy Markdown
Contributor

nico commented Jan 30, 2026

Hello, this makes clang assert on this standalone repro:
clangassert.zip

nico added a commit that referenced this pull request Jan 30, 2026
@nico
Copy link
Copy Markdown
Contributor

nico commented Jan 30, 2026

Reverted in bc73157 for now.

@dtcxzyw
Copy link
Copy Markdown
Member

dtcxzyw commented Jan 30, 2026

Hello, this makes clang assert on this standalone repro: clangassert.zip

Reduced reproducer:

; bin/opt -passes=instcombine test.ll -S
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define void @_ZN2v88internal21debug_helper_internal26FillInUnknownHeapAddressesEPNS_12debug_helper13HeapAddressesEm(ptr %heap_addresses) {
entry:
  %0 = ptrtoint ptr %heap_addresses to i64
  %conv1.i = trunc i64 %0 to i32
  %cmp.i = icmp eq i32 0, %conv1.i
  call void @llvm.assume(i1 %cmp.i)
  ret void
}

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #0

attributes #0 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }
alignment assumptions should have 2 or 3 arguments
  call void @llvm.assume(i1 true) [ "align"(ptr %heap_addresses) ]
LLVM ERROR: Broken module found, compilation aborted!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
Stack dump:
0.      Program arguments: bin/opt -passes=instcombine reduced.ll -S
1.      Running pass "verify" on module "reduced.ll"
 #0 0x00007ffff7dfd4c2 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /data/zyw/dev/llvm-project/llvm/lib/Support/Unix/Signals.inc:846:3
 #1 0x00007ffff7dfa3fc llvm::sys::RunSignalHandlers() /data/zyw/dev/llvm-project/llvm/lib/Support/Signals.cpp:108:20
 #2 0x00007ffff7dfac21 SignalHandler(int, siginfo_t*, void*) /data/zyw/dev/llvm-project/llvm/lib/Support/Unix/Signals.inc:429:14
 #3 0x00007ffff7845330 (/lib/x86_64-linux-gnu/libc.so.6+0x45330)
 #4 0x00007ffff789eb2c __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x00007ffff789eb2c __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #6 0x00007ffff789eb2c pthread_kill ./nptl/pthread_kill.c:89:10
 #7 0x00007ffff784527e raise ./signal/../sysdeps/posix/raise.c:27:6
 #8 0x00007ffff78288ff abort ./stdlib/abort.c:81:7
 #9 0x00007ffff7c72ceb (/data/zyw/dev/llvm-build/bin/../lib/libLLVMSupport.so.23.0git+0x72ceb)
#10 0x00007ffff7d0cc25 (/data/zyw/dev/llvm-build/bin/../lib/libLLVMSupport.so.23.0git+0x10cc25)
#11 0x00007fffee90ffa1 llvm::SmallPtrSetIteratorImpl::AdvanceIfNotValid() /data/zyw/dev/llvm-project/llvm/lib/IR/Verifier.cpp:8321:23
#12 0x00007fffee90ffa1 llvm::SmallPtrSetIteratorImpl::SmallPtrSetIteratorImpl(void const* const*, void const* const*, llvm::DebugEpochBase const&) /data/zyw/dev/llvm-project/llvm/include/llvm/ADT/SmallPtrSet.h:288:22
#13 0x00007fffee90ffa1 _ZN4llvm19SmallPtrSetIteratorIPvECI4NS_23SmallPtrSetIteratorImplEEPKPKvS7_RKNS_14DebugEpochBaseE /data/zyw/dev/llvm-project/llvm/include/llvm/ADT/SmallPtrSet.h:343:34
#14 0x00007fffee90ffa1 llvm::SmallPtrSetImpl<void*>::makeIterator(void const* const*) const /data/zyw/dev/llvm-project/llvm/include/llvm/ADT/SmallPtrSet.h:492:45
#15 0x00007fffee90ffa1 llvm::SmallPtrSetImpl<void*>::insert(void*) /data/zyw/dev/llvm-project/llvm/include/llvm/ADT/SmallPtrSet.h:391:25
#16 0x00007fffee90ffa1 llvm::PreservedAnalyses::all() /data/zyw/dev/llvm-project/llvm/include/llvm/IR/Analysis.h:120:27
#17 0x00007fffee90ffa1 llvm::VerifierPass::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) /data/zyw/dev/llvm-project/llvm/lib/IR/Verifier.cpp:8323:33
#18 0x00007ffff7f8bf15 llvm::detail::PassModel<llvm::Module, llvm::VerifierPass, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) /data/zyw/dev/llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:92:3
#19 0x00007fffee8d42c6 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) /data/zyw/dev/llvm-project/llvm/include/llvm/IR/PassManagerImpl.h:80:18
#20 0x00007ffff7f97cdc llvm::SmallPtrSetImplBase::~SmallPtrSetImplBase() /data/zyw/dev/llvm-project/llvm/include/llvm/ADT/SmallPtrSet.h:89:5
#21 0x00007ffff7f97cdc llvm::SmallPtrSetImpl<llvm::AnalysisKey*>::~SmallPtrSetImpl() /data/zyw/dev/llvm-project/llvm/include/llvm/ADT/SmallPtrSet.h:368:35
#22 0x00007ffff7f97cdc llvm::SmallPtrSet<llvm::AnalysisKey*, 2u>::~SmallPtrSet() /data/zyw/dev/llvm-project/llvm/include/llvm/ADT/SmallPtrSet.h:527:7
#23 0x00007ffff7f97cdc llvm::PreservedAnalyses::~PreservedAnalyses() /data/zyw/dev/llvm-project/llvm/include/llvm/IR/Analysis.h:112:7
#24 0x00007ffff7f97cdc llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool, bool) /data/zyw/dev/llvm-project/llvm/tools/opt/NewPMDriver.cpp:574:10
#25 0x00007ffff7fa37c4 optMain /data/zyw/dev/llvm-project/llvm/tools/opt/optdriver.cpp:758:5
#26 0x00007ffff782a1ca __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3
#27 0x00007ffff782a28b call_init ./csu/../csu/libc-start.c:128:20
#28 0x00007ffff782a28b __libc_start_main ./csu/../csu/libc-start.c:347:5
#29 0x0000555555555095 _start (bin/opt+0x1095)
Aborted (core dumped)

llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Jan 30, 2026
philnik777 added a commit to philnik777/llvm-project that referenced this pull request Feb 3, 2026
… bundles (llvm#177597)"

Truncating at 32 bits is now avoided by removing a cast to `unsigned`.
This would also break at 64 bits, but I don't think LLVM supports such a
thing.

This reverts commit bc73157.
philnik777 added a commit to philnik777/llvm-project that referenced this pull request Feb 3, 2026
… bundles (llvm#177597)"

Truncating at 32 bits is now avoided by removing a cast to `unsigned`.
This would also break at 64 bits, but I don't think LLVM supports such a
thing.

This reverts commit bc73157.
philnik777 added a commit that referenced this pull request Feb 3, 2026
… bundles (#177597)" (#179497)

Truncating at 32 bits is now avoided by removing a cast to `unsigned`.
This would also break at 64 bits (with the pointer size > 64 bit), but I
don't think LLVM supports such a
thing.

This reverts commit bc73157.
moar55 pushed a commit to moar55/llvm-project that referenced this pull request Feb 3, 2026
… bundles (llvm#177597)" (llvm#179497)

Truncating at 32 bits is now avoided by removing a cast to `unsigned`.
This would also break at 64 bits (with the pointer size > 64 bit), but I
don't think LLVM supports such a
thing.

This reverts commit bc73157.
sshrestha-aa pushed a commit to sshrestha-aa/llvm-project that referenced this pull request Feb 4, 2026
sshrestha-aa pushed a commit to sshrestha-aa/llvm-project that referenced this pull request Feb 4, 2026
rishabhmadan19 pushed a commit to rishabhmadan19/llvm-project that referenced this pull request Feb 9, 2026
… bundles (llvm#177597)" (llvm#179497)

Truncating at 32 bits is now avoided by removing a cast to `unsigned`.
This would also break at 64 bits (with the pointer size > 64 bit), but I
don't think LLVM supports such a
thing.

This reverts commit bc73157.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants