Skip to content

Commit 05751c8

Browse files
tlivelyalexcrichton
authored andcommitted
[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 6ffbea3 commit 05751c8

File tree

12 files changed

+220
-717
lines changed

12 files changed

+220
-717
lines changed

clang/lib/CodeGen/CGBuiltin.cpp

+16-8
Original file line numberDiff line numberDiff line change
@@ -16756,8 +16756,8 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
1675616756
case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i32x4_f32x4: {
1675716757
Value *Src = EmitScalarExpr(E->getArg(0));
1675816758
llvm::Type *ResT = ConvertType(E->getType());
16759-
Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_trunc_saturate_signed,
16760-
{ResT, Src->getType()});
16759+
Function *Callee =
16760+
CGM.getIntrinsic(Intrinsic::fptosi_sat, {ResT, Src->getType()});
1676116761
return Builder.CreateCall(Callee, {Src});
1676216762
}
1676316763
case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i32_f32:
@@ -16767,8 +16767,8 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
1676716767
case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i32x4_f32x4: {
1676816768
Value *Src = EmitScalarExpr(E->getArg(0));
1676916769
llvm::Type *ResT = ConvertType(E->getType());
16770-
Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_trunc_saturate_unsigned,
16771-
{ResT, Src->getType()});
16770+
Function *Callee =
16771+
CGM.getIntrinsic(Intrinsic::fptoui_sat, {ResT, Src->getType()});
1677216772
return Builder.CreateCall(Callee, {Src});
1677316773
}
1677416774
case WebAssembly::BI__builtin_wasm_min_f32:
@@ -17164,14 +17164,22 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
1716417164
unsigned IntNo;
1716517165
switch (BuiltinID) {
1716617166
case WebAssembly::BI__builtin_wasm_trunc_sat_zero_s_f64x2_i32x4:
17167-
IntNo = Intrinsic::wasm_trunc_sat_zero_signed;
17167+
IntNo = Intrinsic::fptosi_sat;
1716817168
break;
1716917169
case WebAssembly::BI__builtin_wasm_trunc_sat_zero_u_f64x2_i32x4:
17170-
IntNo = Intrinsic::wasm_trunc_sat_zero_unsigned;
17170+
IntNo = Intrinsic::fptoui_sat;
1717117171
break;
1717217172
}
17173-
Function *Callee = CGM.getIntrinsic(IntNo);
17174-
return Builder.CreateCall(Callee, Vec);
17173+
llvm::Type *SrcT = Vec->getType();
17174+
llvm::Type *TruncT =
17175+
SrcT->getWithNewType(llvm::IntegerType::get(getLLVMContext(), 32));
17176+
Function *Callee = CGM.getIntrinsic(IntNo, {TruncT, SrcT});
17177+
Value *Trunc = Builder.CreateCall(Callee, Vec);
17178+
Value *Splat = Builder.CreateVectorSplat(2, Builder.getInt32(0));
17179+
Value *ConcatMask =
17180+
llvm::ConstantVector::get({Builder.getInt32(0), Builder.getInt32(1),
17181+
Builder.getInt32(2), Builder.getInt32(3)});
17182+
return Builder.CreateShuffleVector(Trunc, Splat, ConcatMask);
1717517183
}
1717617184
case WebAssembly::BI__builtin_wasm_demote_zero_f64x2_f32x4: {
1717717185
Value *Vec = EmitScalarExpr(E->getArg(0));

clang/test/CodeGen/builtins-wasm.c

+16-14
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

-6
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

+4-20
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

+2
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

+77
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
@@ -1233,6 +1245,9 @@ SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
12331245
case ISD::SRA:
12341246
case ISD::SRL:
12351247
return LowerShift(Op, DAG);
1248+
case ISD::FP_TO_SINT_SAT:
1249+
case ISD::FP_TO_UINT_SAT:
1250+
return LowerFP_TO_INT_SAT(Op, DAG);
12361251
}
12371252
}
12381253

@@ -1949,6 +1964,21 @@ SDValue WebAssemblyTargetLowering::LowerShift(SDValue Op,
19491964
return DAG.getNode(Opcode, DL, Op.getValueType(), Op.getOperand(0), ShiftVal);
19501965
}
19511966

1967+
SDValue WebAssemblyTargetLowering::LowerFP_TO_INT_SAT(SDValue Op,
1968+
SelectionDAG &DAG) const {
1969+
SDLoc DL(Op);
1970+
EVT ResT = Op.getValueType();
1971+
uint64_t Width = Op.getConstantOperandVal(1);
1972+
1973+
if ((ResT == MVT::i32 || ResT == MVT::i64) && (Width == 32 || Width == 64))
1974+
return Op;
1975+
1976+
if (ResT == MVT::v4i32 && Width == 32)
1977+
return Op;
1978+
1979+
return SDValue();
1980+
}
1981+
19521982
//===----------------------------------------------------------------------===//
19531983
// Custom DAG combine hooks
19541984
//===----------------------------------------------------------------------===//
@@ -2037,6 +2067,8 @@ performVectorConvertLowCombine(SDNode *N,
20372067
if (Extract.getOpcode() != ISD::EXTRACT_SUBVECTOR)
20382068
return SDValue();
20392069
auto Source = Extract.getOperand(0);
2070+
if (Source.getValueType() != MVT::v4i32)
2071+
return SDValue();
20402072
auto *IndexNode = dyn_cast<ConstantSDNode>(Extract.getOperand(1));
20412073
if (IndexNode == nullptr)
20422074
return SDValue();
@@ -2058,6 +2090,49 @@ performVectorConvertLowCombine(SDNode *N,
20582090
return DAG.getNode(Op, SDLoc(N), ResVT, Source);
20592091
}
20602092

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

llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h

+1
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

+9-17
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)