[llvm] [DAG] canCreateUndefOrPoison - add handling for ADD/SUB overflow nodes (PR #146322)

Simon Pilgrim via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 30 03:28:42 PDT 2025


https://github.com/RKSimon updated https://github.com/llvm/llvm-project/pull/146322

>From 1b14a2c837a7c0594a790e9a2917fb0ecc11abf8 Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Mon, 30 Jun 2025 10:43:23 +0100
Subject: [PATCH 1/2] [DAG] canCreateUndefOrPoison - add handling for ADD/SUB
 overflow nodes

Neither the arithmetic value or overflow result can create undef/poison from regular operands values.

We have complete test coverage for all ADDO/SUBO nodes, 32-bit codegen handles the _CARRY variants but until #145939 lands AND DAGCombiner::visitFREEZE handles multiple results we can't see any codegen change.

The SMULO/UMULO nodes can be added as well, but I'm struggling to create any test coverage for them.

Pulled out of #145939
---
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 16 ++++++++++++++
 llvm/test/CodeGen/X86/freeze-binary.ll        | 22 +++++--------------
 2 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index fe9a6ea3e77e6..699da5286d13f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -5557,6 +5557,22 @@ bool SelectionDAG::canCreateUndefOrPoison(SDValue Op, const APInt &DemandedElts,
   case ISD::SPLAT_VECTOR:
     return false;
 
+  case ISD::ADDC:
+  case ISD::SUBC:
+  case ISD::ADDE:
+  case ISD::SUBE:
+  case ISD::SADDO:
+  case ISD::SSUBO:
+  case ISD::SADDO_CARRY:
+  case ISD::SSUBO_CARRY:
+  case ISD::UADDO:
+  case ISD::USUBO:
+  case ISD::UADDO_CARRY:
+  case ISD::USUBO_CARRY:
+    // No poison on result or overflow flags.
+    // TODO: Add SMULO/UMULO with test coverage.
+    return false;
+
   case ISD::SELECT_CC:
   case ISD::SETCC: {
     // Integer setcc cannot create undef or poison.
diff --git a/llvm/test/CodeGen/X86/freeze-binary.ll b/llvm/test/CodeGen/X86/freeze-binary.ll
index 4b25fd8a536b2..189de051011d2 100644
--- a/llvm/test/CodeGen/X86/freeze-binary.ll
+++ b/llvm/test/CodeGen/X86/freeze-binary.ll
@@ -814,11 +814,9 @@ define i32 @freeze_saddo(i32 %a0, i32 %a1, i8 %a2, i8 %a3) nounwind {
 ;
 ; X64-LABEL: freeze_saddo:
 ; X64:       # %bb.0:
-; X64-NEXT:    # kill: def $esi killed $esi def $rsi
-; X64-NEXT:    # kill: def $edi killed $edi def $rdi
+; X64-NEXT:    movl %edi, %eax
 ; X64-NEXT:    addb %cl, %dl
-; X64-NEXT:    adcl $0, %edi
-; X64-NEXT:    leal (%rdi,%rsi), %eax
+; X64-NEXT:    adcl %esi, %eax
 ; X64-NEXT:    retq
   %b = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 %a2, i8 %a3)
   %b.o = extractvalue {i8, i1} %b, 1
@@ -844,11 +842,9 @@ define i32 @freeze_uaddo(i32 %a0, i32 %a1, i8 %a2, i8 %a3) nounwind {
 ;
 ; X64-LABEL: freeze_uaddo:
 ; X64:       # %bb.0:
-; X64-NEXT:    # kill: def $esi killed $esi def $rsi
-; X64-NEXT:    # kill: def $edi killed $edi def $rdi
+; X64-NEXT:    movl %edi, %eax
 ; X64-NEXT:    addb %cl, %dl
-; X64-NEXT:    adcl $0, %edi
-; X64-NEXT:    leal (%rdi,%rsi), %eax
+; X64-NEXT:    adcl %esi, %eax
 ; X64-NEXT:    retq
   %b = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 %a2, i8 %a3)
   %b.o = extractvalue {i8, i1} %b, 1
@@ -878,11 +874,8 @@ define i32 @freeze_ssubo(i32 %a0, i32 %a1, i8 %a2, i8 %a3) nounwind {
 ; X64-LABEL: freeze_ssubo:
 ; X64:       # %bb.0:
 ; X64-NEXT:    movl %edi, %eax
-; X64-NEXT:    xorl %edi, %edi
 ; X64-NEXT:    addb %cl, %dl
-; X64-NEXT:    setb %dil
-; X64-NEXT:    andl $1, %edi
-; X64-NEXT:    subl %edi, %eax
+; X64-NEXT:    sbbl $0, %eax
 ; X64-NEXT:    subl %esi, %eax
 ; X64-NEXT:    retq
   %b = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 %a2, i8 %a3)
@@ -913,11 +906,8 @@ define i32 @freeze_usubo(i32 %a0, i32 %a1, i8 %a2, i8 %a3) nounwind {
 ; X64-LABEL: freeze_usubo:
 ; X64:       # %bb.0:
 ; X64-NEXT:    movl %edi, %eax
-; X64-NEXT:    xorl %edi, %edi
 ; X64-NEXT:    addb %cl, %dl
-; X64-NEXT:    setb %dil
-; X64-NEXT:    andl $1, %edi
-; X64-NEXT:    subl %edi, %eax
+; X64-NEXT:    sbbl $0, %eax
 ; X64-NEXT:    subl %esi, %eax
 ; X64-NEXT:    retq
   %b = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 %a2, i8 %a3)

>From c9ef1417d5cb382d8e2a119784e2561e75d9e1cb Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Mon, 30 Jun 2025 11:28:25 +0100
Subject: [PATCH 2/2] Add SMULO/UMULO handling

---
 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 699da5286d13f..93cfe6f02bc84 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -5563,14 +5563,15 @@ bool SelectionDAG::canCreateUndefOrPoison(SDValue Op, const APInt &DemandedElts,
   case ISD::SUBE:
   case ISD::SADDO:
   case ISD::SSUBO:
+  case ISD::SMULO:
   case ISD::SADDO_CARRY:
   case ISD::SSUBO_CARRY:
   case ISD::UADDO:
   case ISD::USUBO:
+  case ISD::UMULO:
   case ISD::UADDO_CARRY:
   case ISD::USUBO_CARRY:
     // No poison on result or overflow flags.
-    // TODO: Add SMULO/UMULO with test coverage.
     return false;
 
   case ISD::SELECT_CC:



More information about the llvm-commits mailing list