@@ -199,6 +199,13 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
199
199
200
200
if (Subtarget.is64Bit () && Subtarget.hasStdExtM ()) {
201
201
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);
202
209
setOperationAction (ISD::SDIV, MVT::i32 , Custom);
203
210
setOperationAction (ISD::UDIV, MVT::i32 , Custom);
204
211
setOperationAction (ISD::UREM, MVT::i32 , Custom);
@@ -1436,11 +1443,12 @@ static RISCVISD::NodeType getRISCVWOpcode(unsigned Opcode) {
1436
1443
// be promoted to i64, making it difficult to select the SLLW/DIVUW/.../*W
1437
1444
// later one because the fact the operation was originally of type i32 is
1438
1445
// lost.
1439
- static SDValue customLegalizeToWOp (SDNode *N, SelectionDAG &DAG) {
1446
+ static SDValue customLegalizeToWOp (SDNode *N, SelectionDAG &DAG,
1447
+ unsigned ExtOpc = ISD::ANY_EXTEND) {
1440
1448
SDLoc DL (N);
1441
1449
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 ));
1444
1452
SDValue NewRes = DAG.getNode (WOpcode, DL, MVT::i64 , NewOp0, NewOp1);
1445
1453
// ReplaceNodeResults requires we maintain the same type for the return value.
1446
1454
return DAG.getNode (ISD::TRUNCATE, DL, MVT::i32 , NewRes);
@@ -1537,14 +1545,26 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
1537
1545
break ;
1538
1546
case ISD::SDIV:
1539
1547
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" );
1543
1553
if (N->getOperand (0 ).getOpcode () == ISD::Constant ||
1544
1554
N->getOperand (1 ).getOpcode () == ISD::Constant)
1545
1555
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));
1547
1566
break ;
1567
+ }
1548
1568
case ISD::BITCAST: {
1549
1569
assert (((N->getValueType (0 ) == MVT::i32 && Subtarget.is64Bit () &&
1550
1570
Subtarget.hasStdExtF ()) ||
@@ -2147,6 +2167,7 @@ void RISCVTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
2147
2167
const APInt &DemandedElts,
2148
2168
const SelectionDAG &DAG,
2149
2169
unsigned Depth) const {
2170
+ unsigned BitWidth = Known.getBitWidth ();
2150
2171
unsigned Opc = Op.getOpcode ();
2151
2172
assert ((Opc >= ISD::BUILTIN_OP_END ||
2152
2173
Opc == ISD::INTRINSIC_WO_CHAIN ||
@@ -2158,6 +2179,26 @@ void RISCVTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
2158
2179
Known.resetAll ();
2159
2180
switch (Opc) {
2160
2181
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
+ }
2161
2202
case RISCVISD::READ_VLENB:
2162
2203
// We assume VLENB is at least 8 bytes.
2163
2204
// FIXME: The 1.0 draft spec defines minimum VLEN as 128 bits.
0 commit comments