1; RUN: opt -S -memcpyopt < %s | FileCheck %s 2 3; PR40118: BasicAA didn't realize that stackrestore ends the lifetime of 4; unescaped dynamic allocas, such as those that might come from inalloca. 5 6source_filename = "t.cpp" 7target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" 8target triple = "i686-unknown-windows-msvc19.14.26433" 9 10@str = internal constant [9 x i8] c"abcdxxxxx" 11 12 13; Test that we can propagate memcpy through an unescaped dynamic alloca across 14; a call to @external. 15 16define i32 @test_norestore(i32 %n) { 17 %tmpmem = alloca [10 x i8], align 4 18 %tmp = getelementptr inbounds [10 x i8], [10 x i8]* %tmpmem, i32 0, i32 0 19 20 ; Make a dynamic alloca, initialize it. 21 %p = alloca i8, i32 %n, align 4 22 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* align 1 getelementptr inbounds ([9 x i8], [9 x i8]* @str, i32 0, i32 0), i32 9, i1 false) 23 24 ; This extra byte exists to prevent memcpyopt from propagating @str. 25 %p10 = getelementptr inbounds i8, i8* %p, i32 9 26 store i8 0, i8* %p10 27 28 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %tmp, i8* %p, i32 10, i1 false) 29 call void @external() 30 %heap = call i8* @malloc(i32 9) 31 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %heap, i8* %tmp, i32 9, i1 false) 32 call void @useit(i8* %heap) 33 ret i32 0 34} 35 36; CHECK-LABEL: define i32 @test_norestore(i32 %n) 37; CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* align 1 getelementptr inbounds ([9 x i8], [9 x i8]* @str, i32 0, i32 0), i32 9, i1 false) 38; CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %tmp, i8* %p, i32 10, i1 false) 39; CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %heap, i8* %p, i32 9, i1 false) 40 41 42; Do not propagate memcpy from %p across the stackrestore. 43 44define i32 @test_stackrestore() { 45 %tmpmem = alloca [10 x i8], align 4 46 %tmp = getelementptr inbounds [10 x i8], [10 x i8]* %tmpmem, i32 0, i32 0 47 %inalloca.save = tail call i8* @llvm.stacksave() 48 %argmem = alloca inalloca [10 x i8], align 4 49 %p = getelementptr inbounds [10 x i8], [10 x i8]* %argmem, i32 0, i32 0 50 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* align 1 getelementptr inbounds ([9 x i8], [9 x i8]* @str, i32 0, i32 0), i32 9, i1 false) 51 52 ; This extra byte exists to prevent memcpyopt from propagating @str. 53 %p10 = getelementptr inbounds [10 x i8], [10 x i8]* %argmem, i32 0, i32 9 54 store i8 0, i8* %p10 55 56 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %tmp, i8* %p, i32 10, i1 false) 57 call void @llvm.stackrestore(i8* %inalloca.save) 58 %heap = call i8* @malloc(i32 9) 59 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %heap, i8* %tmp, i32 9, i1 false) 60 call void @useit(i8* %heap) 61 ret i32 0 62} 63 64; CHECK-LABEL: define i32 @test_stackrestore() 65; CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* align 1 getelementptr inbounds ([9 x i8], [9 x i8]* @str, i32 0, i32 0), i32 9, i1 false) 66; CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %tmp, i8* %p, i32 10, i1 false) 67; CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %heap, i8* %tmp, i32 9, i1 false) 68 69declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture writeonly, i8* nocapture readonly, i32, i1) 70declare i8* @llvm.stacksave() 71declare void @llvm.stackrestore(i8*) 72declare i8* @malloc(i32) 73declare void @useit(i8*) 74declare void @external() 75