Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[simd] Implement store lane #1647

Merged
merged 1 commit into from
Mar 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/binary-reader-ir.cc
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ class BinaryReaderIR : public BinaryReaderNop {
Address alignment_log2,
Address offset,
uint64_t value) override;
Result OnSimdStoreLaneExpr(Opcode opcode,
Address alignment_log2,
Address offset,
uint64_t value) override;
Result OnSimdShuffleOpExpr(Opcode opcode, v128 value) override;
Result OnLoadSplatExpr(Opcode opcode,
Address alignment_log2,
Expand Down Expand Up @@ -1093,6 +1097,14 @@ Result BinaryReaderIR::OnSimdLoadLaneExpr(Opcode opcode,
MakeUnique<SimdLoadLaneExpr>(opcode, alignment_log2, offset, value));
}

Result BinaryReaderIR::OnSimdStoreLaneExpr(Opcode opcode,
Address alignment_log2,
Address offset,
uint64_t value) {
return AppendExpr(
MakeUnique<SimdStoreLaneExpr>(opcode, alignment_log2, offset, value));
}

Result BinaryReaderIR::OnSimdShuffleOpExpr(Opcode opcode, v128 value) {
return AppendExpr(MakeUnique<SimdShuffleOpExpr>(opcode, value));
}
Expand Down
21 changes: 11 additions & 10 deletions src/binary-reader-logging.cc
Original file line number Diff line number Diff line change
Expand Up @@ -395,16 +395,6 @@ Result BinaryReaderLogging::OnSimdLaneOpExpr(Opcode opcode, uint64_t value) {
return reader_->OnSimdLaneOpExpr(opcode, value);
}

Result BinaryReaderLogging::OnSimdLoadLaneExpr(Opcode opcode,
Address alignment_log2,
Address offset,
uint64_t value) {
LOGF("OnSimdLoadLaneExpr (align log2: %" PRIaddress ", offset: %" PRIaddress
", lane: %" PRIu64 ")\n",
alignment_log2, offset, value);
return reader_->OnSimdLoadLaneExpr(opcode, alignment_log2, offset, value);
}

Result BinaryReaderLogging::OnSimdShuffleOpExpr(Opcode opcode, v128 value) {
LOGF("OnSimdShuffleOpExpr (lane: 0x%08x %08x %08x %08x)\n", value.u32(0),
value.u32(1), value.u32(2), value.u32(3));
Expand Down Expand Up @@ -743,6 +733,15 @@ Result BinaryReaderLogging::OnComdatEntry(ComdatType kind, Index index) {
return reader_->name(opcode, alignment_log2, offset); \
}

#define DEFINE_SIMD_LOAD_STORE_LANE_OPCODE(name) \
Result BinaryReaderLogging::name(Opcode opcode, Address alignment_log2, \
Address offset, uint64_t value) { \
LOGF(#name "(opcode: \"%s\" (%u), align log2: %" PRIaddress \
", offset: %" PRIaddress ", lane: %" PRIu64 ")\n", \
opcode.GetName(), opcode.GetCode(), alignment_log2, offset, value); \
return reader_->name(opcode, alignment_log2, offset, value); \
}

#define DEFINE0(name) \
Result BinaryReaderLogging::name() { \
LOGF(#name "\n"); \
Expand Down Expand Up @@ -848,6 +847,8 @@ DEFINE0(OnUnreachableExpr)
DEFINE0(OnUnwindExpr)
DEFINE_OPCODE(OnUnaryExpr)
DEFINE_OPCODE(OnTernaryExpr)
DEFINE_SIMD_LOAD_STORE_LANE_OPCODE(OnSimdLoadLaneExpr);
DEFINE_SIMD_LOAD_STORE_LANE_OPCODE(OnSimdStoreLaneExpr);
DEFINE_END(EndCodeSection)

DEFINE_BEGIN(BeginElemSection)
Expand Down
4 changes: 4 additions & 0 deletions src/binary-reader-logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,10 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
Address alignment_log2,
Address offset,
uint64_t value) override;
Result OnSimdStoreLaneExpr(Opcode opcode,
Address alignment_log2,
Address offset,
uint64_t value) override;
Result OnSimdShuffleOpExpr(Opcode opcode, v128 value) override;
Result OnLoadSplatExpr(Opcode opcode,
Address alignment_log2,
Expand Down
6 changes: 6 additions & 0 deletions src/binary-reader-nop.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,12 @@ class BinaryReaderNop : public BinaryReaderDelegate {
uint64_t value) override {
return Result::Ok;
}
Result OnSimdStoreLaneExpr(Opcode opcode,
Address alignment_log2,
Address offset,
uint64_t value) override {
return Result::Ok;
}
Result OnSimdShuffleOpExpr(Opcode opcode, v128 value) override {
return Result::Ok;
}
Expand Down
15 changes: 15 additions & 0 deletions src/binary-reader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1333,6 +1333,21 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) {
CALLBACK(OnOpcodeUint32Uint32Uint32, alignment_log2, offset, lane_val);
break;
}
case Opcode::V128Store8Lane:
case Opcode::V128Store16Lane:
case Opcode::V128Store32Lane:
case Opcode::V128Store64Lane: {
Address alignment_log2;
CHECK_RESULT(ReadAlignment(&alignment_log2, "load alignment"));
Address offset;
CHECK_RESULT(ReadAddress(&offset, 0, "load offset"));
uint8_t lane_val;
CHECK_RESULT(ReadU8(&lane_val, "Lane idx"));

CALLBACK(OnSimdStoreLaneExpr, opcode, alignment_log2, offset, lane_val);
CALLBACK(OnOpcodeUint32Uint32Uint32, alignment_log2, offset, lane_val);
break;
}
case Opcode::V128Load32Zero:
case Opcode::V128Load64Zero: {
Address alignment_log2;
Expand Down
4 changes: 4 additions & 0 deletions src/binary-reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,10 @@ class BinaryReaderDelegate {
Address alignment_log2,
Address offset,
uint64_t value) = 0;
virtual Result OnSimdStoreLaneExpr(Opcode opcode,
Address alignment_log2,
Address offset,
uint64_t value) = 0;

virtual Result OnLoadSplatExpr(Opcode opcode,
Address alignment_log2,
Expand Down
27 changes: 19 additions & 8 deletions src/binary-writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,8 @@ class BinaryWriter {
void WriteTableNumberWithReloc(Index table_number, const char* desc);
template <typename T>
void WriteLoadStoreExpr(const Func* func, const Expr* expr, const char* desc);
template <typename T>
void WriteSimdLoadStoreLaneExpr(const Func* func, const Expr* expr, const char* desc);
void WriteExpr(const Func* func, const Expr* expr);
void WriteExprList(const Func* func, const ExprList& exprs);
void WriteInitExpr(const ExprList& expr);
Expand Down Expand Up @@ -645,6 +647,18 @@ void BinaryWriter::WriteLoadStoreExpr(const Func* func,
WriteU32Leb128(stream_, typed_expr->offset, desc);
}

template <typename T>
void BinaryWriter::WriteSimdLoadStoreLaneExpr(const Func* func,
const Expr* expr,
const char* desc) {
auto* typed_expr = cast<T>(expr);
WriteOpcode(stream_, typed_expr->opcode);
Address align = typed_expr->opcode.GetAlignment(typed_expr->align);
stream_->WriteU8(log2_u32(align), "alignment");
WriteU32Leb128(stream_, typed_expr->offset, desc);
stream_->WriteU8(static_cast<uint8_t>(typed_expr->val), "Simd Lane literal");
}

void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
switch (expr->type()) {
case ExprType::AtomicLoad:
Expand Down Expand Up @@ -1017,14 +1031,11 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
break;
}
case ExprType::SimdLoadLane: {
const Opcode opcode = cast<SimdLoadLaneExpr>(expr)->opcode;
auto* load_lane_expr = cast<SimdLoadLaneExpr>(expr);
WriteOpcode(stream_, opcode);
Address align = load_lane_expr->opcode.GetAlignment(load_lane_expr->align);
stream_->WriteU8(log2_u32(align), "alignment");
WriteU32Leb128(stream_, load_lane_expr->offset, "load offset");
stream_->WriteU8(static_cast<uint8_t>(cast<SimdLoadLaneExpr>(expr)->val),
"Simd Lane literal");
WriteSimdLoadStoreLaneExpr<SimdLoadLaneExpr>(func, expr, "load offset");
break;
}
case ExprType::SimdStoreLane: {
WriteSimdLoadStoreLaneExpr<SimdStoreLaneExpr>(func, expr, "store offset");
break;
}
case ExprType::SimdShuffleOp: {
Expand Down
6 changes: 6 additions & 0 deletions src/expr-visitor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,12 @@ Result ExprVisitor::HandleDefaultState(Expr* expr) {
break;
}

case ExprType::SimdStoreLane: {
CHECK_RESULT(
delegate_->OnSimdStoreLaneExpr(cast<SimdStoreLaneExpr>(expr)));
break;
}

case ExprType::SimdShuffleOp: {
CHECK_RESULT(
delegate_->OnSimdShuffleOpExpr(cast<SimdShuffleOpExpr>(expr)));
Expand Down
2 changes: 2 additions & 0 deletions src/expr-visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ class ExprVisitor::Delegate {
virtual Result OnTernaryExpr(TernaryExpr*) = 0;
virtual Result OnSimdLaneOpExpr(SimdLaneOpExpr*) = 0;
virtual Result OnSimdLoadLaneExpr(SimdLoadLaneExpr*) = 0;
virtual Result OnSimdStoreLaneExpr(SimdStoreLaneExpr*) = 0;
virtual Result OnSimdShuffleOpExpr(SimdShuffleOpExpr*) = 0;
virtual Result OnLoadSplatExpr(LoadSplatExpr*) = 0;
virtual Result OnLoadZeroExpr(LoadZeroExpr*) = 0;
Expand Down Expand Up @@ -209,6 +210,7 @@ class ExprVisitor::DelegateNop : public ExprVisitor::Delegate {
Result OnTernaryExpr(TernaryExpr*) override { return Result::Ok; }
Result OnSimdLaneOpExpr(SimdLaneOpExpr*) override { return Result::Ok; }
Result OnSimdLoadLaneExpr(SimdLoadLaneExpr*) override { return Result::Ok; }
Result OnSimdStoreLaneExpr(SimdStoreLaneExpr*) override { return Result::Ok; }
Result OnSimdShuffleOpExpr(SimdShuffleOpExpr*) override { return Result::Ok; }
Result OnLoadSplatExpr(LoadSplatExpr*) override { return Result::Ok; }
Result OnLoadZeroExpr(LoadZeroExpr*) override { return Result::Ok; }
Expand Down
14 changes: 14 additions & 0 deletions src/interp/binary-reader-interp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,10 @@ class BinaryReaderInterp : public BinaryReaderNop {
Address alignment_log2,
Address offset,
uint64_t value) override;
Result OnSimdStoreLaneExpr(Opcode opcode,
Address alignment_log2,
Address offset,
uint64_t value) override;
Result OnSimdShuffleOpExpr(Opcode opcode, v128 value) override;
Result OnLoadSplatExpr(Opcode opcode,
Address alignment_log2,
Expand Down Expand Up @@ -908,6 +912,16 @@ Result BinaryReaderInterp::OnSimdLoadLaneExpr(Opcode opcode,
return Result::Ok;
}

Result BinaryReaderInterp::OnSimdStoreLaneExpr(Opcode opcode,
Address alignment_log2,
Address offset,
uint64_t value) {
CHECK_RESULT(validator_.OnSimdStoreLane(loc, opcode,
GetAlignment(alignment_log2), value));
istream_.Emit(opcode, kMemoryIndex0, offset, static_cast<u8>(value));
return Result::Ok;
}

Result BinaryReaderInterp::OnSimdShuffleOpExpr(Opcode opcode, v128 value) {
CHECK_RESULT(validator_.OnSimdShuffleOp(loc, opcode, value));
istream_.Emit(opcode, value);
Expand Down
36 changes: 28 additions & 8 deletions src/interp/interp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1636,10 +1636,15 @@ RunResult Thread::StepInternal(Trap::Ptr* out_trap) {
case O::V128Load32Splat: return DoSimdLoadSplat<u32x4, u32>(instr, out_trap);
case O::V128Load64Splat: return DoSimdLoadSplat<u64x2, u64>(instr, out_trap);

case O::V128Load8Lane: return DoSimdLoadLane<u8x16, u8>(instr, out_trap);
case O::V128Load16Lane: return DoSimdLoadLane<u16x8, u16>(instr, out_trap);
case O::V128Load32Lane: return DoSimdLoadLane<u32x4, u32>(instr, out_trap);
case O::V128Load64Lane: return DoSimdLoadLane<u64x2, u64>(instr, out_trap);
case O::V128Load8Lane: return DoSimdLoadLane<u8x16>(instr, out_trap);
case O::V128Load16Lane: return DoSimdLoadLane<u16x8>(instr, out_trap);
case O::V128Load32Lane: return DoSimdLoadLane<u32x4>(instr, out_trap);
case O::V128Load64Lane: return DoSimdLoadLane<u64x2>(instr, out_trap);

case O::V128Store8Lane: return DoSimdStoreLane<u8x16>(instr, out_trap);
case O::V128Store16Lane: return DoSimdStoreLane<u16x8>(instr, out_trap);
case O::V128Store32Lane: return DoSimdStoreLane<u32x4>(instr, out_trap);
case O::V128Store64Lane: return DoSimdStoreLane<u64x2>(instr, out_trap);

case O::V128Load32Zero: return DoSimdLoadZero<u32x4, u32>(instr, out_trap);
case O::V128Load64Zero: return DoSimdLoadZero<u64x2, u64>(instr, out_trap);
Expand Down Expand Up @@ -2170,19 +2175,34 @@ RunResult Thread::DoSimdLoadSplat(Instr instr, Trap::Ptr* out_trap) {
return RunResult::Ok;
}

template <typename S, typename T>
template <typename S>
RunResult Thread::DoSimdLoadLane(Instr instr, Trap::Ptr* out_trap) {
using L = typename S::LaneType;
using T = typename S::LaneType;
auto result = Pop<S>();
L val;
if (Load<L>(instr, &val, out_trap) != RunResult::Ok) {
T val;
if (Load<T>(instr, &val, out_trap) != RunResult::Ok) {
return RunResult::Trap;
}
result.v[instr.imm_u32x2_u8.idx] = val;
Push(result);
return RunResult::Ok;
}

template <typename S>
RunResult Thread::DoSimdStoreLane(Instr instr, Trap::Ptr* out_trap) {
using T = typename S::LaneType;
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32x2_u8.fst]};
auto result = Pop<S>();
T val = result.v[instr.imm_u32x2_u8.idx];
u64 offset = PopPtr(memory);
TRAP_IF(Failed(memory->Store(offset, instr.imm_u32x2_u8.snd, val)),
StringPrintf("out of bounds memory access: access at %" PRIu64
"+%" PRIzd " >= max value %" PRIu64,
offset + instr.imm_u32x2_u8.snd, sizeof(T),
memory->ByteSize()));
return RunResult::Ok;
}

template <typename S, typename T>
RunResult Thread::DoSimdLoadZero(Instr instr, Trap::Ptr* out_trap) {
using L = typename S::LaneType;
Expand Down
4 changes: 3 additions & 1 deletion src/interp/interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1152,8 +1152,10 @@ class Thread : public Object {
RunResult DoSimdShift(BinopFunc<R, T>);
template <typename S, typename T>
RunResult DoSimdLoadSplat(Instr, Trap::Ptr* out_trap);
template <typename S, typename T>
template <typename S>
RunResult DoSimdLoadLane(Instr, Trap::Ptr* out_trap);
template <typename S>
RunResult DoSimdStoreLane(Instr, Trap::Ptr* out_trap);
template <typename S, typename T>
RunResult DoSimdLoadZero(Instr, Trap::Ptr* out_trap);
RunResult DoSimdSwizzle();
Expand Down
4 changes: 4 additions & 0 deletions src/interp/istream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,10 @@ Instr Istream::Read(Offset* offset) const {
case Opcode::V128Load16Lane:
case Opcode::V128Load32Lane:
case Opcode::V128Load64Lane:
case Opcode::V128Store8Lane:
case Opcode::V128Store16Lane:
case Opcode::V128Store32Lane:
case Opcode::V128Store64Lane:
// Index, memory offset, lane index immediates, 2 operands.
instr.kind = InstrKind::Imm_Index_Offset_Lane_Op_2;
instr.imm_u32x2_u8.fst = ReadAt<u32>(offset);
Expand Down
3 changes: 2 additions & 1 deletion src/ir-util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,8 @@ ModuleContext::Arities ModuleContext::GetExprArity(const Expr& expr) const {
}
}

case ExprType::SimdLoadLane: {
case ExprType::SimdLoadLane:
case ExprType::SimdStoreLane: {
return { 2, 1 };
}

Expand Down
1 change: 1 addition & 0 deletions src/ir.cc
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ const char* ExprTypeName[] = {
"Select",
"SimdLaneOp",
"SimdLoadLane",
"SimdStoreLane",
"SimdShuffleOp",
"LoadSplat",
"LoadZero",
Expand Down
24 changes: 20 additions & 4 deletions src/ir.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ enum class ExprType {
Select,
SimdLaneOp,
SimdLoadLane,
SimdStoreLane,
SimdShuffleOp,
LoadSplat,
LoadZero,
Expand Down Expand Up @@ -455,20 +456,35 @@ class SimdLaneOpExpr : public ExprMixin<ExprType::SimdLaneOp> {
uint64_t val;
};

class SimdLoadLaneExpr : public ExprMixin<ExprType::SimdLoadLane> {
class SimdLoadLaneExpr : public OpcodeExpr<ExprType::SimdLoadLane> {
public:
SimdLoadLaneExpr(Opcode opcode,
Address align,
Address offset,
uint64_t val,
const Location& loc = Location())
: ExprMixin<ExprType::SimdLoadLane>(loc),
opcode(opcode),
: OpcodeExpr<ExprType::SimdLoadLane>(opcode, loc),
align(align),
offset(offset),
val(val) {}

Address align;
Address offset;
uint64_t val;
};

class SimdStoreLaneExpr : public OpcodeExpr<ExprType::SimdStoreLane> {
public:
SimdStoreLaneExpr(Opcode opcode,
Address align,
Address offset,
uint64_t val,
const Location& loc = Location())
: OpcodeExpr<ExprType::SimdStoreLane>(opcode, loc),
align(align),
offset(offset),
val(val) {}

Opcode opcode;
Address align;
Address offset;
uint64_t val;
Expand Down
4 changes: 4 additions & 0 deletions src/lexer-keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,10 @@ v128.load8_lane, TokenType::SimdLoadLane, Opcode::V128Load8Lane
v128.load16_lane, TokenType::SimdLoadLane, Opcode::V128Load16Lane
v128.load32_lane, TokenType::SimdLoadLane, Opcode::V128Load32Lane
v128.load64_lane, TokenType::SimdLoadLane, Opcode::V128Load64Lane
v128.store8_lane, TokenType::SimdStoreLane, Opcode::V128Store8Lane
v128.store16_lane, TokenType::SimdStoreLane, Opcode::V128Store16Lane
v128.store32_lane, TokenType::SimdStoreLane, Opcode::V128Store32Lane
v128.store64_lane, TokenType::SimdStoreLane, Opcode::V128Store64Lane
i8x16.shuffle, TokenType::SimdShuffleOp, Opcode::I8X16Shuffle
i8x16.swizzle, TokenType::Binary, Opcode::I8X16Swizzle
# Deprecated names.
Expand Down
Loading