@@ -121,6 +121,11 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
121
121
setOperationAction (Op, T, Expand);
122
122
}
123
123
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
+
124
129
// SIMD-specific configuration
125
130
if (Subtarget->hasSIMD128 ()) {
126
131
// Hoist bitcasts out of shuffles
@@ -134,6 +139,9 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
134
139
setTargetDAGCombine (ISD::SINT_TO_FP);
135
140
setTargetDAGCombine (ISD::UINT_TO_FP);
136
141
142
+ // Combine concat of {s,u}int_to_fp_sat to i32x4.trunc_sat_f64x2_zero_{s,u}
143
+ setTargetDAGCombine (ISD::CONCAT_VECTORS);
144
+
137
145
// Support saturating add for i8x16 and i16x8
138
146
for (auto Op : {ISD::SADDSAT, ISD::UADDSAT})
139
147
for (auto T : {MVT::v16i8, MVT::v8i16})
@@ -198,6 +206,10 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
198
206
{ISD::SINT_TO_FP, ISD::UINT_TO_FP, ISD::FP_TO_SINT, ISD::FP_TO_UINT})
199
207
for (auto T : {MVT::v2i64, MVT::v2f64})
200
208
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);
201
213
}
202
214
203
215
// As a special case, these operators use the type to mean the type to
@@ -1233,6 +1245,9 @@ SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
1233
1245
case ISD::SRA:
1234
1246
case ISD::SRL:
1235
1247
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);
1236
1251
}
1237
1252
}
1238
1253
@@ -1949,6 +1964,21 @@ SDValue WebAssemblyTargetLowering::LowerShift(SDValue Op,
1949
1964
return DAG.getNode (Opcode, DL, Op.getValueType (), Op.getOperand (0 ), ShiftVal);
1950
1965
}
1951
1966
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
+
1952
1982
// ===----------------------------------------------------------------------===//
1953
1983
// Custom DAG combine hooks
1954
1984
// ===----------------------------------------------------------------------===//
@@ -2037,6 +2067,8 @@ performVectorConvertLowCombine(SDNode *N,
2037
2067
if (Extract.getOpcode () != ISD::EXTRACT_SUBVECTOR)
2038
2068
return SDValue ();
2039
2069
auto Source = Extract.getOperand (0 );
2070
+ if (Source.getValueType () != MVT::v4i32)
2071
+ return SDValue ();
2040
2072
auto *IndexNode = dyn_cast<ConstantSDNode>(Extract.getOperand (1 ));
2041
2073
if (IndexNode == nullptr )
2042
2074
return SDValue ();
@@ -2058,6 +2090,49 @@ performVectorConvertLowCombine(SDNode *N,
2058
2090
return DAG.getNode (Op, SDLoc (N), ResVT, Source);
2059
2091
}
2060
2092
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
+
2061
2136
SDValue
2062
2137
WebAssemblyTargetLowering::PerformDAGCombine (SDNode *N,
2063
2138
DAGCombinerInfo &DCI) const {
@@ -2072,5 +2147,7 @@ WebAssemblyTargetLowering::PerformDAGCombine(SDNode *N,
2072
2147
case ISD::SINT_TO_FP:
2073
2148
case ISD::UINT_TO_FP:
2074
2149
return performVectorConvertLowCombine (N, DCI);
2150
+ case ISD::CONCAT_VECTORS:
2151
+ return performVectorTruncSatLowCombine (N, DCI);
2075
2152
}
2076
2153
}
0 commit comments