[llvm] [X86] Resolve FIXME: Accept live flag if no overflow occurs. (PR #86836)

via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 27 10:16:40 PDT 2024


https://github.com/AtariDreams updated https://github.com/llvm/llvm-project/pull/86836

>From 8e314754ae1442bd8a3c40342232cdf76cb9d521 Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Wed, 27 Mar 2024 13:10:24 -0400
Subject: [PATCH] [X86] Resolve FIXME: Accept live flag if no overflow occurs.

---
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp |  8 ++-
 llvm/lib/Target/X86/X86ISelLowering.cpp       | 50 ++++++++++++++-----
 2 files changed, 43 insertions(+), 15 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index e8d1ac1d3a9167..5f0cc76d260184 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -4129,8 +4129,12 @@ 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;
+  // Fallback to ConstantRange::signedAddMayOverflow handling.
+  KnownBits N0Known = computeKnownBits(N0);
+  KnownBits N1Known = computeKnownBits(N1);
+  ConstantRange N0Range = ConstantRange::fromKnownBits(N0Known, true);
+  ConstantRange N1Range = ConstantRange::fromKnownBits(N1Known, true);
+  return mapOverflowResult(N0Range.signedAddMayOverflow(N1Range));
 }
 
 SelectionDAG::OverflowKind
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 9d98d31b31df0b..26e450607efbe1 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -54522,14 +54522,27 @@ static SDValue combineADC(SDNode *N, SelectionDAG &DAG,
   }
 
   // Fold ADC(C1,C2,Carry) -> ADC(0,C1+C2,Carry)
-  // iff the flag result is dead.
-  // TODO: Allow flag result if C1+C2 doesn't signed/unsigned overflow.
-  if (LHSC && RHSC && !LHSC->isZero() && !N->hasAnyUseOfValue(1)) {
-    SDLoc DL(N);
-    APInt Sum = LHSC->getAPIntValue() + RHSC->getAPIntValue();
-    return DAG.getNode(X86ISD::ADC, DL, N->getVTList(),
-                       DAG.getConstant(0, DL, LHS.getValueType()),
-                       DAG.getConstant(Sum, DL, LHS.getValueType()), CarryIn);
+  // if the flag result is dead, or if C1+C2 doesn't signed/unsigned overflow.
+  if (LHSC && RHSC && !LHSC->isZero()) {
+    // Calculate the sum and check for overflow.
+    bool Overflow;
+
+    // Check for signed overflow first. Because it is more involved, let sadd_ov
+    // do the work
+    APInt Sum = LHSC->getAPIntValue().sadd_ov(RHSC->getAPIntValue(), Overflow);
+
+    // Manually check for unsigned overflow. Luckily, this is relatively easy:
+    // just check for wrap-around
+    Overflow |= Sum.ult(RHSC->getAPIntValue());
+
+    // Only apply the optimization if there is no overflow or the flag result is
+    // not used.
+    if (!Overflow || !N->hasAnyUseOfValue(1)) {
+      SDLoc DL(N);
+      return DAG.getNode(X86ISD::ADC, DL, N->getVTList(),
+                         DAG.getConstant(0, DL, LHS.getValueType()),
+                         DAG.getConstant(Sum, DL, LHS.getValueType()), CarryIn);
+    }
   }
 
   if (SDValue Flags = combineCarryThroughADD(CarryIn, DAG)) {
@@ -54539,11 +54552,22 @@ static SDValue combineADC(SDNode *N, SelectionDAG &DAG,
   }
 
   // Fold ADC(ADD(X,Y),0,Carry) -> ADC(X,Y,Carry)
-  // iff the flag result is dead.
-  if (LHS.getOpcode() == ISD::ADD && RHSC && RHSC->isZero() &&
-      !N->hasAnyUseOfValue(1))
-    return DAG.getNode(X86ISD::ADC, SDLoc(N), N->getVTList(), LHS.getOperand(0),
-                       LHS.getOperand(1), CarryIn);
+  // iff the flag result is dead or known to be 0 anyway.
+
+  if (LHS.getOpcode() == ISD::ADD && RHSC && RHSC->isZero()) {
+    SelectionDAG::OverflowKind UnsignedOverflow =
+        DAG.computeOverflowForUnsignedAdd(LHS.getOperand(0), LHS.getOperand(1));
+    SelectionDAG::OverflowKind SignedOverflow =
+        DAG.computeOverflowForSignedAdd(LHS.getOperand(0), LHS.getOperand(1));
+    if (!N->hasAnyUseOfValue(1) || (DAG.computeOverflowForSignedAdd(
+                                        LHS.getOperand(0), LHS.getOperand(1)) ==
+                                        SelectionDAG::OverflowKind::OFK_Never &&
+                                    DAG.computeOverflowForUnsignedAdd(
+                                        LHS.getOperand(0), LHS.getOperand(1)) ==
+                                        SelectionDAG::OverflowKind::OFK_Never))
+      return DAG.getNode(X86ISD::ADC, SDLoc(N), N->getVTList(),
+                         LHS.getOperand(0), LHS.getOperand(1), CarryIn);
+  }
 
   return SDValue();
 }



More information about the llvm-commits mailing list