262 lines · plain
1; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mcpu=mvp -mattr=+bulk-memory | FileCheck %s --check-prefixes CHECK,BULK-MEM2; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mcpu=mvp -mattr=-bulk-memory | FileCheck %s --check-prefixes CHECK,NO-BULK-MEM3 4; Test that basic bulk memory codegen works correctly5 6target triple = "wasm64-unknown-unknown"7 8declare void @llvm.memcpy.p0.p0.i8(ptr, ptr, i8, i1)9declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)10 11declare void @llvm.memmove.p0.p0.i8(ptr, ptr, i8, i1)12declare void @llvm.memmove.p0.p0.i64(ptr, ptr, i64, i1)13 14declare void @llvm.memset.p0.i8(ptr, i8, i8, i1)15declare void @llvm.memset.p0.i64(ptr, i8, i64, i1)16 17; CHECK-LABEL: memcpy_i8:18; NO-BULK-MEM-NOT: memory.copy19; BULK-MEM-NEXT: .functype memcpy_i8 (i64, i64, i32) -> ()20; BULK-MEM-NEXT: block21; BULK-MEM-NEXT: i64.extend_i32_u $push[[L0:[0-9]+]]=, $222; BULK-MEM-NEXT: local.tee $push[[L1:[0-9]+]]=, $3=, $pop[[L0]]23; BULK-MEM-NEXT: i64.eqz $push0=, $pop[[L1]]24; BULK-MEM-NEXT: br_if 0, $pop025; BULK-MEM-NEXT: memory.copy 0, 0, $0, $1, $326; BULK-MEM-NEXT: .LBB{{.*}}:27; BULK-MEM-NEXT: end_block28; BULK-MEM-NEXT: return29define void @memcpy_i8(ptr %dest, ptr %src, i8 zeroext %len) {30 call void @llvm.memcpy.p0.p0.i8(ptr %dest, ptr %src, i8 %len, i1 0)31 ret void32}33 34; CHECK-LABEL: memmove_i8:35; NO-BULK-MEM-NOT: memory.copy36; BULK-MEM-NEXT: .functype memmove_i8 (i64, i64, i32) -> ()37; BULK-MEM-NEXT: block38; BULK-MEM-NEXT: i64.extend_i32_u $push[[L0:[0-9]+]]=, $239; BULK-MEM-NEXT: local.tee $push[[L1:[0-9]+]]=, $3=, $pop[[L0]]40; BULK-MEM-NEXT: i64.eqz $push0=, $pop[[L1]]41; BULK-MEM-NEXT: br_if 0, $pop042; BULK-MEM-NEXT: memory.copy 0, 0, $0, $1, $343; BULK-MEM-NEXT: .LBB{{.*}}:44; BULK-MEM-NEXT: end_block45; BULK-MEM-NEXT: return46define void @memmove_i8(ptr %dest, ptr %src, i8 zeroext %len) {47 call void @llvm.memmove.p0.p0.i8(ptr %dest, ptr %src, i8 %len, i1 0)48 ret void49}50 51; CHECK-LABEL: memset_i8:52; NO-BULK-MEM-NOT: memory.fill53; BULK-MEM-NEXT: .functype memset_i8 (i64, i32, i32) -> ()54; BULK-MEM-NEXT: block55; BULK-MEM-NEXT: i64.extend_i32_u $push[[L0:[0-9]+]]=, $256; BULK-MEM-NEXT: local.tee $push[[L1:[0-9]+]]=, $3=, $pop[[L0]]57; BULK-MEM-NEXT: i64.eqz $push0=, $pop[[L1]]58; BULK-MEM-NEXT: br_if 0, $pop059; BULK-MEM-NEXT: memory.fill 0, $0, $1, $360; BULK-MEM-NEXT: .LBB{{.*}}:61; BULK-MEM-NEXT: end_block62; BULK-MEM-NEXT: return63define void @memset_i8(ptr %dest, i8 %val, i8 zeroext %len) {64 call void @llvm.memset.p0.i8(ptr %dest, i8 %val, i8 %len, i1 0)65 ret void66}67 68; CHECK-LABEL: memcpy_i32:69; NO-BULK-MEM-NOT: memory.copy70; BULK-MEM-NEXT: .functype memcpy_i32 (i64, i64, i64) -> ()71; BULK-MEM-NEXT: block72; BULK-MEM-NEXT: i64.eqz $push0=, $273; BULK-MEM-NEXT: br_if 0, $pop074; BULK-MEM-NEXT: memory.copy 0, 0, $0, $1, $275; BULK-MEM-NEXT: .LBB{{.*}}:76; BULK-MEM-NEXT: end_block77; BULK-MEM-NEXT: return78define void @memcpy_i32(ptr %dest, ptr %src, i64 %len) {79 call void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 %len, i1 0)80 ret void81}82 83; CHECK-LABEL: memmove_i32:84; NO-BULK-MEM-NOT: memory.copy85; BULK-MEM-NEXT: .functype memmove_i32 (i64, i64, i64) -> ()86; BULK-MEM-NEXT: block87; BULK-MEM-NEXT: i64.eqz $push0=, $288; BULK-MEM-NEXT: br_if 0, $pop089; BULK-MEM-NEXT: memory.copy 0, 0, $0, $1, $290; BULK-MEM-NEXT: .LBB{{.*}}:91; BULK-MEM-NEXT: end_block92; BULK-MEM-NEXT: return93define void @memmove_i32(ptr %dest, ptr %src, i64 %len) {94 call void @llvm.memmove.p0.p0.i64(ptr %dest, ptr %src, i64 %len, i1 0)95 ret void96}97 98; CHECK-LABEL: memset_i32:99; NO-BULK-MEM-NOT: memory.fill100; BULK-MEM-NEXT: .functype memset_i32 (i64, i32, i64) -> ()101; BULK-MEM-NEXT: block102; BULK-MEM-NEXT: i64.eqz $push0=, $2103; BULK-MEM-NEXT: br_if 0, $pop0104; BULK-MEM-NEXT: memory.fill 0, $0, $1, $2105; BULK-MEM-NEXT: .LBB{{.*}}:106; BULK-MEM-NEXT: end_block107; BULK-MEM-NEXT: return108define void @memset_i32(ptr %dest, i8 %val, i64 %len) {109 call void @llvm.memset.p0.i64(ptr %dest, i8 %val, i64 %len, i1 0)110 ret void111}112 113; CHECK-LABEL: memcpy_0:114; CHECK-NEXT: .functype memcpy_0 (i64, i64) -> ()115; CHECK-NEXT: return116define void @memcpy_0(ptr %dest, ptr %src) {117 call void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 0, i1 0)118 ret void119}120 121; CHECK-LABEL: memmove_0:122; CHECK-NEXT: .functype memmove_0 (i64, i64) -> ()123; CHECK-NEXT: return124define void @memmove_0(ptr %dest, ptr %src) {125 call void @llvm.memmove.p0.p0.i64(ptr %dest, ptr %src, i64 0, i1 0)126 ret void127}128 129; CHECK-LABEL: memset_0:130; NO-BULK-MEM-NOT: memory.fill131; BULK-MEM-NEXT: .functype memset_0 (i64, i32) -> ()132; BULK-MEM-NEXT: return133define void @memset_0(ptr %dest, i8 %val) {134 call void @llvm.memset.p0.i64(ptr %dest, i8 %val, i64 0, i1 0)135 ret void136}137 138; CHECK-LABEL: memcpy_1:139; CHECK-NEXT: .functype memcpy_1 (i64, i64) -> ()140; CHECK-NEXT: i32.load8_u $push[[L0:[0-9]+]]=, 0($1)141; CHECK-NEXT: i32.store8 0($0), $pop[[L0]]142; CHECK-NEXT: return143define void @memcpy_1(ptr %dest, ptr %src) {144 call void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 1, i1 0)145 ret void146}147 148; CHECK-LABEL: memmove_1:149; CHECK-NEXT: .functype memmove_1 (i64, i64) -> ()150; CHECK-NEXT: i32.load8_u $push[[L0:[0-9]+]]=, 0($1)151; CHECK-NEXT: i32.store8 0($0), $pop[[L0]]152; CHECK-NEXT: return153define void @memmove_1(ptr %dest, ptr %src) {154 call void @llvm.memmove.p0.p0.i64(ptr %dest, ptr %src, i64 1, i1 0)155 ret void156}157 158; CHECK-LABEL: memset_1:159; NO-BULK-MEM-NOT: memory.fill160; BULK-MEM-NEXT: .functype memset_1 (i64, i32) -> ()161; BULK-MEM-NEXT: i32.store8 0($0), $1162; BULK-MEM-NEXT: return163define void @memset_1(ptr %dest, i8 %val) {164 call void @llvm.memset.p0.i64(ptr %dest, i8 %val, i64 1, i1 0)165 ret void166}167 168; CHECK-LABEL: memcpy_1024:169; NO-BULK-MEM-NOT: memory.copy170; BULK-MEM-NEXT: .functype memcpy_1024 (i64, i64) -> ()171; BULK-MEM-NEXT: i64.const $push[[L0:[0-9]+]]=, 1024172; BULK-MEM-NEXT: memory.copy 0, 0, $0, $1, $pop[[L0]]173; BULK-MEM-NEXT: return174define void @memcpy_1024(ptr %dest, ptr %src) {175 call void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 1024, i1 0)176 ret void177}178 179; CHECK-LABEL: memmove_1024:180; NO-BULK-MEM-NOT: memory.copy181; BULK-MEM-NEXT: .functype memmove_1024 (i64, i64) -> ()182; BULK-MEM-NEXT: i64.const $push[[L0:[0-9]+]]=, 1024183; BULK-MEM-NEXT: memory.copy 0, 0, $0, $1, $pop[[L0]]184; BULK-MEM-NEXT: return185define void @memmove_1024(ptr %dest, ptr %src) {186 call void @llvm.memmove.p0.p0.i64(ptr %dest, ptr %src, i64 1024, i1 0)187 ret void188}189 190; CHECK-LABEL: memset_1024:191; NO-BULK-MEM-NOT: memory.fill192; BULK-MEM-NEXT: .functype memset_1024 (i64, i32) -> ()193; BULK-MEM-NEXT: i64.const $push[[L0:[0-9]+]]=, 1024194; BULK-MEM-NEXT: memory.fill 0, $0, $1, $pop[[L0]]195; BULK-MEM-NEXT: return196define void @memset_1024(ptr %dest, i8 %val) {197 call void @llvm.memset.p0.i64(ptr %dest, i8 %val, i64 1024, i1 0)198 ret void199}200 201; The following tests check that frame index elimination works for202; bulk memory instructions. The stack pointer is bumped by 112 instead203; of 100 because the stack pointer in WebAssembly is currently always204; 16-byte aligned, even in leaf functions, although it is not written205; back to the global in this case.206 207; TODO: Change TransientStackAlignment to 1 to avoid this extra208; arithmetic. This will require forcing the use of StackAlignment in209; PrologEpilogEmitter.cpp when210; WebAssemblyFrameLowering::needsSPWriteback would be true.211 212; CHECK-LABEL: memcpy_alloca_src:213; NO-BULK-MEM-NOT: memory.copy214; BULK-MEM-NEXT: .functype memcpy_alloca_src (i64) -> ()215; BULK-MEM-NEXT: global.get $push[[L1:[0-9]+]]=, __stack_pointer216; BULK-MEM-NEXT: i64.const $push[[L0:[0-9]+]]=, 112217; BULK-MEM-NEXT: i64.sub $push[[L2:[0-9]+]]=, $pop[[L1]], $pop[[L0]]218; BULK-MEM-NEXT: i64.const $push[[L3:[0-9]+]]=, 12219; BULK-MEM-NEXT: i64.add $push[[L4:[0-9]+]]=, $pop[[L2]], $pop[[L3]]220; BULK-MEM-NEXT: i64.const $push[[L5:[0-9]+]]=, 100221; BULK-MEM-NEXT: memory.copy 0, 0, $0, $pop[[L4]], $pop[[L5]]222; BULK-MEM-NEXT: return223define void @memcpy_alloca_src(ptr %dst) {224 %a = alloca [100 x i8]225 call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %a, i64 100, i1 false)226 ret void227}228 229; CHECK-LABEL: memcpy_alloca_dst:230; NO-BULK-MEM-NOT: memory.copy231; BULK-MEM-NEXT: .functype memcpy_alloca_dst (i64) -> ()232; BULK-MEM-NEXT: global.get $push[[L1:[0-9]+]]=, __stack_pointer233; BULK-MEM-NEXT: i64.const $push[[L0:[0-9]+]]=, 112234; BULK-MEM-NEXT: i64.sub $push[[L2:[0-9]+]]=, $pop[[L1]], $pop[[L0]]235; BULK-MEM-NEXT: i64.const $push[[L3:[0-9]+]]=, 12236; BULK-MEM-NEXT: i64.add $push[[L4:[0-9]+]]=, $pop[[L2]], $pop[[L3]]237; BULK-MEM-NEXT: i64.const $push[[L5:[0-9]+]]=, 100238; BULK-MEM-NEXT: memory.copy 0, 0, $pop[[L4]], $0, $pop[[L5]]239; BULK-MEM-NEXT: return240define void @memcpy_alloca_dst(ptr %src) {241 %a = alloca [100 x i8]242 call void @llvm.memcpy.p0.p0.i64(ptr %a, ptr %src, i64 100, i1 false)243 ret void244}245 246; CHECK-LABEL: memset_alloca:247; NO-BULK-MEM-NOT: memory.fill248; BULK-MEM-NEXT: .functype memset_alloca (i32) -> ()249; BULK-MEM-NEXT: global.get $push[[L1:[0-9]+]]=, __stack_pointer250; BULK-MEM-NEXT: i64.const $push[[L0:[0-9]+]]=, 112251; BULK-MEM-NEXT: i64.sub $push[[L2:[0-9]+]]=, $pop[[L1]], $pop[[L0]]252; BULK-MEM-NEXT: i64.const $push[[L3:[0-9]+]]=, 12253; BULK-MEM-NEXT: i64.add $push[[L4:[0-9]+]]=, $pop[[L2]], $pop[[L3]]254; BULK-MEM-NEXT: i64.const $push[[L5:[0-9]+]]=, 100255; BULK-MEM-NEXT: memory.fill 0, $pop[[L4]], $0, $pop[[L5]]256; BULK-MEM-NEXT: return257define void @memset_alloca(i8 %val) {258 %a = alloca [100 x i8]259 call void @llvm.memset.p0.i64(ptr %a, i8 %val, i64 100, i1 false)260 ret void261}262