[llvm] [FunctionAttrs] Handle ConstantRange overflow in memset initializes inference (PR #145739)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 25 09:59:30 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Shivam Gupta (xgupta)
<details>
<summary>Changes</summary>
Avoid constructing invalid ConstantRange when Offset + Length in memset overflows signed 64-bit integer space. This prevents assertion failures when inferring the initializes attribute.
Fixes #<!-- -->140345
---
Full diff: https://github.com/llvm/llvm-project/pull/145739.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/IPO/FunctionAttrs.cpp (+16-5)
- (modified) llvm/test/Transforms/FunctionAttrs/initializes.ll (+14)
``````````diff
diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
index f918d7e059b63..8f6b68e97ee73 100644
--- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
@@ -57,6 +57,7 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Utils/Local.h"
@@ -675,11 +676,21 @@ ArgumentAccessInfo getArgumentAccessInfo(const Instruction *I,
[](Value *Length,
std::optional<int64_t> Offset) -> std::optional<ConstantRange> {
auto *ConstantLength = dyn_cast<ConstantInt>(Length);
- if (ConstantLength && Offset &&
- ConstantLength->getValue().isStrictlyPositive()) {
- return ConstantRange(
- APInt(64, *Offset, true),
- APInt(64, *Offset + ConstantLength->getSExtValue(), true));
+ if (ConstantLength && Offset) {
+ int64_t Off = *Offset;
+ int64_t Len = ConstantLength->getSExtValue();
+
+ // Reject zero or negative lengths
+ if (Len <= 0)
+ return std::nullopt;
+
+ int64_t High;
+ if (llvm::AddOverflow(Off, Len, High))
+ return std::nullopt;
+
+ APInt Low(64, Off, true);
+ APInt HighAP(64, High, true);
+ return ConstantRange(Low, HighAP);
}
return std::nullopt;
};
diff --git a/llvm/test/Transforms/FunctionAttrs/initializes.ll b/llvm/test/Transforms/FunctionAttrs/initializes.ll
index 5800bc1ca7864..193d0fd589884 100644
--- a/llvm/test/Transforms/FunctionAttrs/initializes.ll
+++ b/llvm/test/Transforms/FunctionAttrs/initializes.ll
@@ -649,3 +649,17 @@ define void @range_overflows_signed_64_bit_int(ptr %arg) {
store i32 0, ptr %getelementptr
ret void
}
+
+; We should bail if the memset range overflows a signed 64-bit int.
+define void @memset_large_offset_nonzero_size(ptr %dst) {
+; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
+; CHECK-LABEL: define void @memset_large_offset_nonzero_size(
+; CHECK-SAME: ptr writeonly captures(none) [[DST:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[OFFSET:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 9223372036854775805
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[OFFSET]], i8 0, i64 3, i1 false)
+; CHECK-NEXT: ret void
+;
+ %offset = getelementptr inbounds i8, ptr %dst, i64 9223372036854775805
+ call void @llvm.memset.p0.i64(ptr %offset, i8 0, i64 3, i1 false)
+ ret void
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/145739
More information about the llvm-commits
mailing list