// transform it into a store of the expanded constant value.
if (MemSetInst *MSI = dyn_cast<MemSetInst>(User)) {
assert(MSI->getRawDest() == Ptr && "Consistency error!");
- unsigned NumBytes = cast<ConstantInt>(MSI->getLength())->getZExtValue();
- if (NumBytes != 0) {
+ signed SNumBytes = cast<ConstantInt>(MSI->getLength())->getSExtValue();
+ if (SNumBytes > 0) {
+ unsigned NumBytes = static_cast<unsigned>(SNumBytes);
unsigned Val = cast<ConstantInt>(MSI->getValue())->getZExtValue();
// Compute the value replicated the right number of times.
ConstantInt *Length = dyn_cast<ConstantInt>(MI->getLength());
if (Length == 0)
return MarkUnsafe(Info, User);
+ if (Length->isNegative())
+ return MarkUnsafe(Info, User);
+
isSafeMemAccess(Offset, Length->getZExtValue(), 0,
UI.getOperandNo() == 0, Info, MI,
true /*AllowWholeAccess*/);
--- /dev/null
+; PR12202\r
+; RUN: opt < %s -scalarrepl -S\r
+; Ensure that we do not hang or crash when feeding a negative value to memset\r
+\r
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S32"\r
+target triple = "i686-pc-win32"\r
+\r
+define i32 @test() nounwind {\r
+entry:\r
+ %retval = alloca i32, align 4\r
+ %buff = alloca [1 x i8], align 1\r
+ store i32 0, i32* %retval\r
+ %0 = bitcast [1 x i8]* %buff to i8*\r
+ call void @llvm.memset.p0i8.i32(i8* %0, i8 0, i32 1, i32 1, i1 false)\r
+ %arraydecay = getelementptr inbounds [1 x i8]* %buff, i32 0, i32 0\r
+ call void @llvm.memset.p0i8.i32(i8* %arraydecay, i8 -1, i32 -8, i32 1, i1 false) ; Negative 8!\r
+ ret i32 0\r
+}\r
+\r
+declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) nounwind\r