[llvm] Optimize ADC folding when flags are used (PR #218299)

via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 23 16:41:18 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-x86

Author: AZero13 (AZero13)

<details>
<summary>Changes</summary>



---
Full diff: https://github.com/llvm/llvm-project/pull/218299.diff


2 Files Affected:

- (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+16-8) 
- (modified) llvm/test/CodeGen/X86/combine-adc.ll (+38) 


``````````diff
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index bf435b0c2f849..f4d5c22d14114 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -59692,14 +59692,22 @@ 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;
+    APInt Sum = LHSC->getAPIntValue().uadd_ov(RHSC->getAPIntValue(), UOF);
+
+    if (!N->hasAnyUseOfValue(1) || !UOF) {
+      bool SOF;
+      (void)LHSC->getAPIntValue().sadd_ov(RHSC->getAPIntValue(), SOF);
+      if (!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 cb934c8664e45..f3aa3cb2d79db 100644
--- a/llvm/test/CodeGen/X86/combine-adc.ll
+++ b/llvm/test/CodeGen/X86/combine-adc.ll
@@ -251,3 +251,41 @@ define i32 @adc_add_multi_use(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, ptr %5) no
 
 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
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/218299


More information about the llvm-commits mailing list