forked from OSchip/llvm-project
[WebAssembly] Add prototype relaxed float to int trunc instructions
Add i32x4.relaxed_trunc_f32x4_s, i32x4.relaxed_trunc_f32x4_u, i32x4.relaxed_trunc_f64x2_s_zero, i32x4.relaxed_trunc_f64x2_u_zero. These are only exposed as builtins, and require user opt-in. Differential Revision: https://reviews.llvm.org/D112186
This commit is contained in:
parent
a55632a069
commit
fb67f3d969
|
@ -179,5 +179,10 @@ TARGET_BUILTIN(__builtin_wasm_relaxed_max_f32x4, "V4fV4fV4f", "nc", "relaxed-sim
|
|||
TARGET_BUILTIN(__builtin_wasm_relaxed_min_f64x2, "V2dV2dV2d", "nc", "relaxed-simd")
|
||||
TARGET_BUILTIN(__builtin_wasm_relaxed_max_f64x2, "V2dV2dV2d", "nc", "relaxed-simd")
|
||||
|
||||
TARGET_BUILTIN(__builtin_wasm_relaxed_trunc_s_i32x4_f32x4, "V4iV4f", "nc", "relaxed-simd")
|
||||
TARGET_BUILTIN(__builtin_wasm_relaxed_trunc_u_i32x4_f32x4, "V4UiV4f", "nc", "relaxed-simd")
|
||||
TARGET_BUILTIN(__builtin_wasm_relaxed_trunc_zero_s_i32x4_f64x2, "V4iV2d", "nc", "relaxed-simd")
|
||||
TARGET_BUILTIN(__builtin_wasm_relaxed_trunc_zero_u_i32x4_f64x2, "V4UiV2d", "nc", "relaxed-simd")
|
||||
|
||||
#undef BUILTIN
|
||||
#undef TARGET_BUILTIN
|
||||
|
|
|
@ -18391,6 +18391,31 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
|
|||
Function *Callee = CGM.getIntrinsic(IntNo, LHS->getType());
|
||||
return Builder.CreateCall(Callee, {LHS, RHS});
|
||||
}
|
||||
case WebAssembly::BI__builtin_wasm_relaxed_trunc_s_i32x4_f32x4:
|
||||
case WebAssembly::BI__builtin_wasm_relaxed_trunc_u_i32x4_f32x4:
|
||||
case WebAssembly::BI__builtin_wasm_relaxed_trunc_zero_s_i32x4_f64x2:
|
||||
case WebAssembly::BI__builtin_wasm_relaxed_trunc_zero_u_i32x4_f64x2: {
|
||||
Value *Vec = EmitScalarExpr(E->getArg(0));
|
||||
unsigned IntNo;
|
||||
switch (BuiltinID) {
|
||||
case WebAssembly::BI__builtin_wasm_relaxed_trunc_s_i32x4_f32x4:
|
||||
IntNo = Intrinsic::wasm_relaxed_trunc_signed;
|
||||
break;
|
||||
case WebAssembly::BI__builtin_wasm_relaxed_trunc_u_i32x4_f32x4:
|
||||
IntNo = Intrinsic::wasm_relaxed_trunc_unsigned;
|
||||
break;
|
||||
case WebAssembly::BI__builtin_wasm_relaxed_trunc_zero_s_i32x4_f64x2:
|
||||
IntNo = Intrinsic::wasm_relaxed_trunc_zero_signed;
|
||||
break;
|
||||
case WebAssembly::BI__builtin_wasm_relaxed_trunc_zero_u_i32x4_f64x2:
|
||||
IntNo = Intrinsic::wasm_relaxed_trunc_zero_unsigned;
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("unexpected builtin ID");
|
||||
}
|
||||
Function *Callee = CGM.getIntrinsic(IntNo);
|
||||
return Builder.CreateCall(Callee, {Vec});
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -765,3 +765,27 @@ f64x2 relaxed_max_f64x2(f64x2 a, f64x2 b) {
|
|||
// WEBASSEMBLY-SAME: <2 x double> %a, <2 x double> %b)
|
||||
// WEBASSEMBLY-NEXT: ret
|
||||
}
|
||||
|
||||
i32x4 relaxed_trunc_s_i32x4_f32x4(f32x4 f) {
|
||||
return __builtin_wasm_relaxed_trunc_s_i32x4_f32x4(f);
|
||||
// WEBASSEMBLY: call <4 x i32> @llvm.wasm.relaxed.trunc.signed(<4 x float> %f)
|
||||
// WEBASSEMBLY-NEXT: ret
|
||||
}
|
||||
|
||||
u32x4 relaxed_trunc_u_i32x4_f32x4(f32x4 f) {
|
||||
return __builtin_wasm_relaxed_trunc_u_i32x4_f32x4(f);
|
||||
// WEBASSEMBLY: call <4 x i32> @llvm.wasm.relaxed.trunc.unsigned(<4 x float> %f)
|
||||
// WEBASSEMBLY-NEXT: ret
|
||||
}
|
||||
|
||||
i32x4 relaxed_trunc_zero_s_i32x4_f64x2(f64x2 x) {
|
||||
return __builtin_wasm_relaxed_trunc_zero_s_i32x4_f64x2(x);
|
||||
// WEBASSEMBLY: call <4 x i32> @llvm.wasm.relaxed.trunc.zero.signed(<2 x double> %x)
|
||||
// WEBASSEMBLY-NEXT: ret
|
||||
}
|
||||
|
||||
u32x4 relaxed_trunc_zero_u_i32x4_f64x2(f64x2 x) {
|
||||
return __builtin_wasm_relaxed_trunc_zero_u_i32x4_f64x2(x);
|
||||
// WEBASSEMBLY: call <4 x i32> @llvm.wasm.relaxed.trunc.zero.unsigned(<2 x double> %x)
|
||||
// WEBASSEMBLY-NEXT: ret
|
||||
}
|
||||
|
|
|
@ -214,6 +214,27 @@ def int_wasm_relaxed_max :
|
|||
[LLVMMatchType<0>, LLVMMatchType<0>],
|
||||
[IntrNoMem, IntrSpeculatable]>;
|
||||
|
||||
def int_wasm_relaxed_trunc_signed:
|
||||
Intrinsic<[llvm_v4i32_ty],
|
||||
[llvm_v4f32_ty],
|
||||
[IntrNoMem, IntrSpeculatable]>;
|
||||
|
||||
def int_wasm_relaxed_trunc_unsigned:
|
||||
Intrinsic<[llvm_v4i32_ty],
|
||||
[llvm_v4f32_ty],
|
||||
[IntrNoMem, IntrSpeculatable]>;
|
||||
|
||||
def int_wasm_relaxed_trunc_zero_signed:
|
||||
Intrinsic<[llvm_v4i32_ty],
|
||||
[llvm_v2f64_ty],
|
||||
[IntrNoMem, IntrSpeculatable]>;
|
||||
|
||||
def int_wasm_relaxed_trunc_zero_unsigned:
|
||||
Intrinsic<[llvm_v4i32_ty],
|
||||
[llvm_v2f64_ty],
|
||||
[IntrNoMem, IntrSpeculatable]>;
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Thread-local storage intrinsics
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -1392,3 +1392,20 @@ multiclass SIMD_RELAXED_FMINMAX<Vec vec, bits<32> simdopMin, bits<32> simdopMax>
|
|||
|
||||
defm "" : SIMD_RELAXED_FMINMAX<F32x4, 0xb4, 0xe2>;
|
||||
defm "" : SIMD_RELAXED_FMINMAX<F64x2, 0xd4, 0xee>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Relaxed floating-point to int conversions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
multiclass SIMD_RELAXED_CONVERT<Vec vec, Vec arg, SDPatternOperator op, string name, bits<32> simdop> {
|
||||
defm op#_#vec :
|
||||
RELAXED_I<(outs V128:$dst), (ins V128:$vec), (outs), (ins),
|
||||
[(set (vec.vt V128:$dst), (vec.vt (op (arg.vt V128:$vec))))],
|
||||
vec.prefix#"."#name#"\t$dst, $vec", vec.prefix#"."#name, simdop>;
|
||||
}
|
||||
|
||||
defm "" : SIMD_RELAXED_CONVERT<I32x4, F32x4, int_wasm_relaxed_trunc_signed, "relaxed_trunc_f32x4_s", 0xa5>;
|
||||
defm "" : SIMD_RELAXED_CONVERT<I32x4, F32x4, int_wasm_relaxed_trunc_unsigned, "relaxed_trunc_f32x4_u", 0xa6>;
|
||||
|
||||
defm "" : SIMD_RELAXED_CONVERT<I32x4, F64x2, int_wasm_relaxed_trunc_zero_signed, "relaxed_trunc_f64x2_s_zero", 0xc5>;
|
||||
defm "" : SIMD_RELAXED_CONVERT<I32x4, F64x2, int_wasm_relaxed_trunc_zero_unsigned, "relaxed_trunc_f64x2_u_zero", 0xc6>;
|
||||
|
|
|
@ -526,6 +526,48 @@ define <4 x i32> @laneselect_v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) {
|
|||
ret <4 x i32> %v
|
||||
}
|
||||
|
||||
; CHECK-LABEL: relaxed_trunc_s:
|
||||
; NO-CHECK-NOT: f32x4
|
||||
; CHECK-NEXT: .functype relaxed_trunc_s (v128) -> (v128){{$}}
|
||||
; CHECK-NEXT: i32x4.relaxed_trunc_f32x4_s $push[[R:[0-9]+]]=, $0
|
||||
; CHECK-NEXT: return $pop[[R]]
|
||||
declare <4 x i32> @llvm.wasm.relaxed.trunc.signed(<4 x float>)
|
||||
define <4 x i32> @relaxed_trunc_s(<4 x float> %x) {
|
||||
%a = call <4 x i32> @llvm.wasm.relaxed.trunc.signed(<4 x float> %x)
|
||||
ret <4 x i32> %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: relaxed_trunc_u:
|
||||
; NO-CHECK-NOT: f32x4
|
||||
; CHECK-NEXT: .functype relaxed_trunc_u (v128) -> (v128){{$}}
|
||||
; CHECK-NEXT: i32x4.relaxed_trunc_f32x4_u $push[[R:[0-9]+]]=, $0
|
||||
; CHECK-NEXT: return $pop[[R]]
|
||||
declare <4 x i32> @llvm.wasm.relaxed.trunc.unsigned(<4 x float>)
|
||||
define <4 x i32> @relaxed_trunc_u(<4 x float> %x) {
|
||||
%a = call <4 x i32> @llvm.wasm.relaxed.trunc.unsigned(<4 x float> %x)
|
||||
ret <4 x i32> %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: relaxed_trunc_zero_s:
|
||||
; CHECK-NEXT: .functype relaxed_trunc_zero_s (v128) -> (v128){{$}}
|
||||
; CHECK-NEXT: i32x4.relaxed_trunc_f64x2_s_zero $push[[R:[0-9]+]]=, $0{{$}}
|
||||
; CHECK-NEXT: return $pop[[R]]{{$}}
|
||||
declare <4 x i32> @llvm.wasm.relaxed.trunc.zero.signed(<2 x double>)
|
||||
define <4 x i32> @relaxed_trunc_zero_s(<2 x double> %x) {
|
||||
%a = call <4 x i32> @llvm.wasm.relaxed.trunc.zero.signed(<2 x double> %x)
|
||||
ret <4 x i32> %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: relaxed_trunc_zero_u:
|
||||
; CHECK-NEXT: .functype relaxed_trunc_zero_u (v128) -> (v128){{$}}
|
||||
; CHECK-NEXT: i32x4.relaxed_trunc_f64x2_u_zero $push[[R:[0-9]+]]=, $0{{$}}
|
||||
; CHECK-NEXT: return $pop[[R]]{{$}}
|
||||
declare <4 x i32> @llvm.wasm.relaxed.trunc.zero.unsigned(<2 x double>)
|
||||
define <4 x i32> @relaxed_trunc_zero_u(<2 x double> %x) {
|
||||
%a = call <4 x i32> @llvm.wasm.relaxed.trunc.zero.unsigned(<2 x double> %x)
|
||||
ret <4 x i32> %a
|
||||
}
|
||||
|
||||
; ==============================================================================
|
||||
; 2 x i64
|
||||
; ==============================================================================
|
||||
|
|
|
@ -818,4 +818,16 @@ main:
|
|||
# CHECK: f64x2.relaxed_max # encoding: [0xfd,0xee,0x01]
|
||||
f64x2.relaxed_max
|
||||
|
||||
# CHECK: i32x4.relaxed_trunc_f32x4_s # encoding: [0xfd,0xa5,0x01]
|
||||
i32x4.relaxed_trunc_f32x4_s
|
||||
|
||||
# CHECK: i32x4.relaxed_trunc_f32x4_u # encoding: [0xfd,0xa6,0x01]
|
||||
i32x4.relaxed_trunc_f32x4_u
|
||||
|
||||
# CHECK: i32x4.relaxed_trunc_f64x2_s_zero # encoding: [0xfd,0xc5,0x01]
|
||||
i32x4.relaxed_trunc_f64x2_s_zero
|
||||
|
||||
# CHECK: i32x4.relaxed_trunc_f64x2_u_zero # encoding: [0xfd,0xc6,0x01]
|
||||
i32x4.relaxed_trunc_f64x2_u_zero
|
||||
|
||||
end_function
|
||||
|
|
Loading…
Reference in New Issue