[llvm] [InstCombine] Try folding align assumes with unkown offset (PR #204962)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Jun 20 23:41:55 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
@llvm/pr-subscribers-llvm-ir
Author: Nikolas Klauser (philnik777)
<details>
<summary>Changes</summary>
There are a few folds which don't depend on the offset of the alignment, but are nevertheless guarded on whether the offset is known. Run these folds unconditionally instead.
---
Full diff: https://github.com/llvm/llvm-project/pull/204962.diff
5 Files Affected:
- (modified) llvm/include/llvm/IR/BundleAttributes.h (+1)
- (modified) llvm/lib/Analysis/ValueTracking.cpp (+1-1)
- (modified) llvm/lib/IR/BundleAttributes.cpp (+4-2)
- (modified) llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp (+6-3)
- (modified) llvm/test/Transforms/InstCombine/assume.ll (+26)
``````````diff
diff --git a/llvm/include/llvm/IR/BundleAttributes.h b/llvm/include/llvm/IR/BundleAttributes.h
index a456be4aa7a9a..dd43d4ed276ea 100644
--- a/llvm/include/llvm/IR/BundleAttributes.h
+++ b/llvm/include/llvm/IR/BundleAttributes.h
@@ -30,6 +30,7 @@ inline BundleAttr getBundleAttrFromOBU(OperandBundleUse OBU) {
struct AssumeAlignInfo {
const Use &Ptr;
const Use &Alignment;
+ const Use *Offset;
std::optional<uint64_t> AlignmentVal;
std::optional<uint64_t> OffsetVal;
};
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 9334551005224..70345319ed57d 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1075,7 +1075,7 @@ void llvm::computeKnownBitsFromContext(const Value *V, KnownBits &Known,
if (Elem.Index != AssumptionCache::ExprResultIdx) {
if (auto OBU = I->getOperandBundleAt(Elem.Index);
getBundleAttrFromOBU(OBU) == BundleAttr::Align) {
- auto [Ptr, _, Alignment, Offset] = getAssumeAlignInfo(OBU);
+ auto [Ptr, _, _2, Alignment, Offset] = getAssumeAlignInfo(OBU);
if (Ptr == V && Alignment && Offset && isPowerOf2_64(*Alignment) &&
isValidAssumeForContext(I, Q)) {
Known.Zero |= (*Alignment - 1) & ~*Offset;
diff --git a/llvm/lib/IR/BundleAttributes.cpp b/llvm/lib/IR/BundleAttributes.cpp
index 2beb57c6dd710..4a6ed18714c2c 100644
--- a/llvm/lib/IR/BundleAttributes.cpp
+++ b/llvm/lib/IR/BundleAttributes.cpp
@@ -39,10 +39,12 @@ BundleAttr llvm::getBundleAttrFromID(uint32_t ID) {
AssumeAlignInfo llvm::getAssumeAlignInfo(OperandBundleUse OBU) {
assert(OBU.getTagID() == LLVMContext::OB_Align && OBU.Inputs.size() >= 2 &&
OBU.Inputs.size() <= 3);
- AssumeAlignInfo Ret{OBU.Inputs[0], OBU.Inputs[1], std::nullopt, std::nullopt};
+ AssumeAlignInfo Ret{OBU.Inputs[0], OBU.Inputs[1], nullptr, std::nullopt,
+ std::nullopt};
if (auto *Align = dyn_cast<ConstantInt>(OBU.Inputs[1]))
Ret.AlignmentVal = Align->getZExtValue();
if (OBU.Inputs.size() == 3) {
+ Ret.Offset = &OBU.Inputs[2];
if (auto *Offset = dyn_cast<ConstantInt>(OBU.Inputs[2]))
Ret.OffsetVal = Offset->getZExtValue();
} else {
@@ -83,7 +85,7 @@ bool llvm::assumeBundleImpliesNonNull(const Value *Val, const Function *Context,
OperandBundleUse OBU) {
switch (getBundleAttrFromOBU(OBU)) {
case BundleAttr::Align: {
- auto [Ptr, _, Alignment, Offset] = getAssumeAlignInfo(OBU);
+ auto [Ptr, _, _2, Alignment, Offset] = getAssumeAlignInfo(OBU);
return Ptr == Val && Alignment && Offset && isPowerOf2_64(*Alignment) &&
*Offset % *Alignment != 0;
}
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 6992602f54fe9..ce9e4b836a56e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3701,9 +3701,9 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
llvm_unreachable("Unexpected Attribute");
case BundleAttr::Align: {
// Try to remove redundant alignment assumptions.
- auto [Ptr, _, Alignment, Offset] = getAssumeAlignInfo(OBU);
+ auto [Ptr, _, OffsetPtr, Alignment, Offset] = getAssumeAlignInfo(OBU);
- if (!Alignment || !Offset)
+ if (!Alignment)
break;
// Remove align 1 and non-power-of-two bundles; they don't add any
@@ -3716,10 +3716,13 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
GEP->getMaxPreservedAlignment(getDataLayout()) >= *Alignment) {
Builder.CreateAlignmentAssumption(
getDataLayout(), GEP->getPointerOperand(), *Alignment,
- *Offset == 0 ? nullptr : Builder.getInt64(*Offset));
+ OffsetPtr ? const_cast<Value *>(OffsetPtr->get()) : nullptr);
return RemoveBundle();
}
+ if (!Offset)
+ break;
+
Value *BasePtr;
const APInt *PtrOffset;
if (match(Ptr.get(), m_PtrAdd(m_Value(BasePtr), m_APInt(PtrOffset)))) {
diff --git a/llvm/test/Transforms/InstCombine/assume.ll b/llvm/test/Transforms/InstCombine/assume.ll
index 2d4d51b8bbe4b..69220811ac206 100644
--- a/llvm/test/Transforms/InstCombine/assume.ll
+++ b/llvm/test/Transforms/InstCombine/assume.ll
@@ -199,6 +199,16 @@ define void @align_on_gep_keeping_alignment(ptr %ptr, i64 %offset) {
ret void
}
+define void @align_on_gep_keeping_alignment_variable_offset(ptr %ptr, i64 %offset, i64 %offset2) {
+; CHECK-LABEL: @align_on_gep_keeping_alignment_variable_offset(
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[PTR:%.*]], i64 8, i64 [[OFFSET2:%.*]]) ]
+; CHECK-NEXT: ret void
+;
+ %ptr2 = getelementptr [8 x i8], ptr %ptr, i64 %offset
+ call void @llvm.assume(i1 true) [ "align"(ptr %ptr2, i64 8, i64 %offset2) ]
+ ret void
+}
+
define void @align_on_gep_not_keeping_alignment(ptr %ptr, i64 %offset) {
; CHECK-LABEL: @align_on_gep_not_keeping_alignment(
; CHECK-NEXT: [[PTR2:%.*]] = getelementptr [4 x i8], ptr [[PTR:%.*]], i64 [[OFFSET:%.*]]
@@ -242,6 +252,22 @@ define void @non_power_of_two_align(ptr %ptr) {
ret void
}
+define void @non_power_of_two_align_variable_offset(ptr %ptr, i64 %i) {
+; CHECK-LABEL: @non_power_of_two_align_variable_offset(
+; CHECK-NEXT: ret void
+;
+ call void @llvm.assume(i1 true) [ "align"(ptr %ptr, i64 3, i64 %i) ]
+ ret void
+}
+
+define void @align_1_variable_offset(ptr %ptr, i64 %i) {
+; CHECK-LABEL: @align_1_variable_offset(
+; CHECK-NEXT: ret void
+;
+ call void @llvm.assume(i1 true) [ "align"(ptr %ptr, i64 1, i64 %i) ]
+ ret void
+}
+
; Same check as in @foo1, but make sure it works if the assume is first too.
define i32 @foo2(ptr %a) #0 {
``````````
</details>
https://github.com/llvm/llvm-project/pull/204962
More information about the llvm-commits
mailing list