@@ -50,10 +50,13 @@ def wasm_memset_t : SDTypeProfile<0, 4,
50
50
def wasm_memset : SDNode<"WebAssemblyISD::MEMSET", wasm_memset_t,
51
51
[SDNPHasChain, SDNPMayStore]>;
52
52
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.
53
56
multiclass BulkMemoryOps<WebAssemblyRegClass rc, string B> {
54
57
55
58
let mayStore = 1, hasSideEffects = 1 in
56
- defm MEMORY_INIT_A #B :
59
+ defm INIT_A #B :
57
60
BULK_I<(outs),
58
61
(ins i32imm_op:$seg, i32imm_op:$idx, rc:$dest,
59
62
I32:$offset, I32:$size),
@@ -62,89 +65,59 @@ defm MEMORY_INIT_A#B :
62
65
"memory.init\t$seg, $idx, $dest, $offset, $size",
63
66
"memory.init\t$seg, $idx", 0x08>;
64
67
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
-
80
68
let mayLoad = 1, mayStore = 1 in
81
- defm MEMORY_COPY_A32 :
69
+ defm COPY_A#B :
82
70
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),
84
72
(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
87
75
)],
88
76
"memory.copy\t$src_idx, $dst_idx, $dst, $src, $len",
89
77
"memory.copy\t$src_idx, $dst_idx", 0x0a>;
90
78
91
79
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),
94
82
(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)],
96
84
"memory.fill\t$idx, $dst, $value, $size",
97
85
"memory.fill\t$idx", 0x0b>;
86
+ }
98
87
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">;
109
90
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> {
117
96
118
97
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),
121
100
(outs), (ins i32imm_op:$src_idx, i32imm_op:$dst_idx),
122
101
[(wasm_memcpy (i32 imm:$src_idx), (i32 imm:$dst_idx),
123
- I32 :$dst, I32 :$src, I32 :$len
102
+ rc :$dst, rc :$src, rc :$len
124
103
)],
125
104
"", "", 0>,
126
105
Requires<[HasBulkMemory]>;
127
106
128
107
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),
130
109
(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)],
132
111
"", "", 0>,
133
112
Requires<[HasBulkMemory]>;
134
113
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
+ }
144
115
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