[llvm] [IR] Only follow ptr/ptr-vector sources in stripAndAccumulateConstantOffsets bitcasts (PR #203356)

Anshil Gandhi via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 17 00:03:11 PDT 2026


https://github.com/gandhi56 updated https://github.com/llvm/llvm-project/pull/203356

>From dce928c03d46dbc29fc33a15588256de16840452 Mon Sep 17 00:00:00 2001
From: Anshil Gandhi <Anshil.Gandhi at amd.com>
Date: Thu, 11 Jun 2026 11:59:14 -0500
Subject: [PATCH] [IR] Only follow ptr (or ptr-vector) sources in
 stripAndAccumulateConstantOffsets bitcasts

stripAndAccumulateConstantOffsets used to walk through every bitcast operand.
If the operand was not a pointer (e.g. a same-sized byte type such as b64
reinterpreted as ptr), the walk could continue and violate the invariant that
the stripped value remains ptr or ptr-vector.

Align with stripPointerCastsAndOffsets: only look through bitcasts whose
source type is a pointer or pointer vector; keep addrspacecast as its own case.

This commit is needed in PR #177908.
---
 llvm/lib/IR/Value.cpp                          | 16 ++++++++++------
 llvm/test/Transforms/InferAlignment/bitcast.ll | 14 ++++++++++++++
 2 files changed, 24 insertions(+), 6 deletions(-)
 create mode 100644 llvm/test/Transforms/InferAlignment/bitcast.ll

diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp
index f944f546670de..d3f90bd81bbe2 100644
--- a/llvm/lib/IR/Value.cpp
+++ b/llvm/lib/IR/Value.cpp
@@ -784,17 +784,21 @@ const Value *Value::stripAndAccumulateConstantOffsets(
         }
       }
       V = GEP->getPointerOperand();
-    } else if (Operator::getOpcode(V) == Instruction::BitCast ||
-               Operator::getOpcode(V) == Instruction::AddrSpaceCast) {
+    } else if (Operator::getOpcode(V) == Instruction::BitCast) {
+      const Value *Src = cast<Operator>(V)->getOperand(0);
+      if (!Src->getType()->isPtrOrPtrVectorTy())
+        return V;
+      V = Src;
+    } else if (Operator::getOpcode(V) == Instruction::AddrSpaceCast) {
       V = cast<Operator>(V)->getOperand(0);
     } else if (auto *GA = dyn_cast<GlobalAlias>(V)) {
       if (!GA->isInterposable())
         V = GA->getAliasee();
     } else if (const auto *Call = dyn_cast<CallBase>(V)) {
-        if (const Value *RV = Call->getReturnedArgOperand())
-          V = RV;
-        if (AllowInvariantGroup && Call->isLaunderOrStripInvariantGroup())
-          V = Call->getArgOperand(0);
+      if (const Value *RV = Call->getReturnedArgOperand())
+        V = RV;
+      if (AllowInvariantGroup && Call->isLaunderOrStripInvariantGroup())
+        V = Call->getArgOperand(0);
     } else if (auto *Int2Ptr = dyn_cast<Operator>(V)) {
       // Try to accumulate across (inttoptr (add (ptrtoint p), off)).
       if (!AllowNonInbounds || !LookThroughIntToPtr || !Int2Ptr ||
diff --git a/llvm/test/Transforms/InferAlignment/bitcast.ll b/llvm/test/Transforms/InferAlignment/bitcast.ll
new file mode 100644
index 0000000000000..f77f244a19377
--- /dev/null
+++ b/llvm/test/Transforms/InferAlignment/bitcast.ll
@@ -0,0 +1,14 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -passes=infer-alignment -S | FileCheck %s
+
+define void @bitcast_b64_to_p1(b64 %b) {
+; CHECK-LABEL: define void @bitcast_b64_to_p1(
+; CHECK-SAME: b64 [[B:%.*]]) {
+; CHECK-NEXT:    [[P:%.*]] = bitcast b64 [[B]] to ptr addrspace(1)
+; CHECK-NEXT:    store i64 0, ptr addrspace(1) [[P]], align 4
+; CHECK-NEXT:    ret void
+;
+  %p = bitcast b64 %b to ptr addrspace(1)
+  store i64 0, ptr addrspace(1) %p
+  ret void
+}



More information about the llvm-commits mailing list