Skip to content

Commit 8d77589

Browse files
committed
Define the bulk-memory instructions using a multiclass.
1 parent 1d9594c commit 8d77589

File tree

1 file changed

+33
-60
lines changed

1 file changed

+33
-60
lines changed

llvm/lib/Target/WebAssembly/WebAssemblyInstrBulkMemory.td

Lines changed: 33 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,13 @@ def wasm_memset_t : SDTypeProfile<0, 4,
5050
def wasm_memset : SDNode<"WebAssemblyISD::MEMSET", wasm_memset_t,
5151
[SDNPHasChain, SDNPMayStore]>;
5252

53+
// A multiclass for defining Wasm's raw bulk-memory `memory.*` instructions.
54+
// `memory.copy` and `memory.fill` have Wasm's behavior rather than
55+
// `memcpy`/`memset` behavior.
5356
multiclass BulkMemoryOps<WebAssemblyRegClass rc, string B> {
5457

5558
let mayStore = 1, hasSideEffects = 1 in
56-
defm MEMORY_INIT_A#B :
59+
defm INIT_A#B :
5760
BULK_I<(outs),
5861
(ins i32imm_op:$seg, i32imm_op:$idx, rc:$dest,
5962
I32:$offset, I32:$size),
@@ -62,89 +65,59 @@ defm MEMORY_INIT_A#B :
6265
"memory.init\t$seg, $idx, $dest, $offset, $size",
6366
"memory.init\t$seg, $idx", 0x08>;
6467

65-
let hasSideEffects = 1 in
66-
defm DATA_DROP :
67-
BULK_I<(outs), (ins i32imm_op:$seg), (outs), (ins i32imm_op:$seg),
68-
[],
69-
"data.drop\t$seg", "data.drop\t$seg", 0x09>;
70-
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-
8068
let mayLoad = 1, mayStore = 1 in
81-
defm MEMORY_COPY_A32 :
69+
defm COPY_A#B :
8270
BULK_I<(outs), (ins i32imm_op:$src_idx, i32imm_op:$dst_idx,
83-
I32:$dst, I32:$src, I32:$len),
71+
rc:$dst, rc:$src, rc:$len),
8472
(outs), (ins i32imm_op:$src_idx, i32imm_op:$dst_idx),
85-
[(wasm_memory_copy (i32 imm:$src_idx), (i32 imm:$dst_idx),
86-
I32:$dst, I32:$src, I32:$len
73+
[(wasm_memcpy (i32 imm:$src_idx), (i32 imm:$dst_idx),
74+
rc:$dst, rc:$src, rc:$len
8775
)],
8876
"memory.copy\t$src_idx, $dst_idx, $dst, $src, $len",
8977
"memory.copy\t$src_idx, $dst_idx", 0x0a>;
9078

9179
let mayStore = 1 in
92-
defm MEMORY_FILL_A32 :
93-
BULK_I<(outs), (ins i32imm_op:$idx, I32:$dst, I32:$value, I32:$size),
80+
defm FILL_A#B :
81+
BULK_I<(outs), (ins i32imm_op:$idx, rc:$dst, I32:$value, rc:$size),
9482
(outs), (ins i32imm_op:$idx),
95-
[(wasm_memory_fill (i32 imm:$idx), I32:$dst, I32:$value, I32:$size)],
83+
[(wasm_memset (i32 imm:$idx), rc:$dst, I32:$value, rc:$size)],
9684
"memory.fill\t$idx, $dst, $value, $size",
9785
"memory.fill\t$idx", 0x0b>;
86+
}
9887

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>;
88+
defm MEMORY_ : BulkMemoryOps<I32, "32">;
89+
defm MEMORY_ : BulkMemoryOps<I64, "64">;
10990

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>;
91+
// A multiclass for defining `memcpy`/`memset` pseudo instructions. These have
92+
// the behavior the rest of LLVM CodeGen expects, and we lower them into code
93+
// sequences that include the Wasm `memory.fill` and `memory.copy` instructions
94+
// using custom inserters, because they introduce new control flow.
95+
multiclass BulkMemOps<WebAssemblyRegClass rc, string B> {
11796

11897
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),
98+
defm CPY_A#B : I<(outs), (ins i32imm_op:$src_idx, i32imm_op:$dst_idx,
99+
rc:$dst, rc:$src, rc:$len),
121100
(outs), (ins i32imm_op:$src_idx, i32imm_op:$dst_idx),
122101
[(wasm_memcpy (i32 imm:$src_idx), (i32 imm:$dst_idx),
123-
I32:$dst, I32:$src, I32:$len
102+
rc:$dst, rc:$src, rc:$len
124103
)],
125104
"", "", 0>,
126105
Requires<[HasBulkMemory]>;
127106

128107
let usesCustomInserter = 1, isCodeGenOnly = 1, mayStore = 1 in
129-
defm MEMSET_A32 : I<(outs), (ins i32imm_op:$idx, I32:$dst, I32:$value, I32:$size),
108+
defm SET_A#B : I<(outs), (ins i32imm_op:$idx, rc:$dst, I32:$value, rc:$size),
130109
(outs), (ins i32imm_op:$idx),
131-
[(wasm_memset (i32 imm:$idx), I32:$dst, I32:$value, I32:$size)],
110+
[(wasm_memset (i32 imm:$idx), rc:$dst, I32:$value, rc:$size)],
132111
"", "", 0>,
133112
Requires<[HasBulkMemory]>;
134113

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]>;
114+
}
144115

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]>;
116+
defm MEM : BulkMemOps<I32, "32">;
117+
defm MEM : BulkMemOps<I64, "64">;
118+
119+
let hasSideEffects = 1 in
120+
defm DATA_DROP :
121+
BULK_I<(outs), (ins i32imm_op:$seg), (outs), (ins i32imm_op:$seg),
122+
[],
123+
"data.drop\t$seg", "data.drop\t$seg", 0x09>;

0 commit comments

Comments
 (0)