[WebAssembly] Remove saturating fp-to-int target intrinsics
Use the target-independent @llvm.fptosi and @llvm.fptoui intrinsics instead.
This includes removing the instrinsics for i32x4.trunc_sat_zero_f64x2_{s,u},
which are now represented in IR as a saturating truncation to a v2i32 followed by
a concatenation with a zero vector.
Differential Revision: https://reviews.llvm.org/D100596
GitOrigin-RevId: 5c729750a6d75df4eeb3eaad72e0b4e93ea27c0e
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 860492a..7e19532 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -17073,8 +17073,8 @@
case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i32x4_f32x4: {
Value *Src = EmitScalarExpr(E->getArg(0));
llvm::Type *ResT = ConvertType(E->getType());
- Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_trunc_saturate_signed,
- {ResT, Src->getType()});
+ Function *Callee =
+ CGM.getIntrinsic(Intrinsic::fptosi_sat, {ResT, Src->getType()});
return Builder.CreateCall(Callee, {Src});
}
case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i32_f32:
@@ -17084,8 +17084,8 @@
case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i32x4_f32x4: {
Value *Src = EmitScalarExpr(E->getArg(0));
llvm::Type *ResT = ConvertType(E->getType());
- Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_trunc_saturate_unsigned,
- {ResT, Src->getType()});
+ Function *Callee =
+ CGM.getIntrinsic(Intrinsic::fptoui_sat, {ResT, Src->getType()});
return Builder.CreateCall(Callee, {Src});
}
case WebAssembly::BI__builtin_wasm_min_f32:
@@ -17481,16 +17481,24 @@
unsigned IntNo;
switch (BuiltinID) {
case WebAssembly::BI__builtin_wasm_trunc_sat_zero_s_f64x2_i32x4:
- IntNo = Intrinsic::wasm_trunc_sat_zero_signed;
+ IntNo = Intrinsic::fptosi_sat;
break;
case WebAssembly::BI__builtin_wasm_trunc_sat_zero_u_f64x2_i32x4:
- IntNo = Intrinsic::wasm_trunc_sat_zero_unsigned;
+ IntNo = Intrinsic::fptoui_sat;
break;
default:
llvm_unreachable("unexpected builtin ID");
}
- Function *Callee = CGM.getIntrinsic(IntNo);
- return Builder.CreateCall(Callee, Vec);
+ llvm::Type *SrcT = Vec->getType();
+ llvm::Type *TruncT =
+ SrcT->getWithNewType(llvm::IntegerType::get(getLLVMContext(), 32));
+ Function *Callee = CGM.getIntrinsic(IntNo, {TruncT, SrcT});
+ Value *Trunc = Builder.CreateCall(Callee, Vec);
+ Value *Splat = Builder.CreateVectorSplat(2, Builder.getInt32(0));
+ Value *ConcatMask =
+ llvm::ConstantVector::get({Builder.getInt32(0), Builder.getInt32(1),
+ Builder.getInt32(2), Builder.getInt32(3)});
+ return Builder.CreateShuffleVector(Trunc, Splat, ConcatMask);
}
case WebAssembly::BI__builtin_wasm_demote_zero_f64x2_f32x4: {
Value *Vec = EmitScalarExpr(E->getArg(0));
diff --git a/test/CodeGen/builtins-wasm.c b/test/CodeGen/builtins-wasm.c
index 1a986f0..d20b6a7 100644
--- a/test/CodeGen/builtins-wasm.c
+++ b/test/CodeGen/builtins-wasm.c
@@ -123,49 +123,49 @@
int trunc_saturate_s_i32_f32(float f) {
return __builtin_wasm_trunc_saturate_s_i32_f32(f);
- // WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float %f)
+ // WEBASSEMBLY: call i32 @llvm.fptosi.sat.i32.f32(float %f)
// WEBASSEMBLY-NEXT: ret
}
int trunc_saturate_u_i32_f32(float f) {
return __builtin_wasm_trunc_saturate_u_i32_f32(f);
- // WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float %f)
+ // WEBASSEMBLY: call i32 @llvm.fptoui.sat.i32.f32(float %f)
// WEBASSEMBLY-NEXT: ret
}
int trunc_saturate_s_i32_f64(double f) {
return __builtin_wasm_trunc_saturate_s_i32_f64(f);
- // WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double %f)
+ // WEBASSEMBLY: call i32 @llvm.fptosi.sat.i32.f64(double %f)
// WEBASSEMBLY-NEXT: ret
}
int trunc_saturate_u_i32_f64(double f) {
return __builtin_wasm_trunc_saturate_u_i32_f64(f);
- // WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double %f)
+ // WEBASSEMBLY: call i32 @llvm.fptoui.sat.i32.f64(double %f)
// WEBASSEMBLY-NEXT: ret
}
long long trunc_saturate_s_i64_f32(float f) {
return __builtin_wasm_trunc_saturate_s_i64_f32(f);
- // WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float %f)
+ // WEBASSEMBLY: call i64 @llvm.fptosi.sat.i64.f32(float %f)
// WEBASSEMBLY-NEXT: ret
}
long long trunc_saturate_u_i64_f32(float f) {
return __builtin_wasm_trunc_saturate_u_i64_f32(f);
- // WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float %f)
+ // WEBASSEMBLY: call i64 @llvm.fptoui.sat.i64.f32(float %f)
// WEBASSEMBLY-NEXT: ret
}
long long trunc_saturate_s_i64_f64(double f) {
return __builtin_wasm_trunc_saturate_s_i64_f64(f);
- // WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double %f)
+ // WEBASSEMBLY: call i64 @llvm.fptosi.sat.i64.f64(double %f)
// WEBASSEMBLY-NEXT: ret
}
long long trunc_saturate_u_i64_f64(double f) {
return __builtin_wasm_trunc_saturate_u_i64_f64(f);
- // WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double %f)
+ // WEBASSEMBLY: call i64 @llvm.fptoui.sat.i64.f64(double %f)
// WEBASSEMBLY-NEXT: ret
}
@@ -852,13 +852,13 @@
i32x4 trunc_saturate_s_i32x4_f32x4(f32x4 f) {
return __builtin_wasm_trunc_saturate_s_i32x4_f32x4(f);
- // WEBASSEMBLY: call <4 x i32> @llvm.wasm.trunc.saturate.signed.v4i32.v4f32(<4 x float> %f)
+ // WEBASSEMBLY: call <4 x i32> @llvm.fptosi.sat.v4i32.v4f32(<4 x float> %f)
// WEBASSEMBLY-NEXT: ret
}
i32x4 trunc_saturate_u_i32x4_f32x4(f32x4 f) {
return __builtin_wasm_trunc_saturate_u_i32x4_f32x4(f);
- // WEBASSEMBLY: call <4 x i32> @llvm.wasm.trunc.saturate.unsigned.v4i32.v4f32(<4 x float> %f)
+ // WEBASSEMBLY: call <4 x i32> @llvm.fptoui.sat.v4i32.v4f32(<4 x float> %f)
// WEBASSEMBLY-NEXT: ret
}
@@ -892,14 +892,16 @@
i32x4 trunc_sat_zero_s_f64x2_i32x4(f64x2 x) {
return __builtin_wasm_trunc_sat_zero_s_f64x2_i32x4(x);
- // WEBASSEMBLY: call <4 x i32> @llvm.wasm.trunc.sat.zero.signed(<2 x double> %x)
- // WEBASSEMBLY: ret
+ // WEBASSEMBLY: %0 = tail call <2 x i32> @llvm.fptosi.sat.v2i32.v2f64(<2 x double> %x)
+ // WEBASSEMBLY: %1 = shufflevector <2 x i32> %0, <2 x i32> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // WEBASSEMBLY: ret <4 x i32> %1
}
u32x4 trunc_sat_zero_u_f64x2_i32x4(f64x2 x) {
return __builtin_wasm_trunc_sat_zero_u_f64x2_i32x4(x);
- // WEBASSEMBLY: call <4 x i32> @llvm.wasm.trunc.sat.zero.unsigned(<2 x double> %x)
- // WEBASSEMBLY: ret
+ // WEBASSEMBLY: %0 = tail call <2 x i32> @llvm.fptoui.sat.v2i32.v2f64(<2 x double> %x)
+ // WEBASSEMBLY: %1 = shufflevector <2 x i32> %0, <2 x i32> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // WEBASSEMBLY: ret <4 x i32> %1
}
f32x4 wasm_demote_zero_f64x2_f32x4(f64x2 x) {