Skip to content

Commit 4233a15

Browse files
committed
[FunctionAttrs] Handle zero writes in initializes inference.
ConstantRange's constructor asserts that the range not empty, except if lower/upper are min or max values. Check if the length is strictly positive instead of just non-negative so std::nullopt is returned when the size is 0. If that's the case, the access doesn't initialize anything. This should fix a crash when building on macOS with ASan & UBsan after #97373 / #117104 landed: https://green.lab.llvm.org/job/llvm.org/job/clang-stage2-cmake-RgSan/664/console
1 parent 2b1e037 commit 4233a15

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

llvm/lib/Transforms/IPO/FunctionAttrs.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,10 +633,12 @@ ArgumentAccessInfo getArgmentAccessInfo(const Instruction *I,
633633
[](Value *Length,
634634
std::optional<int64_t> Offset) -> std::optional<ConstantRange> {
635635
auto *ConstantLength = dyn_cast<ConstantInt>(Length);
636-
if (ConstantLength && Offset && !ConstantLength->isNegative())
636+
if (ConstantLength && Offset &&
637+
ConstantLength->getValue().isStrictlyPositive()) {
637638
return ConstantRange(
638639
APInt(64, *Offset, true),
639640
APInt(64, *Offset + ConstantLength->getSExtValue(), true));
641+
}
640642
return std::nullopt;
641643
};
642644
if (auto *SI = dyn_cast<StoreInst>(I)) {

llvm/test/Transforms/FunctionAttrs/initializes.ll

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,3 +611,27 @@ define void @caller_byval(ptr %p) {
611611
call void @callee_byval(ptr byval(i32) %p)
612612
ret void
613613
}
614+
615+
define void @memset_offset_0_size_0(ptr %dst, ptr %src) {
616+
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)
617+
; CHECK-LABEL: define void @memset_offset_0_size_0(
618+
; CHECK-SAME: ptr nocapture writeonly [[DST:%.*]], ptr nocapture readonly [[SRC:%.*]]) #[[ATTR1]] {
619+
; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr [[DST]], ptr [[SRC]], i64 0, i1 false)
620+
; CHECK-NEXT: ret void
621+
;
622+
call void @llvm.memmove.p0.p0.i64(ptr %dst, ptr %src, i64 0, i1 false)
623+
ret void
624+
}
625+
626+
define void @memset_offset_1_size_0(ptr %dst, ptr %src) {
627+
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)
628+
; CHECK-LABEL: define void @memset_offset_1_size_0(
629+
; CHECK-SAME: ptr nocapture writeonly [[DST:%.*]], ptr nocapture readonly [[SRC:%.*]]) #[[ATTR1]] {
630+
; CHECK-NEXT: [[DST_1:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 1
631+
; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr [[DST_1]], ptr [[SRC]], i64 0, i1 false)
632+
; CHECK-NEXT: ret void
633+
;
634+
%dst.1 = getelementptr inbounds i8, ptr %dst, i64 1
635+
call void @llvm.memmove.p0.p0.i64(ptr %dst.1, ptr %src, i64 0, i1 false)
636+
ret void
637+
}

0 commit comments

Comments
 (0)