Skip to content

Commit 569475e

Browse files
tlivelycuviper
authored andcommitted
[WebAssembly] Prototype i8x16 to i32x4 widening instructions
As proposed in WebAssembly/simd#395 and matching the opcodes used in V8: https://chromium-review.googlesource.com/c/v8/v8/+/2617385/4/src/wasm/wasm-opcodes.h Differential Revision: https://reviews.llvm.org/D95557
1 parent fd0fbf8 commit 569475e

File tree

7 files changed

+87
-1
lines changed

7 files changed

+87
-1
lines changed

clang/include/clang/Basic/BuiltinsWebAssembly.def

+3
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,9 @@ TARGET_BUILTIN(__builtin_wasm_widen_high_s_i32x4_i64x2, "V2LLiV4i", "nc", "simd1
206206
TARGET_BUILTIN(__builtin_wasm_widen_low_u_i32x4_i64x2, "V2LLUiV4Ui", "nc", "simd128")
207207
TARGET_BUILTIN(__builtin_wasm_widen_high_u_i32x4_i64x2, "V2LLUiV4Ui", "nc", "simd128")
208208

209+
TARGET_BUILTIN(__builtin_wasm_widen_s_i8x16_i32x4, "V4iV16ScIi", "nc", "simd128")
210+
TARGET_BUILTIN(__builtin_wasm_widen_u_i8x16_i32x4, "V4UiV16UcIi", "nc", "simd128")
211+
209212
TARGET_BUILTIN(__builtin_wasm_convert_low_s_i32x4_f64x2, "V2dV4i", "nc", "simd128")
210213
TARGET_BUILTIN(__builtin_wasm_convert_low_u_i32x4_f64x2, "V2dV4Ui", "nc", "simd128")
211214
TARGET_BUILTIN(__builtin_wasm_trunc_saturate_zero_s_f64x2_i32x4, "V4iV2d", "nc", "simd128")

clang/lib/CodeGen/CGBuiltin.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -17222,6 +17222,24 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
1722217222
Function *Callee = CGM.getIntrinsic(IntNo);
1722317223
return Builder.CreateCall(Callee, Vec);
1722417224
}
17225+
case WebAssembly::BI__builtin_wasm_widen_s_i8x16_i32x4:
17226+
case WebAssembly::BI__builtin_wasm_widen_u_i8x16_i32x4: {
17227+
Value *Vec = EmitScalarExpr(E->getArg(0));
17228+
llvm::APSInt SubVecConst =
17229+
*E->getArg(1)->getIntegerConstantExpr(getContext());
17230+
Value *SubVec = llvm::ConstantInt::get(getLLVMContext(), SubVecConst);
17231+
unsigned IntNo;
17232+
switch (BuiltinID) {
17233+
case WebAssembly::BI__builtin_wasm_widen_s_i8x16_i32x4:
17234+
IntNo = Intrinsic::wasm_widen_signed;
17235+
break;
17236+
case WebAssembly::BI__builtin_wasm_widen_u_i8x16_i32x4:
17237+
IntNo = Intrinsic::wasm_widen_unsigned;
17238+
break;
17239+
}
17240+
Function *Callee = CGM.getIntrinsic(IntNo);
17241+
return Builder.CreateCall(Callee, {Vec, SubVec});
17242+
}
1722517243
case WebAssembly::BI__builtin_wasm_convert_low_s_i32x4_f64x2:
1722617244
case WebAssembly::BI__builtin_wasm_convert_low_u_i32x4_f64x2: {
1722717245
Value *Vec = EmitScalarExpr(E->getArg(0));

clang/test/CodeGen/builtins-wasm.c

+12
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,18 @@ u64x2 widen_high_u_i32x4_i64x2(u32x4 x) {
976976
// WEBASSEMBLY: ret
977977
}
978978

979+
i32x4 widen_s_i8x16_i32x4(i8x16 x) {
980+
return __builtin_wasm_widen_s_i8x16_i32x4(x, 3);
981+
// WEBASSEMBLY: call <4 x i32> @llvm.wasm.widen.signed(<16 x i8> %x, i32 3)
982+
// WEBASSEMBLY: ret
983+
}
984+
985+
u32x4 widen_u_i8x16_i32x4(u8x16 x) {
986+
return __builtin_wasm_widen_u_i8x16_i32x4(x, 3);
987+
// WEBASSEMBLY: call <4 x i32> @llvm.wasm.widen.unsigned(<16 x i8> %x, i32 3)
988+
// WEBASSEMBLY: ret
989+
}
990+
979991
f64x2 convert_low_s_i32x4_f64x2(i32x4 x) {
980992
return __builtin_wasm_convert_low_s_i32x4_f64x2(x);
981993
// WEBASSEMBLY: call <2 x double> @llvm.wasm.convert.low.signed(<4 x i32> %x)

llvm/include/llvm/IR/IntrinsicsWebAssembly.td

+8
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,14 @@ def int_wasm_promote_low :
348348
Intrinsic<[llvm_v2f64_ty], [llvm_v4f32_ty],
349349
[IntrNoMem, IntrSpeculatable]>;
350350

351+
// TODO: Remove these if possible if they are merged to the spec.
352+
def int_wasm_widen_signed :
353+
Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty, llvm_i32_ty],
354+
[IntrNoMem, IntrSpeculatable, ImmArg<ArgIndex<1>>]>;
355+
def int_wasm_widen_unsigned :
356+
Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty, llvm_i32_ty],
357+
[IntrNoMem, IntrSpeculatable, ImmArg<ArgIndex<1>>]>;
358+
351359
//===----------------------------------------------------------------------===//
352360
// Thread-local storage intrinsics
353361
//===----------------------------------------------------------------------===//

llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td

+19-1
Original file line numberDiff line numberDiff line change
@@ -1256,7 +1256,6 @@ defm "" : SIMDConvert<I32x4, I16x8, int_wasm_extadd_pairwise_signed,
12561256
defm "" : SIMDConvert<I32x4, I16x8, int_wasm_extadd_pairwise_unsigned,
12571257
"extadd_pairwise_i16x8_u", 0xa6>;
12581258

1259-
12601259
// Prototype f64x2 conversions
12611260
defm "" : SIMDConvert<F64x2, I32x4, int_wasm_convert_low_signed,
12621261
"convert_low_i32x4_s", 0x53>;
@@ -1271,6 +1270,25 @@ defm "" : SIMDConvert<F32x4, F64x2, int_wasm_demote_zero,
12711270
defm "" : SIMDConvert<F64x2, F32x4, int_wasm_promote_low,
12721271
"promote_low_f32x4", 0x69>;
12731272

1273+
// Prototype i8x16 to i32x4 widening
1274+
defm WIDEN_I8x16_TO_I32x4_S :
1275+
SIMD_I<(outs V128:$dst), (ins V128:$vec, vec_i8imm_op:$idx),
1276+
(outs), (ins vec_i8imm_op:$idx),
1277+
[(set (I32x4.vt V128:$dst),
1278+
(I32x4.vt (int_wasm_widen_signed
1279+
(I8x16.vt V128:$vec), (i32 timm:$idx))))],
1280+
"i32x4.widen_i8x16_s\t$dst, $vec, $idx",
1281+
"i32x4.widen_i8x16_s\t$idx", 0x67>;
1282+
defm WIDEN_I8x16_TO_I32x4_U :
1283+
SIMD_I<(outs V128:$dst), (ins V128:$vec, vec_i8imm_op:$idx),
1284+
(outs), (ins vec_i8imm_op:$idx),
1285+
[(set (I32x4.vt V128:$dst),
1286+
(I32x4.vt (int_wasm_widen_unsigned
1287+
(I8x16.vt V128:$vec), (i32 timm:$idx))))],
1288+
"i32x4.widen_i8x16_u\t$dst, $vec, $idx",
1289+
"i32x4.widen_i8x16_u\t$idx", 0x68>;
1290+
1291+
12741292
//===----------------------------------------------------------------------===//
12751293
// Quasi-Fused Multiply- Add and Subtract (QFMA/QFMS)
12761294
//===----------------------------------------------------------------------===//

llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll

+21
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,27 @@ define <4 x i32> @trunc_sat_zero_unsigned_v4i32(<2 x double> %a) {
586586
ret <4 x i32> %v
587587
}
588588

589+
590+
; CHECK-LABEL: widen_signed_v4i32:
591+
; SIMD128-NEXT: .functype widen_signed_v4i32 (v128) -> (v128){{$}}
592+
; SIMD128-NEXT: i32x4.widen_i8x16_s $push[[R:[0-9]+]]=, $0, 1{{$}}
593+
; SIMD128-NEXT: return $pop[[R]]{{$}}
594+
declare <4 x i32> @llvm.wasm.widen.signed(<16 x i8>, i32 immarg)
595+
define <4 x i32> @widen_signed_v4i32(<16 x i8> %x) {
596+
%v = call <4 x i32> @llvm.wasm.widen.signed(<16 x i8> %x, i32 1)
597+
ret <4 x i32> %v
598+
}
599+
600+
; CHECK-LABEL: widen_unsigned_v4i32:
601+
; SIMD128-NEXT: .functype widen_unsigned_v4i32 (v128) -> (v128){{$}}
602+
; SIMD128-NEXT: i32x4.widen_i8x16_u $push[[R:[0-9]+]]=, $0, 1{{$}}
603+
; SIMD128-NEXT: return $pop[[R]]{{$}}
604+
declare <4 x i32> @llvm.wasm.widen.unsigned(<16 x i8>, i32 immarg)
605+
define <4 x i32> @widen_unsigned_v4i32(<16 x i8> %x) {
606+
%v = call <4 x i32> @llvm.wasm.widen.unsigned(<16 x i8> %x, i32 1)
607+
ret <4 x i32> %v
608+
}
609+
589610
; ==============================================================================
590611
; 2 x i64
591612
; ==============================================================================

llvm/test/MC/WebAssembly/simd-encodings.s

+6
Original file line numberDiff line numberDiff line change
@@ -760,4 +760,10 @@ main:
760760
# CHECK: f64x2.promote_low_f32x4 # encoding: [0xfd,0x69]
761761
f64x2.promote_low_f32x4
762762

763+
# CHECK: i32x4.widen_i8x16_s 3 # encoding: [0xfd,0x67,0x03]
764+
i32x4.widen_i8x16_s 3
765+
766+
# CHECK: i32x4.widen_i8x16_u 3 # encoding: [0xfd,0x68,0x03]
767+
i32x4.widen_i8x16_u 3
768+
763769
end_function

0 commit comments

Comments
 (0)