Index: llvm/include/llvm/CodeGen/SelectionDAG.h =================================================================== --- llvm/include/llvm/CodeGen/SelectionDAG.h +++ llvm/include/llvm/CodeGen/SelectionDAG.h @@ -2029,6 +2029,24 @@ OFK_Always, }; + /// Determine if the result of the signed mul of 2 nodes can overflow. + OverflowKind computeOverflowForSignedMul(SDValue N0, SDValue N1) const; + + /// Determine if the result of the unsigned mul of 2 nodes can overflow. + OverflowKind computeOverflowForUnsignedMul(SDValue N0, SDValue N1) const; + + /// Determine if the result of the mul of 2 nodes can overflow. + OverflowKind computeOverflowForMul(bool IsSigned, SDValue N0, + SDValue N1) const { + return IsSigned ? computeOverflowForSignedMul(N0, N1) + : computeOverflowForUnsignedMul(N0, N1); + } + + /// Determine if the result of the mul of 2 nodes can never overflow. + bool willNotOverflowMul(bool IsSigned, SDValue N0, SDValue N1) const { + return computeOverflowForMul(IsSigned, N0, N1) == OFK_Never; + } + /// Determine if the result of the signed addition of 2 nodes can overflow. OverflowKind computeOverflowForSignedAdd(SDValue N0, SDValue N1) const; Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -4036,6 +4036,43 @@ llvm_unreachable("Unknown OverflowResult"); } +SelectionDAG::OverflowKind +SelectionDAG::computeOverflowForUnsignedMul(SDValue N0, SDValue N1) const { + // X * 0 and X * 1 never overflow. + if (isNullConstant(N1) || isOneConstant(N1)) + return OFK_Never; + KnownBits N0Known = computeKnownBits(N0); + KnownBits N1Known = computeKnownBits(N1); + ConstantRange N0Range = ConstantRange::fromKnownBits(N0Known, false); + ConstantRange N1Range = ConstantRange::fromKnownBits(N1Known, false); + return mapOverflowResult(N0Range.unsignedMulMayOverflow(N1Range)); +} + +SelectionDAG::OverflowKind +SelectionDAG::computeOverflowForSignedMul(SDValue N0, SDValue N1) const { + // X * 0 and X * 1 never overflow. + if (isNullConstant(N1) || isOneConstant(N1)) + return OFK_Never; + // Get the size of the result. + unsigned BitWidth = N0.getScalarValueSizeInBits(); + // Sum of the leading zeros. + unsigned SignBits = ComputeNumSignBits(N0) + ComputeNumSignBits(N1); + // If we have enough leading zeros, then there's no overflow. + if (SignBits > BitWidth + 1) + return OFK_Never; + if (SignBits == BitWidth + 1) { + // The overflow occurs when the true multiplication of the + // the operands is the minimum negative number. + KnownBits N0Known = computeKnownBits(N0); + KnownBits N1Known = computeKnownBits(N1); + // If one of the operands is non-negative, then there's no + // overflow. + if (N0Known.isNonNegative() || N1Known.isNonNegative()) + return OFK_Never; + } + return OFK_Sometime; +} + SelectionDAG::OverflowKind SelectionDAG::computeOverflowForSignedAdd(SDValue N0, SDValue N1) const { // X + 0 never overflow