Skip to content

Commit 1cb0b56

Browse files
committed
[WebAssembly] Prototype i64x2.widen_{low,high}_i32x4_{s,u}
As proposed in WebAssembly/simd#290. As usual, these instructions are available only via builtin functions and intrinsics while they are in the prototyping stage. Differential Revision: https://reviews.llvm.org/D90504
1 parent 72ddd55 commit 1cb0b56

File tree

7 files changed

+126
-0
lines changed

7 files changed

+126
-0
lines changed

clang/include/clang/Basic/BuiltinsWebAssembly.def

+5
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,11 @@ TARGET_BUILTIN(__builtin_wasm_narrow_u_i8x16_i16x8, "V16UcV8UsV8Us", "nc", "simd
194194
TARGET_BUILTIN(__builtin_wasm_narrow_s_i16x8_i32x4, "V8sV4iV4i", "nc", "simd128")
195195
TARGET_BUILTIN(__builtin_wasm_narrow_u_i16x8_i32x4, "V8UsV4UiV4Ui", "nc", "simd128")
196196

197+
TARGET_BUILTIN(__builtin_wasm_widen_low_s_i32x4_i64x2, "V2LLiV4i", "nc", "simd128")
198+
TARGET_BUILTIN(__builtin_wasm_widen_high_s_i32x4_i64x2, "V2LLiV4i", "nc", "simd128")
199+
TARGET_BUILTIN(__builtin_wasm_widen_low_u_i32x4_i64x2, "V2LLUiV4Ui", "nc", "simd128")
200+
TARGET_BUILTIN(__builtin_wasm_widen_high_u_i32x4_i64x2, "V2LLUiV4Ui", "nc", "simd128")
201+
197202
TARGET_BUILTIN(__builtin_wasm_load32_zero, "V4ii*", "n", "simd128")
198203
TARGET_BUILTIN(__builtin_wasm_load64_zero, "V2LLiLLi*", "n", "simd128")
199204

clang/lib/CodeGen/CGBuiltin.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -16792,6 +16792,29 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
1679216792
CGM.getIntrinsic(IntNo, {ConvertType(E->getType()), Low->getType()});
1679316793
return Builder.CreateCall(Callee, {Low, High});
1679416794
}
16795+
case WebAssembly::BI__builtin_wasm_widen_low_s_i32x4_i64x2:
16796+
case WebAssembly::BI__builtin_wasm_widen_high_s_i32x4_i64x2:
16797+
case WebAssembly::BI__builtin_wasm_widen_low_u_i32x4_i64x2:
16798+
case WebAssembly::BI__builtin_wasm_widen_high_u_i32x4_i64x2: {
16799+
Value *Vec = EmitScalarExpr(E->getArg(0));
16800+
unsigned IntNo;
16801+
switch (BuiltinID) {
16802+
case WebAssembly::BI__builtin_wasm_widen_low_s_i32x4_i64x2:
16803+
IntNo = Intrinsic::wasm_widen_low_signed;
16804+
break;
16805+
case WebAssembly::BI__builtin_wasm_widen_high_s_i32x4_i64x2:
16806+
IntNo = Intrinsic::wasm_widen_high_signed;
16807+
break;
16808+
case WebAssembly::BI__builtin_wasm_widen_low_u_i32x4_i64x2:
16809+
IntNo = Intrinsic::wasm_widen_low_unsigned;
16810+
break;
16811+
case WebAssembly::BI__builtin_wasm_widen_high_u_i32x4_i64x2:
16812+
IntNo = Intrinsic::wasm_widen_high_unsigned;
16813+
break;
16814+
}
16815+
Function *Callee = CGM.getIntrinsic(IntNo);
16816+
return Builder.CreateCall(Callee, Vec);
16817+
}
1679516818
case WebAssembly::BI__builtin_wasm_load32_zero: {
1679616819
Value *Ptr = EmitScalarExpr(E->getArg(0));
1679716820
Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_load32_zero);

clang/test/CodeGen/builtins-wasm.c

+24
Original file line numberDiff line numberDiff line change
@@ -918,6 +918,30 @@ u16x8 narrow_u_i16x8_i32x4(u32x4 low, u32x4 high) {
918918
// WEBASSEMBLY: ret
919919
}
920920

921+
i64x2 widen_low_s_i32x4_i64x2(i32x4 x) {
922+
return __builtin_wasm_widen_low_s_i32x4_i64x2(x);
923+
// WEBASSEMBLY: call <2 x i64> @llvm.wasm.widen.low.signed(<4 x i32> %x)
924+
// WEBASSEMBLY: ret
925+
}
926+
927+
i64x2 widen_high_s_i32x4_i64x2(i32x4 x) {
928+
return __builtin_wasm_widen_high_s_i32x4_i64x2(x);
929+
// WEBASSEMBLY: call <2 x i64> @llvm.wasm.widen.high.signed(<4 x i32> %x)
930+
// WEBASSEMBLY: ret
931+
}
932+
933+
u64x2 widen_low_u_i32x4_i64x2(u32x4 x) {
934+
return __builtin_wasm_widen_low_u_i32x4_i64x2(x);
935+
// WEBASSEMBLY: call <2 x i64> @llvm.wasm.widen.low.unsigned(<4 x i32> %x)
936+
// WEBASSEMBLY: ret
937+
}
938+
939+
u64x2 widen_high_u_i32x4_i64x2(u32x4 x) {
940+
return __builtin_wasm_widen_high_u_i32x4_i64x2(x);
941+
// WEBASSEMBLY: call <2 x i64> @llvm.wasm.widen.high.unsigned(<4 x i32> %x)
942+
// WEBASSEMBLY: ret
943+
}
944+
921945
i32x4 load32_zero(int *p) {
922946
return __builtin_wasm_load32_zero(p);
923947
// WEBASSEMBLY: call <4 x i32> @llvm.wasm.load32.zero(i32* %p)

llvm/include/llvm/IR/IntrinsicsWebAssembly.td

+13
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ def int_wasm_dot :
151151
Intrinsic<[llvm_v4i32_ty],
152152
[llvm_v8i16_ty, llvm_v8i16_ty],
153153
[IntrNoMem, IntrSpeculatable]>;
154+
154155
def int_wasm_narrow_signed :
155156
Intrinsic<[llvm_anyvector_ty],
156157
[llvm_anyvector_ty, LLVMMatchType<1>],
@@ -159,6 +160,18 @@ def int_wasm_narrow_unsigned :
159160
Intrinsic<[llvm_anyvector_ty],
160161
[llvm_anyvector_ty, LLVMMatchType<1>],
161162
[IntrNoMem, IntrSpeculatable]>;
163+
164+
// TODO: Replace these intrinsics with normal ISel patterns once i32x4 to i64x2
165+
// widening is merged to the proposal.
166+
def int_wasm_widen_low_signed :
167+
Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem, IntrSpeculatable]>;
168+
def int_wasm_widen_high_signed :
169+
Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem, IntrSpeculatable]>;
170+
def int_wasm_widen_low_unsigned :
171+
Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem, IntrSpeculatable]>;
172+
def int_wasm_widen_high_unsigned :
173+
Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem, IntrSpeculatable]>;
174+
162175
def int_wasm_q15mulr_saturate_signed :
163176
Intrinsic<[llvm_v8i16_ty],
164177
[llvm_v8i16_ty, llvm_v8i16_ty],

llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td

+9
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,15 @@ multiclass SIMDWiden<ValueType vec_t, string vec, ValueType arg_t, string arg,
11161116
defm "" : SIMDWiden<v8i16, "i16x8", v16i8, "i8x16", 135>;
11171117
defm "" : SIMDWiden<v4i32, "i32x4", v8i16, "i16x8", 167>;
11181118

1119+
defm "" : SIMDConvert<v2i64, v4i32, int_wasm_widen_low_signed,
1120+
"i64x2.widen_low_i32x4_s", 199>;
1121+
defm "" : SIMDConvert<v2i64, v4i32, int_wasm_widen_high_signed,
1122+
"i64x2.widen_high_i32x4_s", 200>;
1123+
defm "" : SIMDConvert<v2i64, v4i32, int_wasm_widen_low_unsigned,
1124+
"i64x2.widen_low_i32x4_u", 201>;
1125+
defm "" : SIMDConvert<v2i64, v4i32, int_wasm_widen_high_unsigned,
1126+
"i64x2.widen_high_i32x4_u", 202>;
1127+
11191128
// Narrowing operations
11201129
multiclass SIMDNarrow<ValueType vec_t, string vec, ValueType arg_t, string arg,
11211130
bits<32> baseInst> {

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

+40
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,46 @@ define <4 x i32> @trunc_sat_u_v4i32(<4 x float> %x) {
528528
; ==============================================================================
529529
; 2 x i64
530530
; ==============================================================================
531+
; CHECK-LABEL: widen_low_s_v2i64:
532+
; SIMD128-NEXT: .functype widen_low_s_v2i64 (v128) -> (v128){{$}}
533+
; SIMD128-NEXT: i64x2.widen_low_i32x4_s $push[[R:[0-9]+]]=, $0{{$}}
534+
; SIMD128-NEXT: return $pop[[R]]{{$}}
535+
declare <2 x i64> @llvm.wasm.widen.low.signed(<4 x i32>)
536+
define <2 x i64> @widen_low_s_v2i64(<4 x i32> %x) {
537+
%a = call <2 x i64> @llvm.wasm.widen.low.signed(<4 x i32> %x)
538+
ret <2 x i64> %a
539+
}
540+
541+
; CHECK-LABEL: widen_high_s_v2i64:
542+
; SIMD128-NEXT: .functype widen_high_s_v2i64 (v128) -> (v128){{$}}
543+
; SIMD128-NEXT: i64x2.widen_high_i32x4_s $push[[R:[0-9]+]]=, $0{{$}}
544+
; SIMD128-NEXT: return $pop[[R]]{{$}}
545+
declare <2 x i64> @llvm.wasm.widen.high.signed(<4 x i32>)
546+
define <2 x i64> @widen_high_s_v2i64(<4 x i32> %x) {
547+
%a = call <2 x i64> @llvm.wasm.widen.high.signed(<4 x i32> %x)
548+
ret <2 x i64> %a
549+
}
550+
551+
; CHECK-LABEL: widen_low_u_v2i64:
552+
; SIMD128-NEXT: .functype widen_low_u_v2i64 (v128) -> (v128){{$}}
553+
; SIMD128-NEXT: i64x2.widen_low_i32x4_u $push[[R:[0-9]+]]=, $0{{$}}
554+
; SIMD128-NEXT: return $pop[[R]]{{$}}
555+
declare <2 x i64> @llvm.wasm.widen.low.unsigned(<4 x i32>)
556+
define <2 x i64> @widen_low_u_v2i64(<4 x i32> %x) {
557+
%a = call <2 x i64> @llvm.wasm.widen.low.unsigned(<4 x i32> %x)
558+
ret <2 x i64> %a
559+
}
560+
561+
; CHECK-LABEL: widen_high_u_v2i64:
562+
; SIMD128-NEXT: .functype widen_high_u_v2i64 (v128) -> (v128){{$}}
563+
; SIMD128-NEXT: i64x2.widen_high_i32x4_u $push[[R:[0-9]+]]=, $0{{$}}
564+
; SIMD128-NEXT: return $pop[[R]]{{$}}
565+
declare <2 x i64> @llvm.wasm.widen.high.unsigned(<4 x i32>)
566+
define <2 x i64> @widen_high_u_v2i64(<4 x i32> %x) {
567+
%a = call <2 x i64> @llvm.wasm.widen.high.unsigned(<4 x i32> %x)
568+
ret <2 x i64> %a
569+
}
570+
531571
; CHECK-LABEL: extmul_low_s_v2i64:
532572
; SIMD128-NEXT: .functype extmul_low_s_v2i64 (v128, v128) -> (v128){{$}}
533573
; SIMD128-NEXT: i64x2.extmul_low_i32x4_s $push[[R:[0-9]+]]=, $0, $1{{$}}

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

+12
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,18 @@ main:
520520
# CHECK: i64x2.all_true # encoding: [0xfd,0xc3,0x01]
521521
i64x2.all_true
522522

523+
# CHECK: i64x2.widen_low_i32x4_s # encoding: [0xfd,0xc7,0x01]
524+
i64x2.widen_low_i32x4_s
525+
526+
# CHECK: i64x2.widen_high_i32x4_s # encoding: [0xfd,0xc8,0x01]
527+
i64x2.widen_high_i32x4_s
528+
529+
# CHECK: i64x2.widen_low_i32x4_u # encoding: [0xfd,0xc9,0x01]
530+
i64x2.widen_low_i32x4_u
531+
532+
# CHECK: i64x2.widen_high_i32x4_u # encoding: [0xfd,0xca,0x01]
533+
i64x2.widen_high_i32x4_u
534+
523535
# CHECK: i64x2.shl # encoding: [0xfd,0xcb,0x01]
524536
i64x2.shl
525537

0 commit comments

Comments
 (0)