Skip to content

Commit 2486b3b

Browse files
committed
[WebAssembly] Align bulk-memory thresholds
Use the same thresholds for memcpy/move/set when optimizing for size or otherwise. The high-level nature of the memory instructions can allow runtimes to optimize them more readily.
1 parent 8a53cc8 commit 2486b3b

File tree

3 files changed

+247
-0
lines changed

3 files changed

+247
-0
lines changed

llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,17 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
394394
// is equivalent to a simple branch. This reduces code size for wasm, and we
395395
// defer possible jump table optimizations to the VM.
396396
setMinimumJumpTableEntries(2);
397+
398+
// Align bulk memory usage when optimizing for size or otherwise. As well as
399+
// reducing code size, prefering high-level primitives can make it easier for
400+
// runtimes to make optimisations, especially when explicit bounds checking is
401+
// employed.
402+
if (Subtarget->hasBulkMemory()) {
403+
MaxStoresPerMemset = MaxStoresPerMemsetOptSize;
404+
MaxStoresPerMemcpy = MaxStoresPerMemcpyOptSize;
405+
MaxStoresPerMemmove = MaxStoresPerMemmoveOptSize;
406+
MaxLoadsPerMemcmp = MaxLoadsPerMemcmpOptSize;
407+
}
397408
}
398409

399410
MVT WebAssemblyTargetLowering::getPointerTy(const DataLayout &DL,

llvm/test/CodeGen/WebAssembly/bulk-memory.ll

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,27 @@ define void @memcpy_i8(ptr %dest, ptr %src, i8 zeroext %len) {
2929
ret void
3030
}
3131

32+
; CHECK-LABEL: memcpy_i8_fixed_32
33+
; CHECK: i64.load
34+
; CHECK: i64.store
35+
; CHECK: i64.load
36+
; CHECK: i64.store
37+
; CHECK: i64.load
38+
; CHECK: i64.store
39+
; CHECK: i64.load
40+
; CHECK: i64.store
41+
define void @memcpy_i8_fixed_32(ptr %dest, ptr %src) {
42+
call void @llvm.memcpy.p0.p0.i8(ptr %dest, ptr %src, i8 32, i1 0)
43+
ret void
44+
}
45+
46+
; CHECK-LABEL: memcpy_i8_fixed_36
47+
; BULK-MEM: memory.copy
48+
define void @memcpy_i8_fixed_36(ptr %dest, ptr %src) {
49+
call void @llvm.memcpy.p0.p0.i8(ptr %dest, ptr %src, i8 36, i1 0)
50+
ret void
51+
}
52+
3253
; CHECK-LABEL: memmove_i8:
3354
; NO-BULK-MEM-NOT: memory.copy
3455
; BULK-MEM-NEXT: .functype memmove_i8 (i32, i32, i32) -> ()
@@ -44,6 +65,27 @@ define void @memmove_i8(ptr %dest, ptr %src, i8 zeroext %len) {
4465
ret void
4566
}
4667

68+
; CHECK-LABEL: memmove_i8_fixed_32
69+
; CHECK: i64.load
70+
; CHECK: i64.load
71+
; CHECK: i64.load
72+
; CHECK: i64.load
73+
; CHECK: i64.store
74+
; CHECK: i64.store
75+
; CHECK: i64.store
76+
; CHECK: i64.store
77+
define void @memmove_i8_fixed_32(ptr %dest, ptr %src) {
78+
call void @llvm.memmove.p0.p0.i8(ptr %dest, ptr %src, i8 32, i1 0)
79+
ret void
80+
}
81+
82+
; CHECK-LABEL: memmove_i8_fixed_36
83+
; BULK-MEM: memory.copy
84+
define void @memmove_i8_fixed_36(ptr %dest, ptr %src) {
85+
call void @llvm.memmove.p0.p0.i8(ptr %dest, ptr %src, i8 36, i1 0)
86+
ret void
87+
}
88+
4789
; CHECK-LABEL: memset_i8:
4890
; NO-BULK-MEM-NOT: memory.fill
4991
; BULK-MEM-NEXT: .functype memset_i8 (i32, i32, i32) -> ()
@@ -59,6 +101,23 @@ define void @memset_i8(ptr %dest, i8 %val, i8 zeroext %len) {
59101
ret void
60102
}
61103

104+
; CHECK-LABEL: memset_i8_fixed_32
105+
; CHECK: i64.store
106+
; CHECK: i64.store
107+
; CHECK: i64.store
108+
; CHECK: i64.store
109+
define void @memset_i8_fixed_32(ptr %dest, i8 %val) {
110+
call void @llvm.memset.p0.i8(ptr %dest, i8 %val, i8 32, i1 0)
111+
ret void
112+
}
113+
114+
; CHECK-LABEL: memset_i8_fixed_36
115+
; BULK-MEM: memory.fill
116+
define void @memset_i8_fixed_36(ptr %dest, i8 %val) {
117+
call void @llvm.memset.p0.i8(ptr %dest, i8 %val, i8 36, i1 0)
118+
ret void
119+
}
120+
62121
; CHECK-LABEL: memcpy_i32:
63122
; NO-BULK-MEM-NOT: memory.copy
64123
; BULK-MEM-NEXT: .functype memcpy_i32 (i32, i32, i32) -> ()
@@ -74,6 +133,27 @@ define void @memcpy_i32(ptr %dest, ptr %src, i32 %len) {
74133
ret void
75134
}
76135

136+
; CHECK-LABEL: memcpy_i32_fixed_32
137+
; CHECK: i64.load
138+
; CHECK: i64.store
139+
; CHECK: i64.load
140+
; CHECK: i64.store
141+
; CHECK: i64.load
142+
; CHECK: i64.store
143+
; CHECK: i64.load
144+
; CHECK: i64.store
145+
define void @memcpy_i32_fixed_32(ptr %dest, ptr %src) {
146+
call void @llvm.memcpy.p0.p0.i32(ptr %dest, ptr %src, i32 32, i1 0)
147+
ret void
148+
}
149+
150+
; CHECK-LABEL: memcpy_i32_fixed_36
151+
; BULK-MEM: memory.copy
152+
define void @memcpy_i32_fixed_36(ptr %dest, ptr %src) {
153+
call void @llvm.memcpy.p0.p0.i32(ptr %dest, ptr %src, i32 36, i1 0)
154+
ret void
155+
}
156+
77157
; CHECK-LABEL: memmove_i32:
78158
; NO-BULK-MEM-NOT: memory.copy
79159
; BULK-MEM-NEXT: .functype memmove_i32 (i32, i32, i32) -> ()
@@ -89,6 +169,27 @@ define void @memmove_i32(ptr %dest, ptr %src, i32 %len) {
89169
ret void
90170
}
91171

172+
; CHECK-LABEL: memmove_i32_fixed_32
173+
; CHECK: i64.load
174+
; CHECK: i64.load
175+
; CHECK: i64.load
176+
; CHECK: i64.load
177+
; CHECK: i64.store
178+
; CHECK: i64.store
179+
; CHECK: i64.store
180+
; CHECK: i64.store
181+
define void @memmove_i32_fixed_32(ptr %dest, ptr %src) {
182+
call void @llvm.memmove.p0.p0.i32(ptr %dest, ptr %src, i32 32, i1 0)
183+
ret void
184+
}
185+
186+
; CHECK-LABEL: memmove_i32_fixed_36
187+
; BULK-MEM: memory.copy
188+
define void @memmove_i32_fixed_36(ptr %dest, ptr %src) {
189+
call void @llvm.memmove.p0.p0.i32(ptr %dest, ptr %src, i32 36, i1 0)
190+
ret void
191+
}
192+
92193
; CHECK-LABEL: memset_i32:
93194
; NO-BULK-MEM-NOT: memory.fill
94195
; BULK-MEM-NEXT: .functype memset_i32 (i32, i32, i32) -> ()
@@ -104,6 +205,23 @@ define void @memset_i32(ptr %dest, i8 %val, i32 %len) {
104205
ret void
105206
}
106207

208+
; CHECK-LABEL: memset_i32_fixed_32
209+
; CHECK: i64.store
210+
; CHECK: i64.store
211+
; CHECK: i64.store
212+
; CHECK: i64.store
213+
define void @memset_i32_fixed_32(ptr %dest, i8 %val) {
214+
call void @llvm.memset.p0.i32(ptr %dest, i8 %val, i32 32, i1 0)
215+
ret void
216+
}
217+
218+
; CHECK-LABEL: memset_i32_fixed_36
219+
; BULK-MEM: memory.fill
220+
define void @memset_i32_fixed_36(ptr %dest, i8 %val) {
221+
call void @llvm.memset.p0.i32(ptr %dest, i8 %val, i32 36, i1 0)
222+
ret void
223+
}
224+
107225
; CHECK-LABEL: memcpy_1:
108226
; CHECK-NEXT: .functype memcpy_1 (i32, i32) -> ()
109227
; CHECK-NEXT: i32.load8_u $push[[L0:[0-9]+]]=, 0($1)

llvm/test/CodeGen/WebAssembly/bulk-memory64.ll

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,27 @@ define void @memcpy_i8(ptr %dest, ptr %src, i8 zeroext %len) {
3131
ret void
3232
}
3333

34+
; CHECK-LABEL: memcpy_i8_fixed_32
35+
; CHECK: i64.load
36+
; CHECK: i64.store
37+
; CHECK: i64.load
38+
; CHECK: i64.store
39+
; CHECK: i64.load
40+
; CHECK: i64.store
41+
; CHECK: i64.load
42+
; CHECK: i64.store
43+
define void @memcpy_i8_fixed_32(ptr %dest, ptr %src) {
44+
call void @llvm.memcpy.p0.p0.i8(ptr %dest, ptr %src, i8 32, i1 0)
45+
ret void
46+
}
47+
48+
; CHECK-LABEL: memcpy_i8_fixed_36
49+
; BULK-MEM: memory.copy
50+
define void @memcpy_i8_fixed_36(ptr %dest, ptr %src) {
51+
call void @llvm.memcpy.p0.p0.i8(ptr %dest, ptr %src, i8 36, i1 0)
52+
ret void
53+
}
54+
3455
; CHECK-LABEL: memmove_i8:
3556
; NO-BULK-MEM-NOT: memory.copy
3657
; BULK-MEM-NEXT: .functype memmove_i8 (i64, i64, i32) -> ()
@@ -48,6 +69,27 @@ define void @memmove_i8(ptr %dest, ptr %src, i8 zeroext %len) {
4869
ret void
4970
}
5071

72+
; CHECK-LABEL: memmove_i8_fixed_32
73+
; CHECK: i64.load
74+
; CHECK: i64.load
75+
; CHECK: i64.load
76+
; CHECK: i64.load
77+
; CHECK: i64.store
78+
; CHECK: i64.store
79+
; CHECK: i64.store
80+
; CHECK: i64.store
81+
define void @memmove_i8_fixed_32(ptr %dest, ptr %src) {
82+
call void @llvm.memmove.p0.p0.i8(ptr %dest, ptr %src, i8 32, i1 0)
83+
ret void
84+
}
85+
86+
; CHECK-LABEL: memmove_i8_fixed_36
87+
; BULK-MEM: memory.copy
88+
define void @memmove_i8_fixed_36(ptr %dest, ptr %src) {
89+
call void @llvm.memmove.p0.p0.i8(ptr %dest, ptr %src, i8 36, i1 0)
90+
ret void
91+
}
92+
5193
; CHECK-LABEL: memset_i8:
5294
; NO-BULK-MEM-NOT: memory.fill
5395
; BULK-MEM-NEXT: .functype memset_i8 (i64, i32, i32) -> ()
@@ -65,6 +107,23 @@ define void @memset_i8(ptr %dest, i8 %val, i8 zeroext %len) {
65107
ret void
66108
}
67109

110+
; CHECK-LABEL: memset_i8_fixed_32
111+
; CHECK: i64.store
112+
; CHECK: i64.store
113+
; CHECK: i64.store
114+
; CHECK: i64.store
115+
define void @memset_i8_fixed_32(ptr %dest, i8 %val) {
116+
call void @llvm.memset.p0.i8(ptr %dest, i8 %val, i8 32, i1 0)
117+
ret void
118+
}
119+
120+
; CHECK-LABEL: memset_i8_fixed_36
121+
; BULK-MEM: memory.fill
122+
define void @memset_i8_fixed_36(ptr %dest, i8 %val) {
123+
call void @llvm.memset.p0.i8(ptr %dest, i8 %val, i8 36, i1 0)
124+
ret void
125+
}
126+
68127
; CHECK-LABEL: memcpy_i32:
69128
; NO-BULK-MEM-NOT: memory.copy
70129
; BULK-MEM-NEXT: .functype memcpy_i32 (i64, i64, i64) -> ()
@@ -80,6 +139,27 @@ define void @memcpy_i32(ptr %dest, ptr %src, i64 %len) {
80139
ret void
81140
}
82141

142+
; CHECK-LABEL: memcpy_i32_fixed_32
143+
; CHECK: i64.load
144+
; CHECK: i64.store
145+
; CHECK: i64.load
146+
; CHECK: i64.store
147+
; CHECK: i64.load
148+
; CHECK: i64.store
149+
; CHECK: i64.load
150+
; CHECK: i64.store
151+
define void @memcpy_i32_fixed_32(ptr %dest, ptr %src) {
152+
call void @llvm.memcpy.p0.p0.i32(ptr %dest, ptr %src, i32 32, i1 0)
153+
ret void
154+
}
155+
156+
; CHECK-LABEL: memcpy_i32_fixed_36
157+
; BULK-MEM: memory.copy
158+
define void @memcpy_i32_fixed_36(ptr %dest, ptr %src) {
159+
call void @llvm.memcpy.p0.p0.i32(ptr %dest, ptr %src, i32 36, i1 0)
160+
ret void
161+
}
162+
83163
; CHECK-LABEL: memmove_i32:
84164
; NO-BULK-MEM-NOT: memory.copy
85165
; BULK-MEM-NEXT: .functype memmove_i32 (i64, i64, i64) -> ()
@@ -95,6 +175,27 @@ define void @memmove_i32(ptr %dest, ptr %src, i64 %len) {
95175
ret void
96176
}
97177

178+
; CHECK-LABEL: memmove_i32_fixed_32
179+
; CHECK: i64.load
180+
; CHECK: i64.load
181+
; CHECK: i64.load
182+
; CHECK: i64.load
183+
; CHECK: i64.store
184+
; CHECK: i64.store
185+
; CHECK: i64.store
186+
; CHECK: i64.store
187+
define void @memmove_i32_fixed_32(ptr %dest, ptr %src) {
188+
call void @llvm.memmove.p0.p0.i32(ptr %dest, ptr %src, i32 32, i1 0)
189+
ret void
190+
}
191+
192+
; CHECK-LABEL: memmove_i32_fixed_36
193+
; BULK-MEM: memory.copy
194+
define void @memmove_i32_fixed_36(ptr %dest, ptr %src) {
195+
call void @llvm.memmove.p0.p0.i32(ptr %dest, ptr %src, i32 36, i1 0)
196+
ret void
197+
}
198+
98199
; CHECK-LABEL: memset_i32:
99200
; NO-BULK-MEM-NOT: memory.fill
100201
; BULK-MEM-NEXT: .functype memset_i32 (i64, i32, i64) -> ()
@@ -110,6 +211,23 @@ define void @memset_i32(ptr %dest, i8 %val, i64 %len) {
110211
ret void
111212
}
112213

214+
; CHECK-LABEL: memset_i32_fixed_32
215+
; CHECK: i64.store
216+
; CHECK: i64.store
217+
; CHECK: i64.store
218+
; CHECK: i64.store
219+
define void @memset_i32_fixed_32(ptr %dest, i8 %val) {
220+
call void @llvm.memset.p0.i32(ptr %dest, i8 %val, i32 32, i1 0)
221+
ret void
222+
}
223+
224+
; CHECK-LABEL: memset_i32_fixed_36
225+
; BULK-MEM: memory.fill
226+
define void @memset_i32_fixed_36(ptr %dest, i8 %val) {
227+
call void @llvm.memset.p0.i32(ptr %dest, i8 %val, i32 36, i1 0)
228+
ret void
229+
}
230+
113231
; CHECK-LABEL: memcpy_1:
114232
; CHECK-NEXT: .functype memcpy_1 (i64, i64) -> ()
115233
; CHECK-NEXT: i32.load8_u $push[[L0:[0-9]+]]=, 0($1)

0 commit comments

Comments
 (0)