1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s 2 3 ; Test memcpy, memmove, and memset intrinsics. 4 5 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" 6 target triple = "wasm32-unknown-unknown" 7 8 declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) 9 declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) 10 declare 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{{$}} 17 define 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{{$}} 25 define 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{{$}} 33 define 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{{$}} 41 define 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{{$}} 49 define 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{{$}} 57 define 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{{$}} 67 define void @frame_index() { 68 entry: 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 84 declare i8* @def() 85 declare void @block_tail_dup() 86 define i8* @drop_result(i8* %arg, i8 %arg1, i32 %arg2, i32 %arg3, i32 %arg4) { 87 bb: 88 %tmp = icmp eq i32 %arg3, 0 89 br i1 %tmp, label %bb5, label %bb9 90 91 bb5: 92 %tmp6 = icmp eq i32 %arg4, 0 93 br i1 %tmp6, label %bb7, label %bb8 94 95 bb7: 96 call void @llvm.memset.p0i8.i32(i8* %arg, i8 %arg1, i32 %arg2, i32 1, i1 false) 97 br label %bb11 98 99 bb8: 100 br label %bb11 101 102 bb9: 103 %tmp10 = call i8* @def() 104 br label %bb11 105 106 bb11: 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 117 define i8* @tail_dup_to_reuse_result(i8* %arg, i8 %arg1, i32 %arg2, i32 %arg3, i32 %arg4) { 118 bb: 119 %tmp = icmp eq i32 %arg3, 0 120 br i1 %tmp, label %bb5, label %bb9 121 122 bb5: 123 %tmp6 = icmp eq i32 %arg4, 0 124 br i1 %tmp6, label %bb7, label %bb8 125 126 bb7: 127 call void @llvm.memset.p0i8.i32(i8* %arg, i8 %arg1, i32 %arg2, i32 1, i1 false) 128 br label %bb11 129 130 bb8: 131 br label %bb11 132 133 bb9: 134 %tmp10 = call i8* @def() 135 br label %bb11 136 137 bb11: 138 %tmp12 = phi i8* [ %arg, %bb7 ], [ %arg, %bb8 ], [ %tmp10, %bb9 ] 139 ret i8* %tmp12 140 } 141