[DAG] Add computeOverflowForSignedSub/computeOverflowForUnsignedSub/computeOverflowForSub

Match the addition variants (although computeOverflowForUnsignedSub is really just a placeholder), and use this in DAGCombiner::visitSUBO
This commit is contained in:
Simon Pilgrim
2023-05-06 15:25:40 +01:00
parent 3551e0f345
commit 08c1150d4c
4 changed files with 46 additions and 2 deletions

View File

@@ -1997,6 +1997,19 @@ public:
: computeOverflowForUnsignedAdd(N0, N1);
}
/// Determine if the result of the signed sub of 2 nodes can overflow.
OverflowKind computeOverflowForSignedSub(SDValue N0, SDValue N1) const;
/// Determine if the result of the unsigned sub of 2 nodes can overflow.
OverflowKind computeOverflowForUnsignedSub(SDValue N0, SDValue N1) const;
/// Determine if the result of the sub of 2 nodes can overflow.
OverflowKind computeOverflowForSub(bool IsSigned, SDValue N0,
SDValue N1) const {
return IsSigned ? computeOverflowForSignedSub(N0, N1)
: computeOverflowForUnsignedSub(N0, N1);
}
/// Test if the given value is known to have exactly one bit set. This differs
/// from computeKnownBits in that it doesn't necessarily determine which bit
/// is set.

View File

@@ -4135,6 +4135,11 @@ SDValue DAGCombiner::visitSUBO(SDNode *N) {
if (isNullOrNullSplat(N1))
return CombineTo(N, N0, DAG.getConstant(0, DL, CarryVT));
// If it cannot overflow, transform into an sub.
if (DAG.computeOverflowForSub(IsSigned, N0, N1) == SelectionDAG::OFK_Never)
return CombineTo(N, DAG.getNode(ISD::SUB, DL, VT, N0, N1),
DAG.getConstant(0, DL, CarryVT));
// Canonicalize (usubo -1, x) -> ~x, i.e. (xor x, -1) + no borrow
if (!IsSigned && isAllOnesOrAllOnesSplat(N0))
return CombineTo(N, DAG.getNode(ISD::XOR, DL, VT, N1, N0),

View File

@@ -3954,6 +3954,7 @@ SelectionDAG::computeOverflowForSignedAdd(SDValue N0, SDValue N1) const {
if (ComputeNumSignBits(N0) > 1 && ComputeNumSignBits(N1) > 1)
return OFK_Never;
// TODO: Add ConstantRange::signedAddMayOverflow handling.
return OFK_Sometime;
}
@@ -3985,6 +3986,32 @@ SelectionDAG::computeOverflowForUnsignedAdd(SDValue N0, SDValue N1) const {
return OFK_Never;
}
// TODO: Add ConstantRange::unsignedAddMayOverflow handling.
return OFK_Sometime;
}
SelectionDAG::OverflowKind
SelectionDAG::computeOverflowForSignedSub(SDValue N0, SDValue N1) const {
// X - 0 never overflow
if (isNullConstant(N1))
return OFK_Never;
// If both operands each have at least two sign bits, the subtraction
// cannot overflow.
if (ComputeNumSignBits(N0) > 1 && ComputeNumSignBits(N1) > 1)
return OFK_Never;
// TODO: Add ConstantRange::signedSubMayOverflow handling.
return OFK_Sometime;
}
SelectionDAG::OverflowKind
SelectionDAG::computeOverflowForUnsignedSub(SDValue N0, SDValue N1) const {
// X - 0 never overflow
if (isNullConstant(N1))
return OFK_Never;
// TODO: Add ConstantRange::unsignedSubMayOverflow handling.
return OFK_Sometime;
}

View File

@@ -978,14 +978,13 @@ define {i64, i1} @saddoovf(i64 %a, i64 %b) {
ret {i64, i1} %t
}
; FIXME: Failure to recognise sub can't overflow
define {i64, i1} @ssuboovf(i64 %a, i64 %b) {
; CHECK-LABEL: ssuboovf:
; CHECK: ## %bb.0:
; CHECK-NEXT: movzwl %di, %eax
; CHECK-NEXT: shrq $22, %rsi
; CHECK-NEXT: subq %rsi, %rax
; CHECK-NEXT: seto %dl
; CHECK-NEXT: xorl %edx, %edx
; CHECK-NEXT: retq
%1 = and i64 %a, 65535
%2 = lshr i64 %b, 22