@@ -199,6 +199,13 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
199199
200200 if (Subtarget.is64Bit () && Subtarget.hasStdExtM ()) {
201201 setOperationAction (ISD::MUL, MVT::i32 , Custom);
202+
203+ setOperationAction (ISD::SDIV, MVT::i8 , Custom);
204+ setOperationAction (ISD::UDIV, MVT::i8 , Custom);
205+ setOperationAction (ISD::UREM, MVT::i8 , Custom);
206+ setOperationAction (ISD::SDIV, MVT::i16 , Custom);
207+ setOperationAction (ISD::UDIV, MVT::i16 , Custom);
208+ setOperationAction (ISD::UREM, MVT::i16 , Custom);
202209 setOperationAction (ISD::SDIV, MVT::i32 , Custom);
203210 setOperationAction (ISD::UDIV, MVT::i32 , Custom);
204211 setOperationAction (ISD::UREM, MVT::i32 , Custom);
@@ -1436,11 +1443,12 @@ static RISCVISD::NodeType getRISCVWOpcode(unsigned Opcode) {
14361443// be promoted to i64, making it difficult to select the SLLW/DIVUW/.../*W
14371444// later one because the fact the operation was originally of type i32 is
14381445// lost.
1439- static SDValue customLegalizeToWOp (SDNode *N, SelectionDAG &DAG) {
1446+ static SDValue customLegalizeToWOp (SDNode *N, SelectionDAG &DAG,
1447+ unsigned ExtOpc = ISD::ANY_EXTEND) {
14401448 SDLoc DL (N);
14411449 RISCVISD::NodeType WOpcode = getRISCVWOpcode (N->getOpcode ());
1442- SDValue NewOp0 = DAG.getNode (ISD::ANY_EXTEND , DL, MVT::i64 , N->getOperand (0 ));
1443- SDValue NewOp1 = DAG.getNode (ISD::ANY_EXTEND , DL, MVT::i64 , N->getOperand (1 ));
1450+ SDValue NewOp0 = DAG.getNode (ExtOpc , DL, MVT::i64 , N->getOperand (0 ));
1451+ SDValue NewOp1 = DAG.getNode (ExtOpc , DL, MVT::i64 , N->getOperand (1 ));
14441452 SDValue NewRes = DAG.getNode (WOpcode, DL, MVT::i64 , NewOp0, NewOp1);
14451453 // ReplaceNodeResults requires we maintain the same type for the return value.
14461454 return DAG.getNode (ISD::TRUNCATE, DL, MVT::i32 , NewRes);
@@ -1537,14 +1545,26 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
15371545 break ;
15381546 case ISD::SDIV:
15391547 case ISD::UDIV:
1540- case ISD::UREM:
1541- assert (N->getValueType (0 ) == MVT::i32 && Subtarget.is64Bit () &&
1542- Subtarget.hasStdExtM () && " Unexpected custom legalisation" );
1548+ case ISD::UREM: {
1549+ MVT VT = N->getSimpleValueType (0 );
1550+ assert ((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32 ) &&
1551+ Subtarget.is64Bit () && Subtarget.hasStdExtM () &&
1552+ " Unexpected custom legalisation" );
15431553 if (N->getOperand (0 ).getOpcode () == ISD::Constant ||
15441554 N->getOperand (1 ).getOpcode () == ISD::Constant)
15451555 return ;
1546- Results.push_back (customLegalizeToWOp (N, DAG));
1556+
1557+ // If the input is i32, use ANY_EXTEND since the W instructions don't read
1558+ // the upper 32 bits. For other types we need to sign or zero extend
1559+ // based on the opcode.
1560+ unsigned ExtOpc = ISD::ANY_EXTEND;
1561+ if (VT != MVT::i32 )
1562+ ExtOpc = N->getOpcode () == ISD::SDIV ? ISD::SIGN_EXTEND
1563+ : ISD::ZERO_EXTEND;
1564+
1565+ Results.push_back (customLegalizeToWOp (N, DAG, ExtOpc));
15471566 break ;
1567+ }
15481568 case ISD::BITCAST: {
15491569 assert (((N->getValueType (0 ) == MVT::i32 && Subtarget.is64Bit () &&
15501570 Subtarget.hasStdExtF ()) ||
@@ -2147,6 +2167,7 @@ void RISCVTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
21472167 const APInt &DemandedElts,
21482168 const SelectionDAG &DAG,
21492169 unsigned Depth) const {
2170+ unsigned BitWidth = Known.getBitWidth ();
21502171 unsigned Opc = Op.getOpcode ();
21512172 assert ((Opc >= ISD::BUILTIN_OP_END ||
21522173 Opc == ISD::INTRINSIC_WO_CHAIN ||
@@ -2158,6 +2179,26 @@ void RISCVTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
21582179 Known.resetAll ();
21592180 switch (Opc) {
21602181 default : break ;
2182+ case RISCVISD::REMUW: {
2183+ KnownBits Known2;
2184+ Known = DAG.computeKnownBits (Op.getOperand (0 ), DemandedElts, Depth + 1 );
2185+ Known2 = DAG.computeKnownBits (Op.getOperand (1 ), DemandedElts, Depth + 1 );
2186+ // We only care about the lower 32 bits.
2187+ Known = KnownBits::urem (Known.trunc (32 ), Known2.trunc (32 ));
2188+ // Restore the original width by sign extending.
2189+ Known = Known.sext (BitWidth);
2190+ break ;
2191+ }
2192+ case RISCVISD::DIVUW: {
2193+ KnownBits Known2;
2194+ Known = DAG.computeKnownBits (Op.getOperand (0 ), DemandedElts, Depth + 1 );
2195+ Known2 = DAG.computeKnownBits (Op.getOperand (1 ), DemandedElts, Depth + 1 );
2196+ // We only care about the lower 32 bits.
2197+ Known = KnownBits::udiv (Known.trunc (32 ), Known2.trunc (32 ));
2198+ // Restore the original width by sign extending.
2199+ Known = Known.sext (BitWidth);
2200+ break ;
2201+ }
21612202 case RISCVISD::READ_VLENB:
21622203 // We assume VLENB is at least 8 bytes.
21632204 // FIXME: The 1.0 draft spec defines minimum VLEN as 128 bits.
0 commit comments