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