@@ -358,7 +358,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
358358 setOperationAction(
359359 {ISD::SADDSAT, ISD::SSUBSAT, ISD::UADDSAT, ISD::USUBSAT}, MVT::i32,
360360 Custom);
361- setOperationAction(ISD::SADDO, MVT::i32, Custom);
361+ setOperationAction({ ISD::SADDO, ISD::SSUBO} , MVT::i32, Custom);
362362 }
363363 if (!Subtarget.hasStdExtZmmul()) {
364364 setOperationAction({ISD::MUL, ISD::MULHS, ISD::MULHU}, XLenVT, Expand);
@@ -15060,35 +15060,42 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
1506015060 Results.push_back(customLegalizeToWOp(N, DAG, ExtOpc));
1506115061 break;
1506215062 }
15063- case ISD::SADDO: {
15063+ case ISD::SADDO:
15064+ case ISD::SSUBO: {
1506415065 assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
1506515066 "Unexpected custom legalisation");
1506615067
15067- // If the RHS is a constant, we can simplify ConditionRHS below. Otherwise
15068- // use the default legalization.
15069- if (!isa<ConstantSDNode>(N->getOperand(1)))
15070- return;
15071-
15068+ // This is similar to the default legalization, but we return the
15069+ // sext_inreg instead of the add/sub.
15070+ bool IsAdd = N->getOpcode() == ISD::SADDO;
1507215071 SDValue LHS = DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i64, N->getOperand(0));
1507315072 SDValue RHS = DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i64, N->getOperand(1));
15074- SDValue Res = DAG.getNode(ISD::ADD, DL, MVT::i64, LHS, RHS);
15075- Res = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i64, Res,
15076- DAG.getValueType(MVT::i32));
15073+ SDValue Op =
15074+ DAG.getNode(IsAdd ? ISD::ADD : ISD::SUB, DL, MVT::i64, LHS, RHS);
15075+ SDValue Res = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i64, Op,
15076+ DAG.getValueType(MVT::i32));
1507715077
15078- SDValue Zero = DAG.getConstant(0, DL, MVT::i64) ;
15078+ SDValue Overflow ;
1507915079
15080- // For an addition, the result should be less than one of the operands (LHS)
15081- // if and only if the other operand (RHS) is negative, otherwise there will
15082- // be overflow.
15083- // For a subtraction, the result should be less than one of the operands
15084- // (LHS) if and only if the other operand (RHS) is (non-zero) positive,
15085- // otherwise there will be overflow.
15086- EVT OType = N->getValueType(1);
15087- SDValue ResultLowerThanLHS = DAG.getSetCC(DL, OType, Res, LHS, ISD::SETLT);
15088- SDValue ConditionRHS = DAG.getSetCC(DL, OType, RHS, Zero, ISD::SETLT);
15080+ // If the RHS is a constant, we can simplify ConditionRHS below. Otherwise
15081+ // use the default legalization.
15082+ if (IsAdd && isa<ConstantSDNode>(N->getOperand(1))) {
15083+ SDValue Zero = DAG.getConstant(0, DL, MVT::i64);
15084+
15085+ // For an addition, the result should be less than one of the operands
15086+ // (LHS) if and only if the other operand (RHS) is negative, otherwise
15087+ // there will be overflow.
15088+ EVT OType = N->getValueType(1);
15089+ SDValue ResultLowerThanLHS =
15090+ DAG.getSetCC(DL, OType, Res, LHS, ISD::SETLT);
15091+ SDValue ConditionRHS = DAG.getSetCC(DL, OType, RHS, Zero, ISD::SETLT);
15092+
15093+ Overflow =
15094+ DAG.getNode(ISD::XOR, DL, OType, ConditionRHS, ResultLowerThanLHS);
15095+ } else {
15096+ Overflow = DAG.getSetCC(DL, N->getValueType(1), Res, Op, ISD::SETNE);
15097+ }
1508915098
15090- SDValue Overflow =
15091- DAG.getNode(ISD::XOR, DL, OType, ConditionRHS, ResultLowerThanLHS);
1509215099 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Res));
1509315100 Results.push_back(Overflow);
1509415101 return;
0 commit comments