@@ -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+
20652140SDValue
20662141WebAssemblyTargetLowering::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}
0 commit comments