@@ -21,16 +21,33 @@ multiclass BULK_I<dag oops_r, dag iops_r, dag oops_s, dag iops_s,
2121}
2222
2323// Bespoke types and nodes for bulk memory ops
24+
25+ // memory.copy (may trap on empty ranges)
26+ def wasm_memory_copy_t : SDTypeProfile<0, 5,
27+ [SDTCisInt<0>, SDTCisInt<1>, SDTCisPtrTy<2>, SDTCisPtrTy<3>, SDTCisInt<4>]
28+ >;
29+ def wasm_memory_copy : SDNode<"WebAssemblyISD::MEMORY_COPY", wasm_memory_copy_t,
30+ [SDNPHasChain, SDNPMayLoad, SDNPMayStore]>;
31+
32+ // memory.copy with a branch to avoid trapping
2433def wasm_memcpy_t : SDTypeProfile<0, 5,
2534 [SDTCisInt<0>, SDTCisInt<1>, SDTCisPtrTy<2>, SDTCisPtrTy<3>, SDTCisInt<4>]
2635>;
27- def wasm_memcpy : SDNode<"WebAssemblyISD::MEMORY_COPY ", wasm_memcpy_t,
36+ def wasm_memcpy : SDNode<"WebAssemblyISD::MEMCPY ", wasm_memcpy_t,
2837 [SDNPHasChain, SDNPMayLoad, SDNPMayStore]>;
2938
39+ // memory.fill (may trap on empty ranges)
40+ def wasm_memory_fill_t : SDTypeProfile<0, 4,
41+ [SDTCisInt<0>, SDTCisPtrTy<1>, SDTCisInt<2>, SDTCisInt<3>]
42+ >;
43+ def wasm_memory_fill : SDNode<"WebAssemblyISD::MEMORY_FILL", wasm_memory_fill_t,
44+ [SDNPHasChain, SDNPMayStore]>;
45+
46+ // memory.fill with a branch to avoid trapping
3047def wasm_memset_t : SDTypeProfile<0, 4,
3148 [SDTCisInt<0>, SDTCisPtrTy<1>, SDTCisInt<2>, SDTCisInt<3>]
3249>;
33- def wasm_memset : SDNode<"WebAssemblyISD::MEMORY_FILL ", wasm_memset_t,
50+ def wasm_memset : SDNode<"WebAssemblyISD::MEMSET ", wasm_memset_t,
3451 [SDNPHasChain, SDNPMayStore]>;
3552
3653multiclass BulkMemoryOps<WebAssemblyRegClass rc, string B> {
@@ -51,25 +68,83 @@ defm DATA_DROP :
5168 [],
5269 "data.drop\t$seg", "data.drop\t$seg", 0x09>;
5370
71+ }
72+
73+ defm : BulkMemoryOps<I32, "32">;
74+ defm : BulkMemoryOps<I64, "64">;
75+
76+ // Define copy/fill manually instead of using the `BulkMemoryOps` multiclass
77+ // because when a multiclass defines opcodes, it gives them anonymous names
78+ // and we need opcodes with names so that we can handle them with custom code.
79+
5480let mayLoad = 1, mayStore = 1 in
55- defm MEMORY_COPY_A#B :
81+ defm MEMORY_COPY_A32 :
5682 BULK_I<(outs), (ins i32imm_op:$src_idx, i32imm_op:$dst_idx,
57- rc :$dst, rc :$src, rc :$len),
83+ I32 :$dst, I32 :$src, I32 :$len),
5884 (outs), (ins i32imm_op:$src_idx, i32imm_op:$dst_idx),
59- [(wasm_memcpy (i32 imm:$src_idx), (i32 imm:$dst_idx),
60- rc :$dst, rc :$src, rc :$len
85+ [(wasm_memory_copy (i32 imm:$src_idx), (i32 imm:$dst_idx),
86+ I32 :$dst, I32 :$src, I32 :$len
6187 )],
6288 "memory.copy\t$src_idx, $dst_idx, $dst, $src, $len",
6389 "memory.copy\t$src_idx, $dst_idx", 0x0a>;
6490
6591let mayStore = 1 in
66- defm MEMORY_FILL_A#B :
67- BULK_I<(outs), (ins i32imm_op:$idx, rc :$dst, I32:$value, rc :$size),
92+ defm MEMORY_FILL_A32 :
93+ BULK_I<(outs), (ins i32imm_op:$idx, I32 :$dst, I32:$value, I32 :$size),
6894 (outs), (ins i32imm_op:$idx),
69- [(wasm_memset (i32 imm:$idx), rc :$dst, I32:$value, rc :$size)],
95+ [(wasm_memory_fill (i32 imm:$idx), I32 :$dst, I32:$value, I32 :$size)],
7096 "memory.fill\t$idx, $dst, $value, $size",
7197 "memory.fill\t$idx", 0x0b>;
72- }
7398
74- defm : BulkMemoryOps<I32, "32">;
75- defm : BulkMemoryOps<I64, "64">;
99+ let mayLoad = 1, mayStore = 1 in
100+ defm MEMORY_COPY_A64 :
101+ BULK_I<(outs), (ins i32imm_op:$src_idx, i32imm_op:$dst_idx,
102+ I64:$dst, I64:$src, I64:$len),
103+ (outs), (ins i32imm_op:$src_idx, i32imm_op:$dst_idx),
104+ [(wasm_memory_copy (i32 imm:$src_idx), (i32 imm:$dst_idx),
105+ I64:$dst, I64:$src, I64:$len
106+ )],
107+ "memory.copy\t$src_idx, $dst_idx, $dst, $src, $len",
108+ "memory.copy\t$src_idx, $dst_idx", 0x0a>;
109+
110+ let mayStore = 1 in
111+ defm MEMORY_FILL_A64 :
112+ BULK_I<(outs), (ins i32imm_op:$idx, I64:$dst, I32:$value, I64:$size),
113+ (outs), (ins i32imm_op:$idx),
114+ [(wasm_memory_fill (i32 imm:$idx), I64:$dst, I32:$value, I64:$size)],
115+ "memory.fill\t$idx, $dst, $value, $size",
116+ "memory.fill\t$idx", 0x0b>;
117+
118+ let usesCustomInserter = 1, isCodeGenOnly = 1, mayLoad = 1, mayStore = 1 in
119+ defm MEMCPY_A32 : I<(outs), (ins i32imm_op:$src_idx, i32imm_op:$dst_idx,
120+ I32:$dst, I32:$src, I32:$len),
121+ (outs), (ins i32imm_op:$src_idx, i32imm_op:$dst_idx),
122+ [(wasm_memcpy (i32 imm:$src_idx), (i32 imm:$dst_idx),
123+ I32:$dst, I32:$src, I32:$len
124+ )],
125+ "", "", 0>,
126+ Requires<[HasBulkMemory]>;
127+
128+ let usesCustomInserter = 1, isCodeGenOnly = 1, mayStore = 1 in
129+ defm MEMSET_A32 : I<(outs), (ins i32imm_op:$idx, I32:$dst, I32:$value, I32:$size),
130+ (outs), (ins i32imm_op:$idx),
131+ [(wasm_memset (i32 imm:$idx), I32:$dst, I32:$value, I32:$size)],
132+ "", "", 0>,
133+ Requires<[HasBulkMemory]>;
134+
135+ let usesCustomInserter = 1, isCodeGenOnly = 1, mayLoad = 1, mayStore = 1 in
136+ defm MEMCPY_A64 : I<(outs), (ins i32imm_op:$src_idx, i32imm_op:$dst_idx,
137+ I64:$dst, I64:$src, I64:$len),
138+ (outs), (ins i32imm_op:$src_idx, i32imm_op:$dst_idx),
139+ [(wasm_memcpy (i32 imm:$src_idx), (i32 imm:$dst_idx),
140+ I64:$dst, I64:$src, I64:$len
141+ )],
142+ "", "", 0>,
143+ Requires<[HasBulkMemory]>;
144+
145+ let usesCustomInserter = 1, isCodeGenOnly = 1, mayStore = 1 in
146+ defm MEMSET_A64 : I<(outs), (ins i32imm_op:$idx, I64:$dst, I32:$value, I64:$size),
147+ (outs), (ins i32imm_op:$idx),
148+ [(wasm_memset (i32 imm:$idx), I64:$dst, I32:$value, I64:$size)],
149+ "", "", 0>,
150+ Requires<[HasBulkMemory]>;
0 commit comments