Skip to content

Prototype prefetch instructions #3467

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

Merged
merged 2 commits into from
Jan 6, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 3 additions & 0 deletions scripts/gen-s-parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,9 @@
("i16x8.extadd_pairwise_i8x16_u", "makeUnary(s, UnaryOp::ExtAddPairwiseUVecI8x16ToI16x8)"),
("i32x4.extadd_pairwise_i16x8_s", "makeUnary(s, UnaryOp::ExtAddPairwiseSVecI16x8ToI32x4)"),
("i32x4.extadd_pairwise_i16x8_u", "makeUnary(s, UnaryOp::ExtAddPairwiseUVecI16x8ToI32x4)"),
# prefetch instructions
("prefetch.t", "makePrefetch(s, PrefetchOp::PrefetchTemporal)"),
("prefetch.nt", "makePrefetch(s, PrefetchOp::PrefetchNontemporal)"),
# reference types instructions
# TODO Add table instructions
("ref.null", "makeRefNull(s)"),
Expand Down
22 changes: 19 additions & 3 deletions src/gen-s-parser.inc
Original file line number Diff line number Diff line change
Expand Up @@ -2759,9 +2759,25 @@ switch (op[0]) {
case 'n':
if (strcmp(op, "nop") == 0) { return makeNop(); }
goto parse_error;
case 'p':
if (strcmp(op, "pop") == 0) { return makePop(s); }
goto parse_error;
case 'p': {
switch (op[1]) {
case 'o':
if (strcmp(op, "pop") == 0) { return makePop(s); }
goto parse_error;
case 'r': {
switch (op[9]) {
case 'n':
if (strcmp(op, "prefetch.nt") == 0) { return makePrefetch(s, PrefetchOp::PrefetchNontemporal); }
goto parse_error;
case 't':
if (strcmp(op, "prefetch.t") == 0) { return makePrefetch(s, PrefetchOp::PrefetchTemporal); }
goto parse_error;
default: goto parse_error;
}
}
default: goto parse_error;
}
}
case 'r': {
switch (op[1]) {
case 'e': {
Expand Down
1 change: 1 addition & 0 deletions src/ir/ReFinalize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ void ReFinalize::visitSIMDLoad(SIMDLoad* curr) { curr->finalize(); }
void ReFinalize::visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
curr->finalize();
}
void ReFinalize::visitPrefetch(Prefetch* curr) { curr->finalize(); }
void ReFinalize::visitMemoryInit(MemoryInit* curr) { curr->finalize(); }
void ReFinalize::visitDataDrop(DataDrop* curr) { curr->finalize(); }
void ReFinalize::visitMemoryCopy(MemoryCopy* curr) { curr->finalize(); }
Expand Down
1 change: 1 addition & 0 deletions src/ir/cost.h
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,7 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, Index> {
Index visitSIMDShuffle(SIMDShuffle* curr) {
return 1 + visit(curr->left) + visit(curr->right);
}
Index visitPrefetch(Prefetch* curr) { return 1 + visit(curr->ptr); }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I doubt it matters, but maybe this could be 0 instead of 1, as it is meant to speed up later things?

Index visitRefNull(RefNull* curr) { return 1; }
Index visitRefIsNull(RefIsNull* curr) { return 1 + visit(curr->value); }
Index visitRefFunc(RefFunc* curr) { return 1; }
Expand Down
5 changes: 5 additions & 0 deletions src/ir/effects.h
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,11 @@ class EffectAnalyzer {
}
parent.implicitTrap = true;
}
void visitPrefetch(Prefetch* curr) {
// Do not reorder with respect to other memory ops
parent.writesMemory = true;
parent.readsMemory = true;
}
void visitMemoryInit(MemoryInit* curr) {
parent.writesMemory = true;
parent.implicitTrap = true;
Expand Down
25 changes: 25 additions & 0 deletions src/passes/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,24 @@ struct PrintExpressionContents
}
o << " " << int(curr->index);
}
void visitPrefetch(Prefetch* curr) {
prepareColor(o);
switch (curr->op) {
case PrefetchTemporal:
o << "prefetch.t";
break;
case PrefetchNontemporal:
o << "prefetch.nt";
break;
}
restoreNormalColor(o);
if (curr->offset) {
o << " offset=" << curr->offset;
}
if (curr->align != 1) {
o << " align=" << curr->align;
}
}
void visitMemoryInit(MemoryInit* curr) {
prepareColor(o);
o << "memory.init " << curr->segment;
Expand Down Expand Up @@ -2212,6 +2230,13 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
printFullLine(curr->vec);
decIndent();
}
void visitPrefetch(Prefetch* curr) {
o << '(';
PrintExpressionContents(currFunction, o).visit(curr);
incIndent();
printFullLine(curr->ptr);
decIndent();
}
void visitMemoryInit(MemoryInit* curr) {
o << '(';
PrintExpressionContents(currFunction, o).visit(curr);
Expand Down
6 changes: 6 additions & 0 deletions src/wasm-binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,11 @@ enum ASTNodes {
I64x2ExtMulLowUI32x4 = 0xd6,
I64x2ExtMulHighUI32x4 = 0xd7,

// prefetch opcodes

PrefetchT = 0xc5,
PrefetchNT = 0xc6,

// bulk memory opcodes

MemoryInit = 0x08,
Expand Down Expand Up @@ -1481,6 +1486,7 @@ class WasmBinaryBuilder {
bool maybeVisitSIMDShift(Expression*& out, uint32_t code);
bool maybeVisitSIMDLoad(Expression*& out, uint32_t code);
bool maybeVisitSIMDLoadStoreLane(Expression*& out, uint32_t code);
bool maybeVisitPrefetch(Expression*& out, uint32_t code);
bool maybeVisitMemoryInit(Expression*& out, uint32_t code);
bool maybeVisitDataDrop(Expression*& out, uint32_t code);
bool maybeVisitMemoryCopy(Expression*& out, uint32_t code);
Expand Down
9 changes: 9 additions & 0 deletions src/wasm-delegations-fields.h
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,15 @@ switch (DELEGATE_ID) {
DELEGATE_END(SIMDLoadStoreLane);
break;
}
case Expression::Id::PrefetchId: {
DELEGATE_START(Prefetch);
DELEGATE_FIELD_CHILD(Prefetch, ptr);
DELEGATE_FIELD_INT(Prefetch, op);
DELEGATE_FIELD_ADDRESS(Prefetch, offset);
DELEGATE_FIELD_ADDRESS(Prefetch, align);
DELEGATE_END(Prefetch);
break;
}
case Expression::Id::MemoryInitId: {
DELEGATE_START(MemoryInit);
DELEGATE_FIELD_CHILD(MemoryInit, size);
Expand Down
1 change: 1 addition & 0 deletions src/wasm-delegations.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ DELEGATE(SIMDTernary);
DELEGATE(SIMDShift);
DELEGATE(SIMDLoad);
DELEGATE(SIMDLoadStoreLane);
DELEGATE(Prefetch);
DELEGATE(MemoryInit);
DELEGATE(DataDrop);
DELEGATE(MemoryCopy);
Expand Down
8 changes: 8 additions & 0 deletions src/wasm-interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -1167,6 +1167,14 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
NOTE_ENTER("Nop");
return Flow();
}
Flow visitPrefetch(Prefetch* curr) {
NOTE_ENTER("Prefetch");
Flow flow = visit(curr->ptr);
if (flow.breaking()) {
return flow;
}
return Flow();
}
Flow visitUnreachable(Unreachable* curr) {
NOTE_ENTER("Unreachable");
trap("unreachable");
Expand Down
1 change: 1 addition & 0 deletions src/wasm-s-parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ class SExpressionWasmBuilder {
Expression* makeSIMDShift(Element& s, SIMDShiftOp op);
Expression* makeSIMDLoad(Element& s, SIMDLoadOp op);
Expression* makeSIMDLoadStoreLane(Element& s, SIMDLoadStoreLaneOp op);
Expression* makePrefetch(Element& s, PrefetchOp op);
Expression* makeMemoryInit(Element& s);
Expression* makeDataDrop(Element& s);
Expression* makeMemoryCopy(Element& s);
Expand Down
18 changes: 18 additions & 0 deletions src/wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,11 @@ enum SIMDTernaryOp {
SignSelectVec64x2
};

enum PrefetchOp {
PrefetchTemporal,
PrefetchNontemporal,
};

//
// Expressions
//
Expand Down Expand Up @@ -577,6 +582,7 @@ class Expression {
MemorySizeId,
MemoryGrowId,
NopId,
PrefetchId,
UnreachableId,
AtomicRMWId,
AtomicCmpxchgId,
Expand Down Expand Up @@ -1037,6 +1043,18 @@ class SIMDLoadStoreLane
void finalize();
};

class Prefetch : public SpecificExpression<Expression::PrefetchId> {
public:
Prefetch() = default;
Prefetch(MixedArena& allocator) : Prefetch() {}

PrefetchOp op;
Address offset;
Address align;
Expression* ptr;
void finalize();
};

class MemoryInit : public SpecificExpression<Expression::MemoryInitId> {
public:
MemoryInit() = default;
Expand Down
24 changes: 24 additions & 0 deletions src/wasm/wasm-binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2967,6 +2967,9 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
if (maybeVisitSIMDLoadStoreLane(curr, opcode)) {
break;
}
if (maybeVisitPrefetch(curr, opcode)) {
break;
}
throwError("invalid code after SIMD prefix: " + std::to_string(opcode));
break;
}
Expand Down Expand Up @@ -5372,6 +5375,27 @@ bool WasmBinaryBuilder::maybeVisitSIMDLoadStoreLane(Expression*& out,
return true;
}

bool WasmBinaryBuilder::maybeVisitPrefetch(Expression*& out, uint32_t code) {
PrefetchOp op;
switch (code) {
case BinaryConsts::PrefetchT:
op = PrefetchTemporal;
break;
case BinaryConsts::PrefetchNT:
op = PrefetchNontemporal;
break;
default:
return false;
}
auto* curr = allocator.alloc<Prefetch>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's better to use builder.makePrefetch, that is, to leave the direct allocation to the Builder as much as possible, both here an in the s-parser code.

curr->op = op;
readMemoryAccess(curr->align, curr->offset);
curr->ptr = popNonVoidExpression();
curr->finalize();
out = curr;
return true;
}

void WasmBinaryBuilder::visitSelect(Select* curr, uint8_t code) {
BYN_TRACE("zz node: Select, code " << int32_t(code) << std::endl);
if (code == BinaryConsts::SelectWithType) {
Expand Down
9 changes: 9 additions & 0 deletions src/wasm/wasm-s-parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1662,6 +1662,15 @@ SExpressionWasmBuilder::makeSIMDLoadStoreLane(Element& s,
return ret;
}

Expression* SExpressionWasmBuilder::makePrefetch(Element& s, PrefetchOp op) {
auto* ret = allocator.alloc<Prefetch>();
ret->op = op;
size_t i = parseMemAttributes(s, ret->offset, ret->align, /*defaultAlign*/ 1);
ret->ptr = parseExpression(s[i]);
ret->finalize();
return ret;
}

Expression* SExpressionWasmBuilder::makeMemoryInit(Element& s) {
auto ret = allocator.alloc<MemoryInit>();
ret->segment = atoi(s[1]->str().c_str());
Expand Down
14 changes: 14 additions & 0 deletions src/wasm/wasm-stack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,20 @@ void BinaryInstWriter::visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
o << curr->index;
}

void BinaryInstWriter::visitPrefetch(Prefetch* curr) {
o << int8_t(BinaryConsts::SIMDPrefix);
switch (curr->op) {
case PrefetchTemporal:
o << U32LEB(BinaryConsts::PrefetchT);
break;
case PrefetchNontemporal:
o << U32LEB(BinaryConsts::PrefetchNT);
break;
}
assert(curr->align);
emitMemoryAccess(curr->align, /*(unused) bytes=*/0, curr->offset);
}

void BinaryInstWriter::visitMemoryInit(MemoryInit* curr) {
o << int8_t(BinaryConsts::MiscPrefix);
o << U32LEB(BinaryConsts::MemoryInit);
Expand Down
6 changes: 6 additions & 0 deletions src/wasm/wasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ const char* getExpressionName(Expression* curr) {
return "simd_load";
case Expression::Id::SIMDLoadStoreLaneId:
return "simd_load_store_lane";
case Expression::Id::PrefetchId:
return "prefetch";
case Expression::Id::MemoryInitId:
return "memory.init";
case Expression::Id::DataDropId:
Expand Down Expand Up @@ -656,6 +658,10 @@ bool SIMDLoadStoreLane::isStore() {
WASM_UNREACHABLE("unexpected op");
}

void Prefetch::finalize() {
type = ptr->type == Type::unreachable ? Type::unreachable : Type::none;
}

Const* Const::set(Literal value_) {
value = value_;
type = value.type;
Expand Down
1 change: 1 addition & 0 deletions src/wasm2js.h
Original file line number Diff line number Diff line change
Expand Up @@ -1984,6 +1984,7 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
}

Ref visitNop(Nop* curr) { return ValueBuilder::makeToplevel(); }
Ref visitPrefetch(Prefetch* curr) { return ValueBuilder::makeToplevel(); }

Ref visitUnreachable(Unreachable* curr) {
return ValueBuilder::makeCall(ABORT_FUNC);
Expand Down
10 changes: 10 additions & 0 deletions test/simd.wast
Original file line number Diff line number Diff line change
Expand Up @@ -1396,4 +1396,14 @@
(local.get $1)
)
)
(func $prefetch.t (param $0 i32)
(prefetch.t offset=3 align=2
(local.get $0)
)
)
(func $prefetch.nt (param $0 i32)
(prefetch.nt offset=3 align=2
(local.get $0)
)
)
)
11 changes: 11 additions & 0 deletions test/simd.wast.from-wast
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
(type $i32_v128_=>_none (func (param i32 v128)))
(type $i32_v128_=>_v128 (func (param i32 v128) (result v128)))
(type $none_=>_v128 (func (result v128)))
(type $i32_=>_none (func (param i32)))
(type $v128_=>_i64 (func (param v128) (result i64)))
(type $v128_=>_f32 (func (param v128) (result f32)))
(type $v128_=>_f64 (func (param v128) (result f64)))
Expand Down Expand Up @@ -1413,4 +1414,14 @@
(local.get $1)
)
)
(func $prefetch.t (param $0 i32)
(prefetch.t offset=3 align=2
(local.get $0)
)
)
(func $prefetch.nt (param $0 i32)
(prefetch.nt offset=3 align=2
(local.get $0)
)
)
)
11 changes: 11 additions & 0 deletions test/simd.wast.fromBinary
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
(type $i32_v128_=>_none (func (param i32 v128)))
(type $i32_v128_=>_v128 (func (param i32 v128) (result v128)))
(type $none_=>_v128 (func (result v128)))
(type $i32_=>_none (func (param i32)))
(type $v128_=>_i64 (func (param v128) (result i64)))
(type $v128_=>_f32 (func (param v128) (result f32)))
(type $v128_=>_f64 (func (param v128) (result f64)))
Expand Down Expand Up @@ -1413,5 +1414,15 @@
(local.get $1)
)
)
(func $prefetch.t (param $0 i32)
(prefetch.t offset=3 align=2
(local.get $0)
)
)
(func $prefetch.nt (param $0 i32)
(prefetch.nt offset=3 align=2
(local.get $0)
)
)
)

Loading