The following program crashes when built with clang-cl: (If the #if 1 is changed to #if 0, it doesn't crash. For some reason that causes us not to expand the memcpy.) struct Ptr { ~Ptr() {} int *ptr; }; #if 1 struct Arr { struct { struct { char name[54]; } mailbox; int texture_target; int sync_point; } mailbox_holder; void *shared_memory; struct shared_memory_size { int width; int height; } memory_size; }; #else struct Arr { char x[76]; }; #endif void f(Ptr) {} void g(Arr *a, Arr *b, Ptr *p) { *a = *b; // memcpy, possibly expanded to rep movs, clobbering esi f(*p); // inalloca call, causing chkstk, not expecting clobbered esi }; int main() { Ptr p = {}; Arr a = {}, b = {}; g(&a, &b, &p); return 0; } (Reduced from Chromium's cc::CopyOutputResult::TakeTexture.)
Slightly reduced: $ llc -mcpu=pentium4 a.ll -o - a.ll: target datalayout = "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32" target triple = "i686-pc-win32" %struct.Ptr = type { i32* } %struct.Arr = type { %struct.anon, i8*, %"struct.Arr::shared_memory_size" } %struct.anon = type { %struct.anon.0, i32, i32 } %struct.anon.0 = type { [54 x i8] } %"struct.Arr::shared_memory_size" = type { i32, i32 } declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) declare i8* @llvm.stacksave() declare void @llvm.stackrestore(i8*) declare void @f(<{ %struct.Ptr }>* inalloca) #0 define void @g(%struct.Arr* %a, %struct.Arr* %b, %struct.Ptr* %p) #0 { entry: %inalloca.spmem = alloca i8* %aptr = bitcast %struct.Arr* %a to i8* %bptr = bitcast %struct.Arr* %b to i8* %pptr = bitcast %struct.Ptr* %p to i8* call void @llvm.memcpy.p0i8.p0i8.i32(i8* %aptr, i8* %bptr, i32 76, i32 4, i1 false) %inalloca.save = call i8* @llvm.stacksave() %argmem = alloca <{ %struct.Ptr }>, inalloca store i8* %inalloca.save, i8** %inalloca.spmem %gep = getelementptr inbounds <{ %struct.Ptr }>* %argmem, i32 0, i32 0 %gepptr = bitcast %struct.Ptr* %gep to i8* call void @llvm.memcpy.p0i8.p0i8.i32(i8* %gepptr, i8* %pptr, i32 4, i32 4, i1 false) call void @f(<{ %struct.Ptr }>* inalloca %argmem) call void @llvm.stackrestore(i8* %inalloca.save) ret void }
Should be fixed with r202930.
Hopefully fixed harder in r216775.