[llvm] [X86] Optimized ADC + ADD to ADC (PR #176713)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 23 00:27:18 PST 2026


https://github.com/JaydeepChauhan14 updated https://github.com/llvm/llvm-project/pull/176713

>From 241a0004e1659757bd305219c5accd88429c79f2 Mon Sep 17 00:00:00 2001
From: Chauhan Jaydeep Ashwinbhai <chauhan.jaydeep.ashwinbhai at intel.com>
Date: Mon, 19 Jan 2026 01:18:15 -0800
Subject: [PATCH 1/2] [X86] Optimized ADC + ADD to ADC

---
 llvm/lib/Target/X86/X86ISelLowering.cpp |  8 ++-
 llvm/test/CodeGen/X86/combine-add.ll    | 96 +++++++++++++++++++++++++
 2 files changed, 102 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 640d9c5f5bc07..d0f59fb95eec0 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -58197,7 +58197,11 @@ static SDValue combineFunnelShift(SDNode *N, SelectionDAG &DAG,
 static bool needCarryOrOverflowFlag(SDValue Flags) {
   assert(Flags.getValueType() == MVT::i32 && "Unexpected VT!");
 
-  for (const SDNode *User : Flags->users()) {
+  for (const SDUse &Use : Flags->uses()) {
+    // Only check things that use the flags.
+    if (Use.getResNo() != Flags.getResNo())
+      continue;
+    const SDNode *User = Use.getUser();
     X86::CondCode CC;
     switch (User->getOpcode()) {
     default:
@@ -58541,7 +58545,7 @@ 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))
+      !needCarryOrOverflowFlag(SDValue(N, 1)))
     return DAG.getNode(X86ISD::ADC, SDLoc(N), N->getVTList(), LHS.getOperand(0),
                        LHS.getOperand(1), CarryIn);
 
diff --git a/llvm/test/CodeGen/X86/combine-add.ll b/llvm/test/CodeGen/X86/combine-add.ll
index 51a8bf5b48415..7bacb3c495b50 100644
--- a/llvm/test/CodeGen/X86/combine-add.ll
+++ b/llvm/test/CodeGen/X86/combine-add.ll
@@ -561,3 +561,99 @@ define i64 @add_notx_x(i64 %v0) nounwind {
   %y = add i64 %x, %v0
   ret i64 %y
 }
+
+; Basic positive test
+define i32 @add_adc(i32 %0, i32 %1, i32 %2) {
+; CHECK-LABEL: add_adc:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    cmpl %esi, %edi
+; CHECK-NEXT:    adcl %edi, %edx
+; CHECK-NEXT:    cmovsl %esi, %eax
+; CHECK-NEXT:    retq
+  %4 = icmp ult i32 %0, %1
+  %5 = zext i1 %4 to i32
+  %6 = add i32 %2, %0
+  %7 = add i32 %6, %5
+  %8 = icmp slt i32 %7, 0
+  %9 = select i1 %8, i32 %1, i32 %0
+  ret i32 %9
+}
+
+; Negative test: Carry or overflow flag is used
+define i32 @add_adc_wrong_flags(i32 %0, i32 %1, i32 %2, i32 %3) {
+; CHECK-LABEL: add_adc_wrong_flags:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    cmpl %esi, %edi
+; CHECK-NEXT:    adcl $0, %edx
+; CHECK-NEXT:    addl %ecx, %edx
+; CHECK-NEXT:    cmovbl %edi, %eax
+; CHECK-NEXT:    retq
+  %5 = icmp ult i32 %0, %1
+  %6 = zext i1 %5 to i32
+  %7 = add i32 %2, %6
+  %8 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %7, i32 %3)
+  %9 = extractvalue { i32, i1 } %8, 1
+  %10 = select i1 %9, i32 %0, i32 %1
+  ret i32 %10
+}
+
+; Negative test: Multi-use
+define i32 @add_adc_multi_use(i32 %0, i32 %1, i32 %2, i32 %3, ptr %4) {
+; CHECK-LABEL: add_adc_multi_use:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    cmpl %esi, %edi
+; CHECK-NEXT:    adcl $0, %edx
+; CHECK-NEXT:    movl %edx, (%r8)
+; CHECK-NEXT:    addl %ecx, %edx
+; CHECK-NEXT:    cmovsl %edi, %eax
+; CHECK-NEXT:    retq
+  %6 = icmp ult i32 %0, %1
+  %7 = zext i1 %6 to i32
+  %8 = add i32 %2, %7
+  store i32 %8, ptr %4, align 4
+  %9 = add i32 %8, %3
+  %10 = icmp slt i32 %9, 0
+  %11 = select i1 %10, i32 %0, i32 %1
+  ret i32 %11
+}
+
+; Positive test: Both adc operands are constants
+define i32 @add_adc_constants(i32 %0, i32 %1, i32 %2) {
+; CHECK-LABEL: add_adc_constants:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    cmpl %esi, %edi
+; CHECK-NEXT:    adcl $42, %eax
+; CHECK-NEXT:    addl %edx, %eax
+; CHECK-NEXT:    retq
+  %4 = icmp ult i32 %0, %1
+  %5 = zext i1 %4 to i8
+  %6 = tail call { i8, i32 } @llvm.x86.addcarry.32(i8 %5, i32 0, i32 42)
+  %7 = extractvalue { i8, i32 } %6, 1
+  %8 = add i32 %7, %2
+  ret i32 %8
+}
+
+; Negative test: Multi-use
+define i32 @add_adc_constants_multi_use(i32 %0, i32 %1, i32 %2, ptr %3) {
+; CHECK-LABEL: add_adc_constants_multi_use:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    xorl %esi, %esi
+; CHECK-NEXT:    cmpl %eax, %edi
+; CHECK-NEXT:    adcl $42, %esi
+; CHECK-NEXT:    movl %esi, (%rcx)
+; CHECK-NEXT:    addl %edx, %esi
+; CHECK-NEXT:    cmovsl %edi, %eax
+; CHECK-NEXT:    retq
+  %5 = icmp ult i32 %0, %1
+  %6 = select i1 %5, i32 43, i32 42
+  store i32 %6, ptr %3, align 4
+  %7 = add i32 %6, %2
+  %8 = icmp slt i32 %7, 0
+  %9 = select i1 %8, i32 %0, i32 %1
+  ret i32 %9
+}

>From f4a638b436fe7191be1d98fec7a3057fd790bcd3 Mon Sep 17 00:00:00 2001
From: Chauhan Jaydeep Ashwinbhai <chauhan.jaydeep.ashwinbhai at intel.com>
Date: Fri, 23 Jan 2026 00:27:04 -0800
Subject: [PATCH 2/2] Removed testcases

---
 llvm/test/CodeGen/X86/combine-add.ll | 96 ----------------------------
 1 file changed, 96 deletions(-)

diff --git a/llvm/test/CodeGen/X86/combine-add.ll b/llvm/test/CodeGen/X86/combine-add.ll
index 7bacb3c495b50..51a8bf5b48415 100644
--- a/llvm/test/CodeGen/X86/combine-add.ll
+++ b/llvm/test/CodeGen/X86/combine-add.ll
@@ -561,99 +561,3 @@ define i64 @add_notx_x(i64 %v0) nounwind {
   %y = add i64 %x, %v0
   ret i64 %y
 }
-
-; Basic positive test
-define i32 @add_adc(i32 %0, i32 %1, i32 %2) {
-; CHECK-LABEL: add_adc:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    movl %edi, %eax
-; CHECK-NEXT:    cmpl %esi, %edi
-; CHECK-NEXT:    adcl %edi, %edx
-; CHECK-NEXT:    cmovsl %esi, %eax
-; CHECK-NEXT:    retq
-  %4 = icmp ult i32 %0, %1
-  %5 = zext i1 %4 to i32
-  %6 = add i32 %2, %0
-  %7 = add i32 %6, %5
-  %8 = icmp slt i32 %7, 0
-  %9 = select i1 %8, i32 %1, i32 %0
-  ret i32 %9
-}
-
-; Negative test: Carry or overflow flag is used
-define i32 @add_adc_wrong_flags(i32 %0, i32 %1, i32 %2, i32 %3) {
-; CHECK-LABEL: add_adc_wrong_flags:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    movl %esi, %eax
-; CHECK-NEXT:    cmpl %esi, %edi
-; CHECK-NEXT:    adcl $0, %edx
-; CHECK-NEXT:    addl %ecx, %edx
-; CHECK-NEXT:    cmovbl %edi, %eax
-; CHECK-NEXT:    retq
-  %5 = icmp ult i32 %0, %1
-  %6 = zext i1 %5 to i32
-  %7 = add i32 %2, %6
-  %8 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %7, i32 %3)
-  %9 = extractvalue { i32, i1 } %8, 1
-  %10 = select i1 %9, i32 %0, i32 %1
-  ret i32 %10
-}
-
-; Negative test: Multi-use
-define i32 @add_adc_multi_use(i32 %0, i32 %1, i32 %2, i32 %3, ptr %4) {
-; CHECK-LABEL: add_adc_multi_use:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    movl %esi, %eax
-; CHECK-NEXT:    cmpl %esi, %edi
-; CHECK-NEXT:    adcl $0, %edx
-; CHECK-NEXT:    movl %edx, (%r8)
-; CHECK-NEXT:    addl %ecx, %edx
-; CHECK-NEXT:    cmovsl %edi, %eax
-; CHECK-NEXT:    retq
-  %6 = icmp ult i32 %0, %1
-  %7 = zext i1 %6 to i32
-  %8 = add i32 %2, %7
-  store i32 %8, ptr %4, align 4
-  %9 = add i32 %8, %3
-  %10 = icmp slt i32 %9, 0
-  %11 = select i1 %10, i32 %0, i32 %1
-  ret i32 %11
-}
-
-; Positive test: Both adc operands are constants
-define i32 @add_adc_constants(i32 %0, i32 %1, i32 %2) {
-; CHECK-LABEL: add_adc_constants:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    cmpl %esi, %edi
-; CHECK-NEXT:    adcl $42, %eax
-; CHECK-NEXT:    addl %edx, %eax
-; CHECK-NEXT:    retq
-  %4 = icmp ult i32 %0, %1
-  %5 = zext i1 %4 to i8
-  %6 = tail call { i8, i32 } @llvm.x86.addcarry.32(i8 %5, i32 0, i32 42)
-  %7 = extractvalue { i8, i32 } %6, 1
-  %8 = add i32 %7, %2
-  ret i32 %8
-}
-
-; Negative test: Multi-use
-define i32 @add_adc_constants_multi_use(i32 %0, i32 %1, i32 %2, ptr %3) {
-; CHECK-LABEL: add_adc_constants_multi_use:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    movl %esi, %eax
-; CHECK-NEXT:    xorl %esi, %esi
-; CHECK-NEXT:    cmpl %eax, %edi
-; CHECK-NEXT:    adcl $42, %esi
-; CHECK-NEXT:    movl %esi, (%rcx)
-; CHECK-NEXT:    addl %edx, %esi
-; CHECK-NEXT:    cmovsl %edi, %eax
-; CHECK-NEXT:    retq
-  %5 = icmp ult i32 %0, %1
-  %6 = select i1 %5, i32 43, i32 42
-  store i32 %6, ptr %3, align 4
-  %7 = add i32 %6, %2
-  %8 = icmp slt i32 %7, 0
-  %9 = select i1 %8, i32 %0, i32 %1
-  ret i32 %9
-}



More information about the llvm-commits mailing list