[llvm] 3e08b9b - [X86] Optimize ADC constant folding when flags are used (#218299)

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 25 05:29:20 PDT 2026


Author: AZero13
Date: 2026-08-25T13:29:15+01:00
New Revision: 3e08b9b3396c4ad931f66c267b5c0659667603cf

URL: https://github.com/llvm/llvm-project/commit/3e08b9b3396c4ad931f66c267b5c0659667603cf
DIFF: https://github.com/llvm/llvm-project/commit/3e08b9b3396c4ad931f66c267b5c0659667603cf.diff

LOG: [X86] Optimize ADC constant folding when flags are used (#218299)

This PR improves the constant folding of the ADC (Add with Carry) node
in the X86 backend.

Specifically, it extends the ADC(C1, C2, Carry) -> ADC(0, C1+C2, Carry)
fold. Previously, this optimization only fired if the resulting flags
from the ADC were strictly dead (i.e., not used by any subsequent node).

Added: 
    

Modified: 
    llvm/lib/Target/X86/X86ISelLowering.cpp
    llvm/test/CodeGen/X86/combine-adc.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index ef2a0960c7d87..6e194b3d0397f 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -59719,14 +59719,18 @@ 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);
+  // iff the flag result is dead or C1+C2 doesn't signed/unsigned overflow.
+  if (LHSC && RHSC && !LHSC->isZero()) {
+    bool UOF, SOF;
+    APInt Sum = LHSC->getAPIntValue().uadd_ov(RHSC->getAPIntValue(), UOF);
+    (void)LHSC->getAPIntValue().sadd_ov(RHSC->getAPIntValue(), SOF);
+
+    if (!N->hasAnyUseOfValue(1) || (!UOF && !SOF)) {
+      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)) {

diff  --git a/llvm/test/CodeGen/X86/combine-adc.ll b/llvm/test/CodeGen/X86/combine-adc.ll
index df20563489bc3..0487c4483f22d 100644
--- a/llvm/test/CodeGen/X86/combine-adc.ll
+++ b/llvm/test/CodeGen/X86/combine-adc.ll
@@ -296,3 +296,41 @@ define i32 @adc_test(i32 %a, i32 %b) {
 
 declare { i8, i32 } @llvm.x86.addcarry.32(i8, i32, i32)
 declare void @use(i8)
+
+define i32 @adc_fold_with_used_flag(i32 %a0) nounwind {
+; X86-LABEL: adc_fold_with_used_flag:
+; X86:       # %bb.0:
+; X86-NEXT:    pushl %esi
+; X86-NEXT:    xorl %esi, %esi
+; X86-NEXT:    btl $11, {{[0-9]+}}(%esp)
+; X86-NEXT:    adcl $100, %esi
+; X86-NEXT:    setb %al
+; X86-NEXT:    movzbl %al, %eax
+; X86-NEXT:    pushl %eax
+; X86-NEXT:    calll use at PLT
+; X86-NEXT:    addl $4, %esp
+; X86-NEXT:    movl %esi, %eax
+; X86-NEXT:    popl %esi
+; X86-NEXT:    retl
+;
+; X64-LABEL: adc_fold_with_used_flag:
+; X64:       # %bb.0:
+; X64-NEXT:    pushq %rbx
+; X64-NEXT:    xorl %ebx, %ebx
+; X64-NEXT:    btl $11, %edi
+; X64-NEXT:    adcl $100, %ebx
+; X64-NEXT:    setb %al
+; X64-NEXT:    movzbl %al, %edi
+; X64-NEXT:    callq use at PLT
+; X64-NEXT:    movl %ebx, %eax
+; X64-NEXT:    popq %rbx
+; X64-NEXT:    retq
+  %bit = lshr i32 %a0, 11
+  %mask = and i32 %bit, 1
+  %isz = trunc i32 %mask to i8
+  %adc = tail call { i8, i32 } @llvm.x86.addcarry.32(i8 %isz, i32 55, i32 45)
+  %carry = extractvalue { i8, i32 } %adc, 0
+  call void @use(i8 %carry)
+  %sum = extractvalue { i8, i32 } %adc, 1
+  ret i32 %sum
+}


        


More information about the llvm-commits mailing list