Skip to content

Commit 5c72975

Browse files
committed
[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
1 parent 4696857 commit 5c72975

File tree

12 files changed

+220
-717
lines changed

12 files changed

+220
-717
lines changed

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17073,8 +17073,8 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
1707317073
case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i32x4_f32x4: {
1707417074
Value *Src = EmitScalarExpr(E->getArg(0));
1707517075
llvm::Type *ResT = ConvertType(E->getType());
17076-
Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_trunc_saturate_signed,
17077-
{ResT, Src->getType()});
17076+
Function *Callee =
17077+
CGM.getIntrinsic(Intrinsic::fptosi_sat, {ResT, Src->getType()});
1707817078
return Builder.CreateCall(Callee, {Src});
1707917079
}
1708017080
case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i32_f32:
@@ -17084,8 +17084,8 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
1708417084
case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i32x4_f32x4: {
1708517085
Value *Src = EmitScalarExpr(E->getArg(0));
1708617086
llvm::Type *ResT = ConvertType(E->getType());
17087-
Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_trunc_saturate_unsigned,
17088-
{ResT, Src->getType()});
17087+
Function *Callee =
17088+
CGM.getIntrinsic(Intrinsic::fptoui_sat, {ResT, Src->getType()});
1708917089
return Builder.CreateCall(Callee, {Src});
1709017090
}
1709117091
case WebAssembly::BI__builtin_wasm_min_f32:
@@ -17481,16 +17481,24 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
1748117481
unsigned IntNo;
1748217482
switch (BuiltinID) {
1748317483
case WebAssembly::BI__builtin_wasm_trunc_sat_zero_s_f64x2_i32x4:
17484-
IntNo = Intrinsic::wasm_trunc_sat_zero_signed;
17484+
IntNo = Intrinsic::fptosi_sat;
1748517485
break;
1748617486
case WebAssembly::BI__builtin_wasm_trunc_sat_zero_u_f64x2_i32x4:
17487-
IntNo = Intrinsic::wasm_trunc_sat_zero_unsigned;
17487+
IntNo = Intrinsic::fptoui_sat;
1748817488
break;
1748917489
default:
1749017490
llvm_unreachable("unexpected builtin ID");
1749117491
}
17492-
Function *Callee = CGM.getIntrinsic(IntNo);
17493-
return Builder.CreateCall(Callee, Vec);
17492+
llvm::Type *SrcT = Vec->getType();
17493+
llvm::Type *TruncT =
17494+
SrcT->getWithNewType(llvm::IntegerType::get(getLLVMContext(), 32));
17495+
Function *Callee = CGM.getIntrinsic(IntNo, {TruncT, SrcT});
17496+
Value *Trunc = Builder.CreateCall(Callee, Vec);
17497+
Value *Splat = Builder.CreateVectorSplat(2, Builder.getInt32(0));
17498+
Value *ConcatMask =
17499+
llvm::ConstantVector::get({Builder.getInt32(0), Builder.getInt32(1),
17500+
Builder.getInt32(2), Builder.getInt32(3)});
17501+
return Builder.CreateShuffleVector(Trunc, Splat, ConcatMask);
1749417502
}
1749517503
case WebAssembly::BI__builtin_wasm_demote_zero_f64x2_f32x4: {
1749617504
Value *Vec = EmitScalarExpr(E->getArg(0));

clang/test/CodeGen/builtins-wasm.c

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -123,49 +123,49 @@ long long trunc_u_i64_f64(double f) {
123123

124124
int trunc_saturate_s_i32_f32(float f) {
125125
return __builtin_wasm_trunc_saturate_s_i32_f32(f);
126-
// WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float %f)
126+
// WEBASSEMBLY: call i32 @llvm.fptosi.sat.i32.f32(float %f)
127127
// WEBASSEMBLY-NEXT: ret
128128
}
129129

130130
int trunc_saturate_u_i32_f32(float f) {
131131
return __builtin_wasm_trunc_saturate_u_i32_f32(f);
132-
// WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float %f)
132+
// WEBASSEMBLY: call i32 @llvm.fptoui.sat.i32.f32(float %f)
133133
// WEBASSEMBLY-NEXT: ret
134134
}
135135

136136
int trunc_saturate_s_i32_f64(double f) {
137137
return __builtin_wasm_trunc_saturate_s_i32_f64(f);
138-
// WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double %f)
138+
// WEBASSEMBLY: call i32 @llvm.fptosi.sat.i32.f64(double %f)
139139
// WEBASSEMBLY-NEXT: ret
140140
}
141141

142142
int trunc_saturate_u_i32_f64(double f) {
143143
return __builtin_wasm_trunc_saturate_u_i32_f64(f);
144-
// WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double %f)
144+
// WEBASSEMBLY: call i32 @llvm.fptoui.sat.i32.f64(double %f)
145145
// WEBASSEMBLY-NEXT: ret
146146
}
147147

148148
long long trunc_saturate_s_i64_f32(float f) {
149149
return __builtin_wasm_trunc_saturate_s_i64_f32(f);
150-
// WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float %f)
150+
// WEBASSEMBLY: call i64 @llvm.fptosi.sat.i64.f32(float %f)
151151
// WEBASSEMBLY-NEXT: ret
152152
}
153153

154154
long long trunc_saturate_u_i64_f32(float f) {
155155
return __builtin_wasm_trunc_saturate_u_i64_f32(f);
156-
// WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float %f)
156+
// WEBASSEMBLY: call i64 @llvm.fptoui.sat.i64.f32(float %f)
157157
// WEBASSEMBLY-NEXT: ret
158158
}
159159

160160
long long trunc_saturate_s_i64_f64(double f) {
161161
return __builtin_wasm_trunc_saturate_s_i64_f64(f);
162-
// WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double %f)
162+
// WEBASSEMBLY: call i64 @llvm.fptosi.sat.i64.f64(double %f)
163163
// WEBASSEMBLY-NEXT: ret
164164
}
165165

166166
long long trunc_saturate_u_i64_f64(double f) {
167167
return __builtin_wasm_trunc_saturate_u_i64_f64(f);
168-
// WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double %f)
168+
// WEBASSEMBLY: call i64 @llvm.fptoui.sat.i64.f64(double %f)
169169
// WEBASSEMBLY-NEXT: ret
170170
}
171171

@@ -852,13 +852,13 @@ f64x2 sqrt_f64x2(f64x2 x) {
852852

853853
i32x4 trunc_saturate_s_i32x4_f32x4(f32x4 f) {
854854
return __builtin_wasm_trunc_saturate_s_i32x4_f32x4(f);
855-
// WEBASSEMBLY: call <4 x i32> @llvm.wasm.trunc.saturate.signed.v4i32.v4f32(<4 x float> %f)
855+
// WEBASSEMBLY: call <4 x i32> @llvm.fptosi.sat.v4i32.v4f32(<4 x float> %f)
856856
// WEBASSEMBLY-NEXT: ret
857857
}
858858

859859
i32x4 trunc_saturate_u_i32x4_f32x4(f32x4 f) {
860860
return __builtin_wasm_trunc_saturate_u_i32x4_f32x4(f);
861-
// WEBASSEMBLY: call <4 x i32> @llvm.wasm.trunc.saturate.unsigned.v4i32.v4f32(<4 x float> %f)
861+
// WEBASSEMBLY: call <4 x i32> @llvm.fptoui.sat.v4i32.v4f32(<4 x float> %f)
862862
// WEBASSEMBLY-NEXT: ret
863863
}
864864

@@ -892,14 +892,16 @@ u16x8 narrow_u_i16x8_i32x4(u32x4 low, u32x4 high) {
892892

893893
i32x4 trunc_sat_zero_s_f64x2_i32x4(f64x2 x) {
894894
return __builtin_wasm_trunc_sat_zero_s_f64x2_i32x4(x);
895-
// WEBASSEMBLY: call <4 x i32> @llvm.wasm.trunc.sat.zero.signed(<2 x double> %x)
896-
// WEBASSEMBLY: ret
895+
// WEBASSEMBLY: %0 = tail call <2 x i32> @llvm.fptosi.sat.v2i32.v2f64(<2 x double> %x)
896+
// WEBASSEMBLY: %1 = shufflevector <2 x i32> %0, <2 x i32> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
897+
// WEBASSEMBLY: ret <4 x i32> %1
897898
}
898899

899900
u32x4 trunc_sat_zero_u_f64x2_i32x4(f64x2 x) {
900901
return __builtin_wasm_trunc_sat_zero_u_f64x2_i32x4(x);
901-
// WEBASSEMBLY: call <4 x i32> @llvm.wasm.trunc.sat.zero.unsigned(<2 x double> %x)
902-
// WEBASSEMBLY: ret
902+
// WEBASSEMBLY: %0 = tail call <2 x i32> @llvm.fptoui.sat.v2i32.v2f64(<2 x double> %x)
903+
// WEBASSEMBLY: %1 = shufflevector <2 x i32> %0, <2 x i32> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
904+
// WEBASSEMBLY: ret <4 x i32> %1
903905
}
904906

905907
f32x4 wasm_demote_zero_f64x2_f32x4(f64x2 x) {

llvm/include/llvm/IR/IntrinsicsWebAssembly.td

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -264,12 +264,6 @@ def int_wasm_extadd_pairwise_unsigned :
264264
[IntrNoMem, IntrSpeculatable]>;
265265

266266
// TODO: Remove these if possible if they are merged to the spec.
267-
def int_wasm_trunc_sat_zero_signed :
268-
Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty],
269-
[IntrNoMem, IntrSpeculatable]>;
270-
def int_wasm_trunc_sat_zero_unsigned :
271-
Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty],
272-
[IntrNoMem, IntrSpeculatable]>;
273267
def int_wasm_demote_zero :
274268
Intrinsic<[llvm_v4f32_ty], [llvm_v2f64_ty],
275269
[IntrNoMem, IntrSpeculatable]>;

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,8 +1493,6 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
14931493
// WebAssembly float semantics are always known
14941494
case Intrinsic::wasm_trunc_signed:
14951495
case Intrinsic::wasm_trunc_unsigned:
1496-
case Intrinsic::wasm_trunc_saturate_signed:
1497-
case Intrinsic::wasm_trunc_saturate_unsigned:
14981496
return true;
14991497

15001498
// Floating point operations cannot be folded in strictfp functions in
@@ -1896,17 +1894,11 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
18961894
APFloat U = Op->getValueAPF();
18971895

18981896
if (IntrinsicID == Intrinsic::wasm_trunc_signed ||
1899-
IntrinsicID == Intrinsic::wasm_trunc_unsigned ||
1900-
IntrinsicID == Intrinsic::wasm_trunc_saturate_signed ||
1901-
IntrinsicID == Intrinsic::wasm_trunc_saturate_unsigned) {
1902-
1903-
bool Saturating = IntrinsicID == Intrinsic::wasm_trunc_saturate_signed ||
1904-
IntrinsicID == Intrinsic::wasm_trunc_saturate_unsigned;
1905-
bool Signed = IntrinsicID == Intrinsic::wasm_trunc_signed ||
1906-
IntrinsicID == Intrinsic::wasm_trunc_saturate_signed;
1897+
IntrinsicID == Intrinsic::wasm_trunc_unsigned) {
1898+
bool Signed = IntrinsicID == Intrinsic::wasm_trunc_signed;
19071899

19081900
if (U.isNaN())
1909-
return Saturating ? ConstantInt::get(Ty, 0) : nullptr;
1901+
return nullptr;
19101902

19111903
unsigned Width = Ty->getIntegerBitWidth();
19121904
APSInt Int(Width, !Signed);
@@ -1917,15 +1909,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
19171909
if (Status == APFloat::opOK || Status == APFloat::opInexact)
19181910
return ConstantInt::get(Ty, Int);
19191911

1920-
if (!Saturating)
1921-
return nullptr;
1922-
1923-
if (U.isNegative())
1924-
return Signed ? ConstantInt::get(Ty, APInt::getSignedMinValue(Width))
1925-
: ConstantInt::get(Ty, APInt::getMinValue(Width));
1926-
else
1927-
return Signed ? ConstantInt::get(Ty, APInt::getSignedMaxValue(Width))
1928-
: ConstantInt::get(Ty, APInt::getMaxValue(Width));
1912+
return nullptr;
19291913
}
19301914

19311915
if (IntrinsicID == Intrinsic::fptoui_sat ||

llvm/lib/Target/WebAssembly/WebAssemblyISD.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ HANDLE_NODETYPE(EXTEND_HIGH_S)
3535
HANDLE_NODETYPE(EXTEND_HIGH_U)
3636
HANDLE_NODETYPE(CONVERT_LOW_S)
3737
HANDLE_NODETYPE(CONVERT_LOW_U)
38+
HANDLE_NODETYPE(TRUNC_SAT_ZERO_S)
39+
HANDLE_NODETYPE(TRUNC_SAT_ZERO_U)
3840
HANDLE_NODETYPE(THROW)
3941
HANDLE_NODETYPE(CATCH)
4042
HANDLE_NODETYPE(MEMORY_COPY)

llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,11 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
121121
setOperationAction(Op, T, Expand);
122122
}
123123

124+
if (Subtarget->hasNontrappingFPToInt())
125+
for (auto Op : {ISD::FP_TO_SINT_SAT, ISD::FP_TO_UINT_SAT})
126+
for (auto T : {MVT::i32, MVT::i64})
127+
setOperationAction(Op, T, Custom);
128+
124129
// SIMD-specific configuration
125130
if (Subtarget->hasSIMD128()) {
126131
// Hoist bitcasts out of shuffles
@@ -134,6 +139,9 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
134139
setTargetDAGCombine(ISD::SINT_TO_FP);
135140
setTargetDAGCombine(ISD::UINT_TO_FP);
136141

142+
// Combine concat of {s,u}int_to_fp_sat to i32x4.trunc_sat_f64x2_zero_{s,u}
143+
setTargetDAGCombine(ISD::CONCAT_VECTORS);
144+
137145
// Support saturating add for i8x16 and i16x8
138146
for (auto Op : {ISD::SADDSAT, ISD::UADDSAT})
139147
for (auto T : {MVT::v16i8, MVT::v8i16})
@@ -198,6 +206,10 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
198206
{ISD::SINT_TO_FP, ISD::UINT_TO_FP, ISD::FP_TO_SINT, ISD::FP_TO_UINT})
199207
for (auto T : {MVT::v2i64, MVT::v2f64})
200208
setOperationAction(Op, T, Expand);
209+
210+
// But saturating fp_to_int converstions are
211+
for (auto Op : {ISD::FP_TO_SINT_SAT, ISD::FP_TO_UINT_SAT})
212+
setOperationAction(Op, MVT::v4i32, Custom);
201213
}
202214

203215
// As a special case, these operators use the type to mean the type to
@@ -1237,6 +1249,9 @@ SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
12371249
case ISD::SRA:
12381250
case ISD::SRL:
12391251
return LowerShift(Op, DAG);
1252+
case ISD::FP_TO_SINT_SAT:
1253+
case ISD::FP_TO_UINT_SAT:
1254+
return LowerFP_TO_INT_SAT(Op, DAG);
12401255
}
12411256
}
12421257

@@ -1953,6 +1968,21 @@ SDValue WebAssemblyTargetLowering::LowerShift(SDValue Op,
19531968
return DAG.getNode(Opcode, DL, Op.getValueType(), Op.getOperand(0), ShiftVal);
19541969
}
19551970

1971+
SDValue WebAssemblyTargetLowering::LowerFP_TO_INT_SAT(SDValue Op,
1972+
SelectionDAG &DAG) const {
1973+
SDLoc DL(Op);
1974+
EVT ResT = Op.getValueType();
1975+
uint64_t Width = Op.getConstantOperandVal(1);
1976+
1977+
if ((ResT == MVT::i32 || ResT == MVT::i64) && (Width == 32 || Width == 64))
1978+
return Op;
1979+
1980+
if (ResT == MVT::v4i32 && Width == 32)
1981+
return Op;
1982+
1983+
return SDValue();
1984+
}
1985+
19561986
//===----------------------------------------------------------------------===//
19571987
// Custom DAG combine hooks
19581988
//===----------------------------------------------------------------------===//
@@ -2041,6 +2071,8 @@ performVectorConvertLowCombine(SDNode *N,
20412071
if (Extract.getOpcode() != ISD::EXTRACT_SUBVECTOR)
20422072
return SDValue();
20432073
auto Source = Extract.getOperand(0);
2074+
if (Source.getValueType() != MVT::v4i32)
2075+
return SDValue();
20442076
auto *IndexNode = dyn_cast<ConstantSDNode>(Extract.getOperand(1));
20452077
if (IndexNode == nullptr)
20462078
return SDValue();
@@ -2062,6 +2094,49 @@ performVectorConvertLowCombine(SDNode *N,
20622094
return DAG.getNode(Op, SDLoc(N), ResVT, Source);
20632095
}
20642096

2097+
static SDValue
2098+
performVectorTruncSatLowCombine(SDNode *N,
2099+
TargetLowering::DAGCombinerInfo &DCI) {
2100+
auto &DAG = DCI.DAG;
2101+
assert(N->getOpcode() == ISD::CONCAT_VECTORS);
2102+
2103+
// Combine this:
2104+
//
2105+
// (concat_vectors (v2i32 (fp_to_{s,u}int_sat $x, 32)), (v2i32 (splat 0)))
2106+
//
2107+
// into (i32x4.trunc_sat_f64x2_zero_{s,u} $x).
2108+
EVT ResVT = N->getValueType(0);
2109+
if (ResVT != MVT::v4i32)
2110+
return SDValue();
2111+
2112+
auto FPToInt = N->getOperand(0);
2113+
auto FPToIntOp = FPToInt.getOpcode();
2114+
if (FPToIntOp != ISD::FP_TO_SINT_SAT && FPToIntOp != ISD::FP_TO_UINT_SAT)
2115+
return SDValue();
2116+
if (FPToInt.getConstantOperandVal(1) != 32)
2117+
return SDValue();
2118+
2119+
auto Source = FPToInt.getOperand(0);
2120+
if (Source.getValueType() != MVT::v2f64)
2121+
return SDValue();
2122+
2123+
auto *Splat = dyn_cast<BuildVectorSDNode>(N->getOperand(1));
2124+
APInt SplatValue, SplatUndef;
2125+
unsigned SplatBitSize;
2126+
bool HasAnyUndefs;
2127+
if (!Splat || !Splat->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
2128+
HasAnyUndefs))
2129+
return SDValue();
2130+
if (SplatValue != 0)
2131+
return SDValue();
2132+
2133+
unsigned Op = FPToIntOp == ISD::FP_TO_SINT_SAT
2134+
? WebAssemblyISD::TRUNC_SAT_ZERO_S
2135+
: WebAssemblyISD::TRUNC_SAT_ZERO_U;
2136+
2137+
return DAG.getNode(Op, SDLoc(N), ResVT, Source);
2138+
}
2139+
20652140
SDValue
20662141
WebAssemblyTargetLowering::PerformDAGCombine(SDNode *N,
20672142
DAGCombinerInfo &DCI) const {
@@ -2076,5 +2151,7 @@ WebAssemblyTargetLowering::PerformDAGCombine(SDNode *N,
20762151
case ISD::SINT_TO_FP:
20772152
case ISD::UINT_TO_FP:
20782153
return performVectorConvertLowCombine(N, DCI);
2154+
case ISD::CONCAT_VECTORS:
2155+
return performVectorTruncSatLowCombine(N, DCI);
20792156
}
20802157
}

llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ class WebAssemblyTargetLowering final : public TargetLowering {
119119
SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
120120
SDValue LowerAccessVectorElement(SDValue Op, SelectionDAG &DAG) const;
121121
SDValue LowerShift(SDValue Op, SelectionDAG &DAG) const;
122+
SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) const;
122123

123124
// Custom DAG combine hooks
124125
SDValue

llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -96,23 +96,15 @@ defm I64_TRUNC_U_SAT_F64 : I<(outs I64:$dst), (ins F64:$src), (outs), (ins),
9696
"i64.trunc_sat_f64_u", 0xfc07>,
9797
Requires<[HasNontrappingFPToInt]>;
9898

99-
// Lower llvm.wasm.trunc.saturate.* to saturating instructions
100-
def : Pat<(int_wasm_trunc_saturate_signed F32:$src),
101-
(I32_TRUNC_S_SAT_F32 F32:$src)>;
102-
def : Pat<(int_wasm_trunc_saturate_unsigned F32:$src),
103-
(I32_TRUNC_U_SAT_F32 F32:$src)>;
104-
def : Pat<(int_wasm_trunc_saturate_signed F64:$src),
105-
(I32_TRUNC_S_SAT_F64 F64:$src)>;
106-
def : Pat<(int_wasm_trunc_saturate_unsigned F64:$src),
107-
(I32_TRUNC_U_SAT_F64 F64:$src)>;
108-
def : Pat<(int_wasm_trunc_saturate_signed F32:$src),
109-
(I64_TRUNC_S_SAT_F32 F32:$src)>;
110-
def : Pat<(int_wasm_trunc_saturate_unsigned F32:$src),
111-
(I64_TRUNC_U_SAT_F32 F32:$src)>;
112-
def : Pat<(int_wasm_trunc_saturate_signed F64:$src),
113-
(I64_TRUNC_S_SAT_F64 F64:$src)>;
114-
def : Pat<(int_wasm_trunc_saturate_unsigned F64:$src),
115-
(I64_TRUNC_U_SAT_F64 F64:$src)>;
99+
// Support the explicitly saturating operations as well.
100+
def : Pat<(fp_to_sint_sat F32:$src, (i32 32)), (I32_TRUNC_S_SAT_F32 F32:$src)>;
101+
def : Pat<(fp_to_uint_sat F32:$src, (i32 32)), (I32_TRUNC_U_SAT_F32 F32:$src)>;
102+
def : Pat<(fp_to_sint_sat F64:$src, (i32 32)), (I32_TRUNC_S_SAT_F64 F64:$src)>;
103+
def : Pat<(fp_to_uint_sat F64:$src, (i32 32)), (I32_TRUNC_U_SAT_F64 F64:$src)>;
104+
def : Pat<(fp_to_sint_sat F32:$src, (i32 64)), (I64_TRUNC_S_SAT_F32 F32:$src)>;
105+
def : Pat<(fp_to_uint_sat F32:$src, (i32 64)), (I64_TRUNC_U_SAT_F32 F32:$src)>;
106+
def : Pat<(fp_to_sint_sat F64:$src, (i32 64)), (I64_TRUNC_S_SAT_F64 F64:$src)>;
107+
def : Pat<(fp_to_uint_sat F64:$src, (i32 64)), (I64_TRUNC_U_SAT_F64 F64:$src)>;
116108

117109
// Conversion from floating point to integer pseudo-instructions which don't
118110
// trap on overflow or invalid.

0 commit comments

Comments
 (0)