[llvm] [X86] Fold ADC(SHL(X, 1), 0, Carry) to ADC(X, X, Carry) (PR #219512)

via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 28 09:28:27 PDT 2026


https://github.com/AZero13 updated https://github.com/llvm/llvm-project/pull/219512

>From d5b762cf753b46490e8768367299220f135d5860 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Fri, 28 Aug 2026 12:19:54 -0400
Subject: [PATCH] [X86] Fold ADC(SHL(X, 1), 0, Carry) to ADC(X, X, Carry)

During DAG optimization, expressions like `a + a` are canonicalized to `a << 1` (`ISD::SHL X, 1`).

We need to undo that if we can use adc x, x.
---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 7 +++++++
 llvm/test/CodeGen/X86/combine-adc.ll    | 8 +++-----
 llvm/test/CodeGen/X86/subcarry.ll       | 3 +--
 3 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index c8a38aa1bb154..1609cc3fed993 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -59829,6 +59829,13 @@ static SDValue combineADC(SDNode *N, SelectionDAG &DAG,
     return DAG.getNode(X86ISD::ADC, SDLoc(N), N->getVTList(), LHS.getOperand(0),
                        LHS.getOperand(1), CarryIn);
 
+  // Fold ADC(SHL(X,1),0,Carry) -> ADC(X,X,Carry)
+  // iff the flag result is dead.
+  if (LHS.getOpcode() == ISD::SHL && isOneConstant(LHS.getOperand(1)) && RHSC &&
+      RHSC->isZero() && !needCarryOrOverflowFlag(SDValue(N, 1)))
+    return DAG.getNode(X86ISD::ADC, SDLoc(N), N->getVTList(), LHS.getOperand(0),
+                       LHS.getOperand(0), CarryIn);
+
   return SDValue();
 }
 
diff --git a/llvm/test/CodeGen/X86/combine-adc.ll b/llvm/test/CodeGen/X86/combine-adc.ll
index 0487c4483f22d..fa6c9a0828ff3 100644
--- a/llvm/test/CodeGen/X86/combine-adc.ll
+++ b/llvm/test/CodeGen/X86/combine-adc.ll
@@ -254,17 +254,15 @@ define i32 @adc_shl(i32 %a, i32 %b) {
 ; X86-LABEL: adc_shl:
 ; X86:       # %bb.0:
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT:    addl %eax, %eax
 ; X86-NEXT:    cmpl $70, {{[0-9]+}}(%esp)
-; X86-NEXT:    adcl $0, %eax
+; X86-NEXT:    adcl %eax, %eax
 ; X86-NEXT:    retl
 ;
 ; X64-LABEL: adc_shl:
 ; X64:       # %bb.0:
-; X64-NEXT:    # kill: def $edi killed $edi def $rdi
-; X64-NEXT:    leal (%rdi,%rdi), %eax
+; X64-NEXT:    movl %edi, %eax
 ; X64-NEXT:    cmpl $70, %esi
-; X64-NEXT:    adcl $0, %eax
+; X64-NEXT:    adcl %edi, %eax
 ; X64-NEXT:    retq
   %add = shl i32 %a, 1
   %cmp = icmp ult i32 %b, 70
diff --git a/llvm/test/CodeGen/X86/subcarry.ll b/llvm/test/CodeGen/X86/subcarry.ll
index cd361babf53fb..32ac59763f997 100644
--- a/llvm/test/CodeGen/X86/subcarry.ll
+++ b/llvm/test/CodeGen/X86/subcarry.ll
@@ -1578,12 +1578,11 @@ define <4 x i1> @no_subcarry_vector(<4 x i32> %x0, <4 x i32> %x1, <4 x i32> %y0,
 ; X86-NEXT:    movl 36(%esp), %eax
 ; X86-NEXT:    sbbl 68(%esp), %eax
 ; X86-NEXT:    setb %al
-; X86-NEXT:    addb %al, %al
 ; X86-NEXT:    cmpl 48(%esp), %ecx
 ; X86-NEXT:    movl 32(%esp), %ecx
 ; X86-NEXT:    sbbl 64(%esp), %ecx
 ; X86-NEXT:    movl 12(%esp), %ecx
-; X86-NEXT:    adcb $0, %al
+; X86-NEXT:    adcb %al, %al
 ; X86-NEXT:    shlb $2, %al
 ; X86-NEXT:    cmpl 44(%esp), %ecx
 ; X86-NEXT:    movl 28(%esp), %ecx



More information about the llvm-commits mailing list