mirror of
https://github.com/intel/llvm.git
synced 2026-01-18 07:57:36 +08:00
[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:
@@ -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.
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user