[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