diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp index bbfed2ac2c090..74e8a849803d2 100644 --- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -661,8 +661,13 @@ ArgumentAccessInfo getArgumentAccessInfo(const Instruction *I, auto TypeSize = DL.getTypeStoreSize(Ty); if (!TypeSize.isScalable() && Offset) { int64_t Size = TypeSize.getFixedValue(); - return ConstantRange(APInt(64, *Offset, true), - APInt(64, *Offset + Size, true)); + APInt Low(64, *Offset, true); + bool Overflow; + APInt High = Low.sadd_ov(APInt(64, Size, true), Overflow); + // Bail if the range overflows signed 64-bit int. + if (Overflow) + return std::nullopt; + return ConstantRange(Low, High); } return std::nullopt; }; diff --git a/llvm/test/Transforms/FunctionAttrs/initializes.ll b/llvm/test/Transforms/FunctionAttrs/initializes.ll index 861c61d683ae0..937595b5e9b74 100644 --- a/llvm/test/Transforms/FunctionAttrs/initializes.ll +++ b/llvm/test/Transforms/FunctionAttrs/initializes.ll @@ -635,3 +635,17 @@ define void @memset_offset_1_size_0(ptr %dst, ptr %src) { call void @llvm.memmove.p0.p0.i64(ptr %dst.1, ptr %src, i64 0, i1 false) ret void } + +; We should bail if the range overflows a singed 64-bit int. +define void @range_overflows_signed_64_bit_int(ptr %arg) { +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) +; CHECK-LABEL: define void @range_overflows_signed_64_bit_int( +; CHECK-SAME: ptr writeonly captures(none) [[ARG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[GETELEMENTPTR:%.*]] = getelementptr i8, ptr [[ARG]], i64 9223372036854775804 +; CHECK-NEXT: store i32 0, ptr [[GETELEMENTPTR]], align 4 +; CHECK-NEXT: ret void +; + %getelementptr = getelementptr i8, ptr %arg, i64 9223372036854775804 + store i32 0, ptr %getelementptr + ret void +}