[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