Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a0c9845
[X86] Optimized ADD + ADC to ADC
JaydeepChauhan14 Dec 25, 2025
f667556
Merge branch 'main' into optimizeaddwithadc
JaydeepChauhan14 Dec 25, 2025
2a48efd
Addressed the review comments
JaydeepChauhan14 Dec 25, 2025
f68b379
Merge branch 'main' into optimizeaddwithadc
JaydeepChauhan14 Dec 31, 2025
63acd38
Addressed the review comments1
JaydeepChauhan14 Dec 31, 2025
426e499
Updated dyn_cast to cast
JaydeepChauhan14 Jan 1, 2026
f6049c7
Merge branch 'main' into optimizeaddwithadc
JaydeepChauhan14 Jan 2, 2026
fc8e192
Addressed the review comments2
JaydeepChauhan14 Jan 2, 2026
b459a1f
Fixed formatting issue
JaydeepChauhan14 Jan 2, 2026
1572530
Merge branch 'main' into optimizeaddwithadc
JaydeepChauhan14 Jan 3, 2026
e451e86
Addressed the review comments3
JaydeepChauhan14 Jan 3, 2026
d915805
Added precommit tests
JaydeepChauhan14 Feb 11, 2026
c9215c3
Added combine and updated testcase
JaydeepChauhan14 Feb 11, 2026
2bc9500
Merge branch 'main' into optimizeaddwithadc
JaydeepChauhan14 Feb 13, 2026
16de72b
Addressed the review comments3
JaydeepChauhan14 Feb 13, 2026
3c4f127
Merge branch 'main' into optimizeaddwithadc
JaydeepChauhan14 Feb 28, 2026
a7db36b
Addressed the review comments4
JaydeepChauhan14 Feb 28, 2026
5d30f17
Addressed the review comments5
JaydeepChauhan14 Feb 28, 2026
85c8256
Addressed the review comments6
JaydeepChauhan14 Feb 28, 2026
187c4fd
Remove comment
JaydeepChauhan14 Feb 28, 2026
74376bc
Merge branch 'main' into optimizeaddwithadc
JaydeepChauhan14 Mar 10, 2026
e32a1d6
Merge branch 'main' into optimizeaddwithadc
JaydeepChauhan14 Mar 11, 2026
ad98af4
Merge branch 'main' into optimizeaddwithadc
RKSimon Mar 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions llvm/lib/Target/X86/X86ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58896,6 +58896,34 @@ static SDValue combineX86AddSub(SDNode *N, SelectionDAG &DAG,
}
}

// Fold ADD(ADC(Y, C1, CF), C2) -> ADC(Y, C1 + C2, CF) and
// ADD(ADC(Y, 0, CF), X) -> ADC(Y, X, CF) and
Comment thread
JaydeepChauhan14 marked this conversation as resolved.
Outdated
// ADD(ADC(Y, X, CF), 0) -> ADC(Y, X, CF)
Comment thread
JaydeepChauhan14 marked this conversation as resolved.
Outdated
if (!IsSub && LHS.getOpcode() == X86ISD::ADC && LHS.hasOneUse() &&
!needCarryOrOverflowFlag(SDValue(N, 1))) {

auto *C1 = dyn_cast<ConstantSDNode>(LHS.getOperand(1));
auto *C2 = dyn_cast<ConstantSDNode>(RHS);

// Both are constants: fold C1 + C2
if (C1 && C2) {
APInt Sum = C1->getAPIntValue() + C2->getAPIntValue();
return DAG.getNode(X86ISD::ADC, DL, N->getVTList(), LHS.getOperand(0),
DAG.getConstant(Sum, DL, VT), LHS.getOperand(2));
}

// Case: ADC(Y, 0, CF) + X -> ADC(Y, X, CF)
if (C1 && C1->isZero()) {
return DAG.getNode(X86ISD::ADC, DL, N->getVTList(), LHS.getOperand(0),
RHS, LHS.getOperand(2));
}

// Case: ADC(Y, X, CF) + 0 -> ADC(Y, X, CF)
if (C2 && C2->isZero()) {
return LHS;
}
Comment thread
JaydeepChauhan14 marked this conversation as resolved.
Outdated
}

// TODO: Can we drop the ZeroSecondOpOnly limit? This is to guarantee that the
// EFLAGS result doesn't change.
return combineAddOrSubToADCOrSBB(IsSub, DL, VT, LHS, RHS, DAG,
Expand Down
79 changes: 79 additions & 0 deletions llvm/test/CodeGen/X86/combine-add.ll
Original file line number Diff line number Diff line change
Expand Up @@ -561,3 +561,82 @@ define i64 @add_notx_x(i64 %v0) nounwind {
%y = add i64 %x, %v0
ret i64 %y
}

; Basic positive test
define i32 @add_adc_to_adc(i32 %0, i32 %1, i32 %2) nounwind {
; CHECK-LABEL: add_adc_to_adc:
; CHECK: # %bb.0:
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: cmpl %esi, %edi
; CHECK-NEXT: adcl $42, %edx
; CHECK-NEXT: cmovsl %esi, %eax
; CHECK-NEXT: retq
%4 = icmp ult i32 %0, %1
%5 = zext i1 %4 to i32
%6 = add i32 %2, 42
Comment thread
JaydeepChauhan14 marked this conversation as resolved.
%7 = add i32 %6, %5
%8 = icmp slt i32 %7, 0
%9 = select i1 %8, i32 %1, i32 %0
ret i32 %9
}

; positive test: nonconst
define i32 @add_adc_to_adc_nonconst(i32 %0, i32 %1, i32 %2, i32 %extra) nounwind {
; CHECK-LABEL: add_adc_to_adc_nonconst:
; CHECK: # %bb.0:
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: cmpl %esi, %edi
; CHECK-NEXT: adcl %ecx, %edx
; CHECK-NEXT: cmovsl %esi, %eax
; CHECK-NEXT: retq
%c = icmp ult i32 %0, %1
%carry = zext i1 %c to i32
%adc = add i32 %2, %carry
%final = add i32 %adc, %extra
%neg = icmp slt i32 %final, 0
%sel = select i1 %neg, i32 %1, i32 %0
ret i32 %sel
}

; Negative test: Carry or overflow flag is used
define i32 @add_adc_wrong_flags(i32 %0, i32 %1, i32 %2) nounwind {
; CHECK-LABEL: add_adc_wrong_flags:
; CHECK: # %bb.0:
; CHECK-NEXT: movl %esi, %eax
; CHECK-NEXT: cmpl %esi, %edi
; CHECK-NEXT: adcl $10, %edx
; CHECK-NEXT: addl $32, %edx
; CHECK-NEXT: cmovbl %edi, %eax
; CHECK-NEXT: retq
%4 = icmp ult i32 %0, %1
%5 = zext i1 %4 to i32
%6 = add i32 %2, 10
%7 = add i32 %6, %5
%8 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %7, i32 32)
%9 = extractvalue { i32, i1 } %8, 1
%10 = select i1 %9, i32 %0, i32 %1
ret i32 %10
}

; Negative test: Multi-use
define i32 @add_adc_multi_use(i32 %0, i32 %1, i32 %2) nounwind {
; CHECK-LABEL: add_adc_multi_use:
; CHECK: # %bb.0:
; CHECK-NEXT: # kill: def $edx killed $edx def $rdx
; CHECK-NEXT: # kill: def $esi killed $esi def $rsi
; CHECK-NEXT: cmpl %esi, %edi
; CHECK-NEXT: adcl $0, %edx
; CHECK-NEXT: movl %edx, %eax
; CHECK-NEXT: addl $42, %eax
; CHECK-NEXT: cmovsl %edi, %esi
; CHECK-NEXT: leal (%rsi,%rdx), %eax
; CHECK-NEXT: retq
%4 = icmp ult i32 %0, %1
%5 = zext i1 %4 to i32
%6 = add i32 %2, %5
%7 = add i32 %6, 42
%8 = icmp slt i32 %7, 0
%9 = select i1 %8, i32 %0, i32 %1
%10 = add i32 %9, %6
ret i32 %10
}