Skip to content

Commit 611acda

Browse files
committed
Simplify store operations
Automatically target for stores. LoadMemIdx int/float variants gets different code paths. Signed-off-by: Zoltan Herczeg [email protected]
1 parent 5fdeee6 commit 611acda

File tree

7 files changed

+189
-154
lines changed

7 files changed

+189
-154
lines changed

src/interpreter/ByteCode.h

Lines changed: 102 additions & 90 deletions
Large diffs are not rendered by default.

src/interpreter/Interpreter.cpp

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ ByteCodeStackOffset* Interpreter::interpret(ExecutionState& state,
673673
NEXT_INSTRUCTION(); \
674674
}
675675

676-
#define MEMORY_LOAD_MEMIDX_OPERATION(opcodeName, readType, writeType) \
676+
#define MEMORY_LOAD_INT_MEMIDX_OPERATION(opcodeName, readType, writeType) \
677677
DEFINE_OPCODE(opcodeName) \
678678
: \
679679
{ \
@@ -686,23 +686,24 @@ ByteCodeStackOffset* Interpreter::interpret(ExecutionState& state,
686686
NEXT_INSTRUCTION(); \
687687
}
688688

689-
#define MEMORY_STORE_INT_OPERATION(opcodeName, readType, writeType) \
690-
DEFINE_OPCODE(opcodeName) \
691-
: \
692-
{ \
693-
MemoryStore* code = (MemoryStore*)programCounter; \
694-
writeType value = readValue<readType>(bp, code->valueOffset()); \
695-
uint32_t offset = readValue<uint32_t>(bp, code->dstOffset()); \
696-
memories[0]->store(state, offset, code->offset(), value); \
697-
ADD_PROGRAM_COUNTER(MemoryStore); \
698-
NEXT_INSTRUCTION(); \
689+
#define MEMORY_LOAD_FLOAT_MEMIDX_OPERATION(opcodeName, readType, writeType) \
690+
DEFINE_OPCODE(opcodeName) \
691+
: \
692+
{ \
693+
MemoryLoadFloatMemIdx* code = (MemoryLoadFloatMemIdx*)programCounter; \
694+
uint32_t offset = readValue<uint32_t>(bp, code->srcOffset()); \
695+
readType value; \
696+
memories[code->memIndex()]->load(state, offset, code->offset(), &value); \
697+
writeValue<writeType>(bp, code->dstOffset(), value); \
698+
ADD_PROGRAM_COUNTER(MemoryLoadMemIdx); \
699+
NEXT_INSTRUCTION(); \
699700
}
700701

701-
#define MEMORY_STORE_FLOAT_OPERATION(opcodeName, readType, writeType) \
702+
#define MEMORY_STORE_OPERATION(opcodeName, readType, writeType) \
702703
DEFINE_OPCODE(opcodeName) \
703704
: \
704705
{ \
705-
MemoryStoreFloat* code = (MemoryStoreFloat*)programCounter; \
706+
MemoryStore* code = (MemoryStore*)programCounter; \
706707
writeType value = readValue<readType>(bp, code->valueOffset()); \
707708
uint32_t offset = readValue<uint32_t>(bp, code->dstOffset()); \
708709
memories[0]->store(state, offset, code->offset(), value); \
@@ -715,8 +716,8 @@ ByteCodeStackOffset* Interpreter::interpret(ExecutionState& state,
715716
: \
716717
{ \
717718
MemoryStoreMemIdx* code = (MemoryStoreMemIdx*)programCounter; \
718-
writeType value = readValue<readType>(bp, code->src1Offset()); \
719-
uint32_t offset = readValue<uint32_t>(bp, code->src0Offset()); \
719+
writeType value = readValue<readType>(bp, code->valueOffset()); \
720+
uint32_t offset = readValue<uint32_t>(bp, code->dstOffset()); \
720721
memories[code->memIndex()]->store(state, offset, code->offset(), value); \
721722
ADD_PROGRAM_COUNTER(MemoryStoreMemIdx); \
722723
NEXT_INSTRUCTION(); \
@@ -919,8 +920,8 @@ ByteCodeStackOffset* Interpreter::interpret(ExecutionState& state,
919920
: \
920921
{ \
921922
MemoryStoreMemIdx* code = (MemoryStoreMemIdx*)programCounter; \
922-
writeType value = readValue<readType>(bp, code->src1Offset()); \
923-
uint32_t offset = readValue<uint32_t>(bp, code->src0Offset()); \
923+
writeType value = readValue<readType>(bp, code->valueOffset()); \
924+
uint32_t offset = readValue<uint32_t>(bp, code->dstOffset()); \
924925
memories[code->memIndex()]->atomicStore(state, offset, code->offset(), value); \
925926
ADD_PROGRAM_COUNTER(MemoryStoreMemIdx); \
926927
NEXT_INSTRUCTION(); \
@@ -1346,9 +1347,9 @@ ByteCodeStackOffset* Interpreter::interpret(ExecutionState& state,
13461347

13471348
FOR_EACH_BYTECODE_LOAD_INT_OP(MEMORY_LOAD_INT_OPERATION)
13481349
FOR_EACH_BYTECODE_LOAD_FLOAT_OP(MEMORY_LOAD_FLOAT_OPERATION)
1349-
FOR_EACH_BYTECODE_LOAD_MEMIDX_OP(MEMORY_LOAD_MEMIDX_OPERATION)
1350-
FOR_EACH_BYTECODE_STORE_INT_OP(MEMORY_STORE_INT_OPERATION)
1351-
FOR_EACH_BYTECODE_STORE_FLOAT_OP(MEMORY_STORE_FLOAT_OPERATION)
1350+
FOR_EACH_BYTECODE_LOAD_INT_MEMIDX_OP(MEMORY_LOAD_INT_MEMIDX_OPERATION)
1351+
FOR_EACH_BYTECODE_LOAD_FLOAT_MEMIDX_OP(MEMORY_LOAD_FLOAT_MEMIDX_OPERATION)
1352+
FOR_EACH_BYTECODE_STORE_OP(MEMORY_STORE_OPERATION)
13521353
FOR_EACH_BYTECODE_STORE_MEMIDX_OP(MEMORY_STORE_MEMIDX_OPERATION)
13531354
FOR_EACH_BYTECODE_SIMD_LOAD_SPLAT_OP(SIMD_MEMORY_LOAD_SPLAT_OPERATION)
13541355
FOR_EACH_BYTECODE_SIMD_LOAD_SPLAT_MEMIDX_OP(SIMD_MEMORY_LOAD_SPLAT_MEMIDX_OPERATION)

src/jit/Analysis.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,14 @@ void JITCompiler::buildVariables(uint32_t requiredStackSize)
339339
dependencyCtx.currentOptions[i] = 0;
340340
}
341341

342+
const TypeVector::Types& paramTypeInfo = moduleFunction()->functionType()->param().types();
343+
size_t argc = paramTypeInfo.size();
344+
size_t offsetIndex = 0;
345+
for (size_t i = 0; i < argc; i++) {
346+
m_variableList->variables[offsetIndex].info |= Instruction::valueTypeToOperandType(paramTypeInfo[i]);
347+
offsetIndex += STACK_OFFSET(valueStackAllocatedSize(paramTypeInfo[i]));
348+
}
349+
342350
// Phase 1: the direct dependencies are computed for instructions
343351
// and labels (only labels can have multiple dependencies).
344352
for (InstructionListItem* item = m_first; item != nullptr; item = item->next()) {

src/jit/ByteCodeParser.cpp

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,8 +1234,6 @@ static void compileFunction(JITCompiler* compiler)
12341234
}
12351235
break;
12361236
}
1237-
case ByteCode::F32LoadMemIdxOpcode:
1238-
case ByteCode::F64LoadMemIdxOpcode:
12391237
case ByteCode::V128LoadMemIdxOpcode:
12401238
case ByteCode::V128Load8SplatMemIdxOpcode:
12411239
case ByteCode::V128Load16SplatMemIdxOpcode:
@@ -1267,13 +1265,7 @@ static void compileFunction(JITCompiler* compiler)
12671265
case ByteCode::V128Load64ZeroOpcode: {
12681266
group = Instruction::Load;
12691267
paramType = (info & Instruction::kMultiMemory ? ParamTypes::ParamSrcDstValueMemIdx : ParamTypes::ParamSrcDstValue);
1270-
1271-
if (opcode == ByteCode::F32LoadMemIdxOpcode)
1272-
requiredInit = OTLoadF32;
1273-
else if (opcode == ByteCode::F64LoadMemIdxOpcode)
1274-
requiredInit = OTLoadF64;
1275-
else
1276-
requiredInit = OTLoadV128;
1268+
requiredInit = OTLoadV128;
12771269
break;
12781270
}
12791271
case ByteCode::F32LoadOpcode:
@@ -1287,6 +1279,18 @@ static void compileFunction(JITCompiler* compiler)
12871279
operands[1] = STACK_OFFSET(loadFloatOperation->dstOffset());
12881280
break;
12891281
}
1282+
case ByteCode::F32LoadMemIdxOpcode:
1283+
case ByteCode::F64LoadMemIdxOpcode: {
1284+
Instruction* instr = compiler->append(byteCode, Instruction::Load, opcode, 1, 1);
1285+
instr->setRequiredRegsDescriptor(opcode == ByteCode::F32LoadMemIdxOpcode ? OTLoadF32 : OTLoadF64);
1286+
instr->addInfo(Instruction::kMultiMemory);
1287+
Operand* operands = instr->operands();
1288+
1289+
MemoryLoadFloatMemIdx* loadFloatMemIdxOperation = reinterpret_cast<MemoryLoadFloatMemIdx*>(byteCode);
1290+
operands[0] = STACK_OFFSET(loadFloatMemIdxOperation->srcOffset());
1291+
operands[1] = STACK_OFFSET(loadFloatMemIdxOperation->dstOffset());
1292+
break;
1293+
}
12901294
case ByteCode::V128Load8LaneMemIdxOpcode:
12911295
case ByteCode::V128Load16LaneMemIdxOpcode:
12921296
case ByteCode::V128Load32LaneMemIdxOpcode:
@@ -1364,33 +1368,14 @@ static void compileFunction(JITCompiler* compiler)
13641368
}
13651369
break;
13661370
}
1367-
case ByteCode::F32StoreMemIdxOpcode:
1368-
case ByteCode::F64StoreMemIdxOpcode:
13691371
case ByteCode::V128StoreMemIdxOpcode: {
13701372
info |= Instruction::kMultiMemory;
13711373
FALLTHROUGH;
13721374
}
13731375
case ByteCode::V128StoreOpcode: {
13741376
group = Instruction::Store;
13751377
paramType = (info & Instruction::kMultiMemory ? ParamTypes::ParamSrc2ValueMemIdx : ParamTypes::ParamSrc2Value);
1376-
1377-
if (opcode == ByteCode::F32StoreMemIdxOpcode)
1378-
requiredInit = OTStoreF32;
1379-
else if (opcode == ByteCode::F64StoreMemIdxOpcode)
1380-
requiredInit = OTStoreF64;
1381-
else
1382-
requiredInit = OTStoreV128;
1383-
break;
1384-
}
1385-
case ByteCode::F32StoreOpcode:
1386-
case ByteCode::F64StoreOpcode: {
1387-
Instruction* instr = compiler->append(byteCode, Instruction::Store, opcode, 2, 0);
1388-
instr->setRequiredRegsDescriptor(opcode == ByteCode::F32StoreOpcode ? OTStoreF32 : OTStoreF64);
1389-
Operand* operands = instr->operands();
1390-
1391-
MemoryStoreFloat* storeFloatOperation = reinterpret_cast<MemoryStoreFloat*>(byteCode);
1392-
operands[0] = STACK_OFFSET(storeFloatOperation->dstOffset());
1393-
operands[1] = STACK_OFFSET(storeFloatOperation->valueOffset());
1378+
requiredInit = OTStoreV128;
13941379
break;
13951380
}
13961381
case ByteCode::V128Store8LaneMemIdxOpcode:
@@ -2912,6 +2897,14 @@ const uint8_t* VariableList::getOperandDescriptor(Instruction* instr)
29122897
case ByteCode::Store64Opcode:
29132898
requiredInit = OTStoreF64;
29142899
break;
2900+
case ByteCode::I32StoreOpcode:
2901+
case ByteCode::I32StoreMemIdxOpcode:
2902+
requiredInit = OTStoreF32;
2903+
break;
2904+
case ByteCode::I64StoreOpcode:
2905+
case ByteCode::I64StoreMemIdxOpcode:
2906+
requiredInit = OTStoreF64;
2907+
break;
29152908
default:
29162909
return instr->getOperandDescriptor();
29172910
}

src/jit/MemoryInl.h

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -547,8 +547,8 @@ static void emitLoad(sljit_compiler* compiler, Instruction* instr)
547547

548548
if (instr->opcode() != ByteCode::Load32Opcode && instr->opcode() != ByteCode::Load64Opcode) {
549549
if (instr->info() & Instruction::kMultiMemory) {
550-
MemoryLoadMemIdx* loadMemIdxOperation = reinterpret_cast<MemoryLoadMemIdx*>(instr->byteCode());
551-
offset = loadMemIdxOperation->offset();
550+
ByteCodeOffset2ValueMemIdx* loadMemIdxOperation = reinterpret_cast<ByteCodeOffset2ValueMemIdx*>(instr->byteCode());
551+
offset = loadMemIdxOperation->uint32Value();
552552
memIndex = loadMemIdxOperation->memIndex();
553553
} else {
554554
ByteCodeOffset2Value* loadOperation = reinterpret_cast<ByteCodeOffset2Value*>(instr->byteCode());
@@ -773,7 +773,8 @@ static void emitStore(sljit_compiler* compiler, Instruction* instr)
773773
#endif /* HAS_SIMD */
774774

775775
switch (instr->opcode()) {
776-
case ByteCode::Store32Opcode:
776+
default:
777+
ASSERT(instr->opcode() == ByteCode::Store32Opcode);
777778
opcode = (instr->info() & Instruction::kHasFloatOperand) ? SLJIT_MOV_F32 : SLJIT_MOV32;
778779
size = 4;
779780
break;
@@ -787,7 +788,7 @@ static void emitStore(sljit_compiler* compiler, Instruction* instr)
787788
FALLTHROUGH;
788789
case ByteCode::I32StoreMemIdxOpcode:
789790
case ByteCode::I32StoreOpcode:
790-
opcode = SLJIT_MOV32;
791+
opcode = (instr->info() & Instruction::kHasFloatOperand) ? SLJIT_MOV_F32 : SLJIT_MOV32;
791792
size = 4;
792793
break;
793794
case ByteCode::I32AtomicStore8MemIdxOpcode:
@@ -817,7 +818,7 @@ static void emitStore(sljit_compiler* compiler, Instruction* instr)
817818
FALLTHROUGH;
818819
case ByteCode::I64StoreMemIdxOpcode:
819820
case ByteCode::I64StoreOpcode:
820-
opcode = SLJIT_MOV;
821+
opcode = (instr->info() & Instruction::kHasFloatOperand) ? SLJIT_MOV_F64 : SLJIT_MOV;
821822
size = 8;
822823
break;
823824
case ByteCode::I64AtomicStore8MemIdxOpcode:
@@ -846,11 +847,6 @@ static void emitStore(sljit_compiler* compiler, Instruction* instr)
846847
opcode = SLJIT_MOV_U32;
847848
size = 4;
848849
break;
849-
case ByteCode::F32StoreMemIdxOpcode:
850-
case ByteCode::F32StoreOpcode:
851-
opcode = SLJIT_MOV_F32;
852-
size = 4;
853-
break;
854850
#ifdef HAS_SIMD
855851
case ByteCode::V128StoreMemIdxOpcode:
856852
case ByteCode::V128StoreOpcode:
@@ -886,11 +882,6 @@ static void emitStore(sljit_compiler* compiler, Instruction* instr)
886882
size = 8;
887883
break;
888884
#endif /* HAS_SIMD */
889-
default:
890-
ASSERT(instr->opcode() == ByteCode::F64StoreOpcode || instr->opcode() == ByteCode::F64StoreMemIdxOpcode);
891-
opcode = SLJIT_MOV_F64;
892-
size = 8;
893-
break;
894885
}
895886

896887
if (instr->opcode() != ByteCode::Store32Opcode && instr->opcode() != ByteCode::Store64Opcode) {

src/parser/WASMParser.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3441,6 +3441,20 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate {
34413441
}
34423442
FOR_EACH_BYTECODE_STORE_OP(GENERATE_STORE_CODE_CASE)
34433443
#undef GENERATE_STORE_CODE_CASE
3444+
case WASMOpcode::F32StoreOpcode:
3445+
if (memidx == 0) {
3446+
pushByteCode(Walrus::I32Store(offset, src0, src1), code);
3447+
} else {
3448+
pushByteCode(Walrus::I32StoreMemIdx(memidx, alignmentLog2, offset, src0, src1));
3449+
}
3450+
break;
3451+
case WASMOpcode::F64StoreOpcode:
3452+
if (memidx == 0) {
3453+
pushByteCode(Walrus::I64Store(offset, src0, src1), code);
3454+
} else {
3455+
pushByteCode(Walrus::I64StoreMemIdx(memidx, alignmentLog2, offset, src0, src1));
3456+
}
3457+
break;
34443458
default:
34453459
ASSERT_NOT_REACHED();
34463460
break;

test/web-assembly3/jit/memory.wast

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
(module
2+
(memory $mem0 1)
3+
(memory $mem1 1)
4+
5+
(func (export "storeload_f32") (param i32) (param f32) (result f32)
6+
(f32.store $mem0 offset=1 (i32.const 3) (local.get 1))
7+
(f32.load $mem0 offset=1 (i32.const 3))
8+
)
9+
(func (export "storeload_align_f32") (param i32) (param f32) (result f32)
10+
(f32.store $mem1 offset=1 (i32.const 0) (local.get 1))
11+
(f32.load $mem1 offset=1 (i32.const 0))
12+
)
13+
)
14+
15+
(assert_return (invoke "storeload_f32" (i32.const 0) (f32.const 1234)) (f32.const 1234))
16+
(assert_return (invoke "storeload_align_f32" (i32.const 0) (f32.const 1234)) (f32.const 1234))

0 commit comments

Comments
 (0)