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