[llvm] 7395f6a - [DAG] Add computeOverflowForSignedAdd and computeOverflowForAdd wrapper
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Sat May 6 05:33:25 PDT 2023
Author: Simon Pilgrim
Date: 2023-05-06T13:33:14+01:00
New Revision: 7395f6ae784aada24e490b773b2571f08cf39f37
URL: https://github.com/llvm/llvm-project/commit/7395f6ae784aada24e490b773b2571f08cf39f37
DIFF: https://github.com/llvm/llvm-project/commit/7395f6ae784aada24e490b773b2571f08cf39f37.diff
LOG: [DAG] Add computeOverflowForSignedAdd and computeOverflowForAdd wrapper
Add basic computeOverflowForSignedAdd helper to recognise that sadd overflow can't occur if both operands have more that one sign bit.
Add computeOverflowForAdd wrapper that calls computeOverflowForSignedAdd/computeOverflowForUnsignedAdd depending on the IsSigned argument, and use this in DAGCombiner::visitADDO
Added:
Modified:
llvm/include/llvm/CodeGen/SelectionDAG.h
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
llvm/test/CodeGen/X86/xaluo.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index 233af5154a1fe..e6da69479059f 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -1984,9 +1984,19 @@ class SelectionDAG {
OFK_Always,
};
- /// Determine if the result of the unsigned addition of 2 node can overflow.
+ /// Determine if the result of the signed addition of 2 nodes can overflow.
+ OverflowKind computeOverflowForSignedAdd(SDValue N0, SDValue N1) const;
+
+ /// Determine if the result of the unsigned addition of 2 nodes can overflow.
OverflowKind computeOverflowForUnsignedAdd(SDValue N0, SDValue N1) const;
+ /// Determine if the result of the addition of 2 nodes can overflow.
+ OverflowKind computeOverflowForAdd(bool IsSigned, SDValue N0,
+ SDValue N1) const {
+ return IsSigned ? computeOverflowForSignedAdd(N0, N1)
+ : computeOverflowForUnsignedAdd(N0, N1);
+ }
+
/// Test if the given value is known to have exactly one bit set. This
diff ers
/// from computeKnownBits in that it doesn't necessarily determine which bit
/// is set.
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index c8140aff50da5..a98bcbe63468c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -3212,12 +3212,12 @@ SDValue DAGCombiner::visitADDO(SDNode *N) {
if (isNullOrNullSplat(N1))
return CombineTo(N, N0, DAG.getConstant(0, DL, CarryVT));
- if (!IsSigned) {
- // If it cannot overflow, transform into an add.
- if (DAG.computeOverflowForUnsignedAdd(N0, N1) == SelectionDAG::OFK_Never)
- return CombineTo(N, DAG.getNode(ISD::ADD, DL, VT, N0, N1),
- DAG.getConstant(0, DL, CarryVT));
+ // If it cannot overflow, transform into an add.
+ if (DAG.computeOverflowForAdd(IsSigned, N0, N1) == SelectionDAG::OFK_Never)
+ return CombineTo(N, DAG.getNode(ISD::ADD, DL, VT, N0, N1),
+ DAG.getConstant(0, DL, CarryVT));
+ if (!IsSigned) {
// fold (uaddo (xor a, -1), 1) -> (usub 0, a) and flip carry.
if (isBitwiseNot(N0) && isOneOrOneSplat(N1)) {
SDValue Sub = DAG.getNode(ISD::USUBO, DL, N->getVTList(),
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 33defdc9dde5f..c05ea0b9a5c18 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -3943,6 +3943,20 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts,
return Known;
}
+SelectionDAG::OverflowKind
+SelectionDAG::computeOverflowForSignedAdd(SDValue N0, SDValue N1) const {
+ // X + 0 never overflow
+ if (isNullConstant(N1))
+ return OFK_Never;
+
+ // If bother operands each have at least two sign bits, the addition
+ // cannot overflow.
+ if (ComputeNumSignBits(N0) > 1 && ComputeNumSignBits(N1) > 1)
+ return OFK_Never;
+
+ return OFK_Sometime;
+}
+
SelectionDAG::OverflowKind
SelectionDAG::computeOverflowForUnsignedAdd(SDValue N0, SDValue N1) const {
// X + 0 never overflow
diff --git a/llvm/test/CodeGen/X86/xaluo.ll b/llvm/test/CodeGen/X86/xaluo.ll
index 55cdc40754831..508f065fb8210 100644
--- a/llvm/test/CodeGen/X86/xaluo.ll
+++ b/llvm/test/CodeGen/X86/xaluo.ll
@@ -964,15 +964,13 @@ continue:
ret i1 true
}
-; FIXME: Failure to recognise add can't overflow
define {i64, i1} @saddoovf(i64 %a, i64 %b) {
; CHECK-LABEL: saddoovf:
; CHECK: ## %bb.0:
-; CHECK-NEXT: movq %rsi, %rax
; CHECK-NEXT: sarq $17, %rdi
-; CHECK-NEXT: shrq $31, %rax
-; CHECK-NEXT: addq %rdi, %rax
-; CHECK-NEXT: seto %dl
+; CHECK-NEXT: shrq $31, %rsi
+; CHECK-NEXT: leaq (%rsi,%rdi), %rax
+; CHECK-NEXT: xorl %edx, %edx
; CHECK-NEXT: retq
%1 = ashr i64 %a, 17
%2 = lshr i64 %b, 31
More information about the llvm-commits
mailing list