1; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -tail-dup-placement=0 | FileCheck %s 2 3; Test memcpy, memmove, and memset intrinsics. 4 5target triple = "wasm32-unknown-unknown" 6 7declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1) 8declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1) 9declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i1) 10 11; Test that return values are optimized. 12 13; CHECK-LABEL: copy_yes: 14; CHECK: call $push0=, memcpy, $0, $1, $2{{$}} 15; CHECK-NEXT: return $pop0{{$}} 16define i8* @copy_yes(i8* %dst, i8* %src, i32 %len) { 17 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %len, i1 false) 18 ret i8* %dst 19} 20 21; CHECK-LABEL: copy_no: 22; CHECK: call $drop=, memcpy, $0, $1, $2{{$}} 23; CHECK-NEXT: return{{$}} 24define void @copy_no(i8* %dst, i8* %src, i32 %len) { 25 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %len, i1 false) 26 ret void 27} 28 29; CHECK-LABEL: move_yes: 30; CHECK: call $push0=, memmove, $0, $1, $2{{$}} 31; CHECK-NEXT: return $pop0{{$}} 32define i8* @move_yes(i8* %dst, i8* %src, i32 %len) { 33 call void @llvm.memmove.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %len, i1 false) 34 ret i8* %dst 35} 36 37; CHECK-LABEL: move_no: 38; CHECK: call $drop=, memmove, $0, $1, $2{{$}} 39; CHECK-NEXT: return{{$}} 40define void @move_no(i8* %dst, i8* %src, i32 %len) { 41 call void @llvm.memmove.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %len, i1 false) 42 ret void 43} 44 45; CHECK-LABEL: set_yes: 46; CHECK: call $push0=, memset, $0, $1, $2{{$}} 47; CHECK-NEXT: return $pop0{{$}} 48define i8* @set_yes(i8* %dst, i8 %src, i32 %len) { 49 call void @llvm.memset.p0i8.i32(i8* %dst, i8 %src, i32 %len, i1 false) 50 ret i8* %dst 51} 52 53; CHECK-LABEL: set_no: 54; CHECK: call $drop=, memset, $0, $1, $2{{$}} 55; CHECK-NEXT: return{{$}} 56define void @set_no(i8* %dst, i8 %src, i32 %len) { 57 call void @llvm.memset.p0i8.i32(i8* %dst, i8 %src, i32 %len, i1 false) 58 ret void 59} 60 61 62; CHECK-LABEL: frame_index: 63; CHECK: call $drop=, memset, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}} 64; CHECK: call $push{{[0-9]+}}=, memset, ${{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}} 65; CHECK: return{{$}} 66define void @frame_index() { 67entry: 68 %a = alloca [2048 x i8], align 16 69 %b = alloca [2048 x i8], align 16 70 %0 = getelementptr inbounds [2048 x i8], [2048 x i8]* %a, i32 0, i32 0 71 %1 = getelementptr inbounds [2048 x i8], [2048 x i8]* %b, i32 0, i32 0 72 call void @llvm.memset.p0i8.i32(i8* align 16 %0, i8 256, i32 1024, i1 false) 73 call void @llvm.memset.p0i8.i32(i8* align 16 %1, i8 256, i32 1024, i1 false) 74 ret void 75} 76 77; If the result value of memset doesn't get stackified, it should be marked 78; $drop. Note that we use a call to prevent tail dup so that we can test 79; this specific functionality. 80 81; CHECK-LABEL: drop_result: 82; CHECK: call $drop=, memset, $0, $1, $2 83declare i8* @def() 84declare void @block_tail_dup() 85define i8* @drop_result(i8* %arg, i8 %arg1, i32 %arg2, i32 %arg3, i32 %arg4) { 86bb: 87 %tmp = icmp eq i32 %arg3, 0 88 br i1 %tmp, label %bb5, label %bb9 89 90bb5: 91 %tmp6 = icmp eq i32 %arg4, 0 92 br i1 %tmp6, label %bb7, label %bb8 93 94bb7: 95 call void @llvm.memset.p0i8.i32(i8* %arg, i8 %arg1, i32 %arg2, i1 false) 96 br label %bb11 97 98bb8: 99 br label %bb11 100 101bb9: 102 %tmp10 = call i8* @def() 103 br label %bb11 104 105bb11: 106 %tmp12 = phi i8* [ %arg, %bb7 ], [ %arg, %bb8 ], [ %tmp10, %bb9 ] 107 call void @block_tail_dup() 108 ret i8* %tmp12 109} 110 111; This is the same as drop_result, except we let tail dup happen, so the 112; result of the memset *is* stackified. 113 114; CHECK-LABEL: tail_dup_to_reuse_result: 115; CHECK: call $push{{[0-9]+}}=, memset, $0, $1, $2 116define i8* @tail_dup_to_reuse_result(i8* %arg, i8 %arg1, i32 %arg2, i32 %arg3, i32 %arg4) { 117bb: 118 %tmp = icmp eq i32 %arg3, 0 119 br i1 %tmp, label %bb5, label %bb9 120 121bb5: 122 %tmp6 = icmp eq i32 %arg4, 0 123 br i1 %tmp6, label %bb7, label %bb8 124 125bb7: 126 call void @llvm.memset.p0i8.i32(i8* %arg, i8 %arg1, i32 %arg2, i1 false) 127 br label %bb11 128 129bb8: 130 br label %bb11 131 132bb9: 133 %tmp10 = call i8* @def() 134 br label %bb11 135 136bb11: 137 %tmp12 = phi i8* [ %arg, %bb7 ], [ %arg, %bb8 ], [ %tmp10, %bb9 ] 138 ret i8* %tmp12 139} 140