Repository navigation
Fuzzer: Emit SIMD lane load and store instructions - #9206
Conversation
…ructions Previously, br_on_cast_desc_eq and br_on_cast_desc_eq_fail were rarely emitted (~0.2 per module) because: 1. makeBrOn had low selection weight despite covering 6 instructions. 2. breakableStack searches stopped immediately on Type::none targets (forcing br_on_null) and often lacked reference targets. 3. Descriptor casts were only emitted when getSubType happened by chance to pick a struct with a descriptor. Fix this by: - Tracking described struct types by Shareability in describedTypes and adding hasDescribedSubType / getDescribedSubType helpers. - Increasing makeBrOn weight to Important. - Preferring reference targets (especially those with described subtypes) with randomness when searching breakableStack, and wrapping in a new target block when makeBrOn is called for a reference type without a suitable target. - Selecting BrOnCastDescEq and BrOnCastDescEqFail directly when described subtypes are available instead of upgrading BrOnCast / BrOnCastFail. Across 200 fuzzer modules, this increases br_on_cast_desc_eq from 0.20 to 2.69 per module (16.0% -> 48.0% of modules) and br_on_cast_desc_eq_fail from 0.18 to 2.88 per module (11.5% -> 50.0% of modules), while also increasing br_on_null from 27.40 to 34.46 per module.
For i64 pair tuples in _makeConcrete, add makeWideIntExpression with VeryImportant weight (requiring Multivalue as well as WideArithmetic) alongside makeTupleMake instead of replacing it half the time with default weight. This increases generation of unextracted (i64, i64) wide arithmetic expressions by ~4.2x.
Add try-delegate generation to TranslateToFuzzReader::makeTry and update fixAfterChanges to preserve DELEGATE_CALLER_TARGET on try-delegates. Also fix three bugs uncovered by fuzzing delegate and add regression tests: - Preserve concrete stack types on StackInst::Delegate in StackIRGenerator. - Increment controlFlowDepth after printing the condition in PrintSExpression::visitIf and pop catchIndexStack on StackInst::Delegate in printStackIR. - Use dynCast<Try>() instead of cast<Try>() when walking tryStack in CFGWalker.
Add makeElemDrop and call it from makeBulkMemory.
Generate extern.convert_any in makeBasicRef for HeapType::ext when GC is enabled.
Add makeMemorySize and makeMemoryGrow and include them in _makeConcrete when generating an integer matching the memory address type.
Add makeSIMDLoadStoreLane and call it from _makenone, makeSIMD, makeNonAtomicLoad, and makeNonAtomicStore. Also guard makeSIMDLoad with allowMemory.
Add makeTableSize and makeTableGrow and include them in _makeConcrete when generating an integer matching any table's address type. Also cap table->max at ReasonableMaxTableSize instead of kUnlimitedSize in finalizeTable so table.grow cannot allocate unbounded memory during fuzzing.
| if (type == Type::v128) { | ||
| assert(wasm.features.hasSIMD()); | ||
| if (oneIn(2)) { | ||
| return makeSIMDLoadStoreLane(type); |
There was a problem hiding this comment.
Why is the main code path to that function not enough?
There was a problem hiding this comment.
This function can already emit normal SIMD loads when type == Type::v128, so it seems reasonable to let it emit other kinds of SIMD loads as well.
I'm not tied to this, though. Putting SIMDLoadStoreLane only behind makeSIMD also seems reasonable. It will just make it much less likely to be generated, but I guess that's no different from any other SIMD instruction.
I'll make this change.
| &Self::makeNop, | ||
| &Self::makeGlobalSet) | ||
| .add(FeatureSet::BulkMemory, &Self::makeBulkMemory) | ||
| .add(FeatureSet::SIMD, &Self::makeSIMDLoadStoreLane) |
There was a problem hiding this comment.
It looks like in general we put all SIMD instructions behind makeSIMD()?
# Conflicts: # src/tools/fuzzing/fuzzing.cpp
# Conflicts: # src/tools/fuzzing/fuzzing.cpp # test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
# Conflicts: # test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
# Conflicts: # test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
# Conflicts: # test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
# Conflicts: # test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
# Conflicts: # test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
# Conflicts: # test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
# Conflicts: # test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
# Conflicts: # test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
# Conflicts: # test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
# Conflicts: # test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
# Conflicts: # test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
# Conflicts: # test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
# Conflicts: # test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
# Conflicts: # test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
# Conflicts: # test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
| if (!wasm.features.hasSIMD()) { | ||
| return makeTrivial(type); | ||
| } |
There was a problem hiding this comment.
These were dead code; we don't generate v128s if SIMD is not enabled.
|
@tlively Context: c28dd3c3e (Thomas Lively 2021-10-26 11:50:56 -0700 4899) case Type::v128: {
c28dd3c3e (Thomas Lively 2021-10-26 11:50:56 -0700 4900) assert(wasm.features.hasSIMD());If that isn't enough to figure out the issue I can get the |
Add makeSIMDLoadStoreLane and call it from _makenone, makeSIMD,
makeNonAtomicLoad, and makeNonAtomicStore. Also guard makeSIMDLoad with
allowMemory.