Skip to content
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: 10 additions & 2 deletions cranelift/wasm/src/code_translator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2407,8 +2407,16 @@ fn translate_store<FE: FuncEnvironment + ?Sized>(
state: &mut FuncTranslationState,
environ: &mut FE,
) -> WasmResult<()> {
let val = state.pop1();
let val_ty = builder.func.dfg.value_type(val);
let mut val = state.pop1();
let mut val_ty = builder.func.dfg.value_type(val);

// Boolean-vector types don't validate with a `store` instruction, so
// bitcast them to a vector type which is compatible with the store
// instruction.
if val_ty.is_vector() && val_ty.lane_type().is_bool() {
val = builder.ins().raw_bitcast(I8X16, val);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we instead define that boolean vectors can be stored using store directly and are stored as all-zero or all-one lanes?

Copy link
Copy Markdown
Member

@abrown abrown Aug 18, 2021

Choose a reason for hiding this comment

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

That is a good approach but I don't mind what @alexcrichton tried here because:

  • vector translation already involves a lot of bitcasting so this doesn't make the problem worse; if we want to solve the bitcasting we should just solve all of it and close Too many raw_bitcasts in SIMD code #1147
  • changing load and store to allow boolean vectors but not boolean scalars seems like it might cause errors somewhere; this fix would immediately fix a fuzz bug
  • I wouldn't mind settling the general issue about loads and stores with booleans once for all: I've seen mention recently of setting a memory representation for boolean scalars... If we settle it once for all (do we have an issue for this?) and document it then it might make sense to avoid the bitcast (if that's what is decided).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I just created #3205 for this. Agreed that for now, the immediate fuzzbug fix is fine.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ok I'm gonna go ahead and merge this fix for now and defer to #3205 for future updates.

val_ty = I8X16;
}

let (flags, base, offset) =
prepare_addr(memarg, mem_op_size(opcode, val_ty), builder, state, environ)?;
Expand Down
83 changes: 83 additions & 0 deletions cranelift/wasm/wasmtests/simd-store.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
(module
(func (param v128)
(v128.store (i32.const 0) (i8x16.eq (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (i16x8.eq (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (i32x4.eq (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (i64x2.eq (local.get 0) (local.get 0))))

(func (param v128)
(v128.store (i32.const 0) (i8x16.ne (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (i16x8.ne (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (i32x4.ne (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (i64x2.ne (local.get 0) (local.get 0))))

(func (param v128)
(v128.store (i32.const 0) (i8x16.lt_s (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (i16x8.lt_s (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (i32x4.lt_s (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (i64x2.lt_s (local.get 0) (local.get 0))))

(func (param v128)
(v128.store (i32.const 0) (i8x16.lt_u (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (i16x8.lt_u (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (i32x4.lt_u (local.get 0) (local.get 0))))

(func (param v128)
(v128.store (i32.const 0) (i8x16.gt_s (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (i16x8.gt_s (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (i32x4.gt_s (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (i64x2.gt_s (local.get 0) (local.get 0))))

(func (param v128)
(v128.store (i32.const 0) (i8x16.gt_u (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (i16x8.gt_u (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (i32x4.gt_u (local.get 0) (local.get 0))))

(func (param v128)
(v128.store (i32.const 0) (f32x4.eq (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (f64x2.eq (local.get 0) (local.get 0))))

(func (param v128)
(v128.store (i32.const 0) (f32x4.ne (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (f64x2.ne (local.get 0) (local.get 0))))

(func (param v128)
(v128.store (i32.const 0) (f32x4.lt (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (f64x2.lt (local.get 0) (local.get 0))))

(func (param v128)
(v128.store (i32.const 0) (f32x4.le (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (f64x2.le (local.get 0) (local.get 0))))

(func (param v128)
(v128.store (i32.const 0) (f32x4.gt (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (f64x2.gt (local.get 0) (local.get 0))))

(func (param v128)
(v128.store (i32.const 0) (f32x4.ge (local.get 0) (local.get 0))))
(func (param v128)
(v128.store (i32.const 0) (f64x2.ge (local.get 0) (local.get 0))))

(memory 0)
)