[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