[llvm] [X86] Optimized ADD + ADC to ADC (PR #173543)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 11 05:29:56 PDT 2026
https://github.com/RKSimon updated https://github.com/llvm/llvm-project/pull/173543
>From a0c98459b7022a6a3a0d8ab78485b863718fdc55 Mon Sep 17 00:00:00 2001
From: Chauhan Jaydeep Ashwinbhai <chauhan.jaydeep.ashwinbhai at intel.com>
Date: Thu, 25 Dec 2025 03:13:39 -0800
Subject: [PATCH 01/13] [X86] Optimized ADD + ADC to ADC
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 7 ++++++
llvm/test/CodeGen/X86/combine-adc.ll | 30 +++++++++++++++++++++++++
2 files changed, 37 insertions(+)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 811ffb090d751..fd6e7da196d2f 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -58164,6 +58164,13 @@ static SDValue combineX86AddSub(SDNode *N, SelectionDAG &DAG,
}
}
+ // Fold ADD(ADC(Y,0,CF), C) -> ADC(Y, C, CF)
+ if (!IsSub && LHS.getOpcode() == X86ISD::ADC &&
+ X86::isZeroNode(LHS.getOperand(1)) && isa<ConstantSDNode>(RHS)) {
+ return DAG.getNode(X86ISD::ADC, DL, N->getVTList(), LHS.getOperand(0), RHS,
+ LHS.getOperand(2));
+ }
+
// 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,
diff --git a/llvm/test/CodeGen/X86/combine-adc.ll b/llvm/test/CodeGen/X86/combine-adc.ll
index a2aaea31aa6ff..03e60c10cec4b 100644
--- a/llvm/test/CodeGen/X86/combine-adc.ll
+++ b/llvm/test/CodeGen/X86/combine-adc.ll
@@ -136,5 +136,35 @@ define i32 @adc_merge_sub(i32 %a0) nounwind {
ret i32 %result
}
+define i32 @optimize_adc(i32 %0, i32 %1, i32 %2) {
+; X86-LABEL: optimize_adc:
+; X86: # %bb.0:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT: cmpl %eax, %ecx
+; X86-NEXT: adcl $42, %edx
+; X86-NEXT: js .LBB4_2
+; X86-NEXT: # %bb.1:
+; X86-NEXT: movl %ecx, %eax
+; X86-NEXT: .LBB4_2:
+; X86-NEXT: retl
+;
+; X64-LABEL: optimize_adc:
+; X64: # %bb.0:
+; X64-NEXT: movl %edi, %eax
+; X64-NEXT: cmpl %esi, %edi
+; X64-NEXT: adcl $42, %edx
+; X64-NEXT: cmovsl %esi, %eax
+; X64-NEXT: retq
+ %4 = icmp ult i32 %0, %1
+ %5 = zext i1 %4 to i32
+ %6 = add i32 %2, 42
+ %7 = add i32 %6, %5
+ %8 = icmp slt i32 %7, 0
+ %9 = select i1 %8, i32 %1, i32 %0
+ ret i32 %9
+}
+
declare { i8, i32 } @llvm.x86.addcarry.32(i8, i32, i32)
declare void @use(i8)
>From 2a48efdf81c08e77d5c65e5c72bf3212549f073d Mon Sep 17 00:00:00 2001
From: Chauhan Jaydeep Ashwinbhai <chauhan.jaydeep.ashwinbhai at intel.com>
Date: Thu, 25 Dec 2025 06:10:04 -0800
Subject: [PATCH 02/13] Addressed the review comments
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index fd6e7da196d2f..861f1ee4d80b8 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -58164,11 +58164,14 @@ static SDValue combineX86AddSub(SDNode *N, SelectionDAG &DAG,
}
}
- // Fold ADD(ADC(Y,0,CF), C) -> ADC(Y, C, CF)
+ // Fold ADD(ADC(Y, C1, CF), C2) -> ADC(Y, C1 + C2, CF)
if (!IsSub && LHS.getOpcode() == X86ISD::ADC &&
- X86::isZeroNode(LHS.getOperand(1)) && isa<ConstantSDNode>(RHS)) {
- return DAG.getNode(X86ISD::ADC, DL, N->getVTList(), LHS.getOperand(0), RHS,
- LHS.getOperand(2));
+ isa<ConstantSDNode>(LHS.getOperand(1)) && isa<ConstantSDNode>(RHS)) {
+ auto *C1 = dyn_cast<ConstantSDNode>(LHS.getOperand(1));
+ auto *C2 = dyn_cast<ConstantSDNode>(RHS);
+ 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));
}
// TODO: Can we drop the ZeroSecondOpOnly limit? This is to guarantee that the
>From 63acd38d6a40c9f49636ca3ad6fe16e3d0869b4c Mon Sep 17 00:00:00 2001
From: Chauhan Jaydeep Ashwinbhai <chauhan.jaydeep.ashwinbhai at intel.com>
Date: Wed, 31 Dec 2025 10:39:13 -0800
Subject: [PATCH 03/13] Addressed the review comments1
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 6 ++---
llvm/test/CodeGen/X86/combine-adc.ll | 36 ++++++++++++++++++++++---
2 files changed, 36 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 8a5a3cb16193b..841f39bb4d8b9 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -58166,7 +58166,8 @@ static SDValue combineX86AddSub(SDNode *N, SelectionDAG &DAG,
// Fold ADD(ADC(Y, C1, CF), C2) -> ADC(Y, C1 + C2, CF)
if (!IsSub && LHS.getOpcode() == X86ISD::ADC &&
- isa<ConstantSDNode>(LHS.getOperand(1)) && isa<ConstantSDNode>(RHS)) {
+ isa<ConstantSDNode>(LHS.getOperand(1)) && isa<ConstantSDNode>(RHS) &&
+ !needCarryOrOverflowFlag(SDValue(N, 1))) {
auto *C1 = dyn_cast<ConstantSDNode>(LHS.getOperand(1));
auto *C2 = dyn_cast<ConstantSDNode>(RHS);
APInt Sum = C1->getAPIntValue() + C2->getAPIntValue();
@@ -58252,8 +58253,7 @@ static SDValue combineADC(SDNode *N, SelectionDAG &DAG,
// Fold ADC(ADD(X,Y),0,Carry) -> ADC(X,Y,Carry)
// iff the flag result is dead.
- if (LHS.getOpcode() == ISD::ADD && RHSC && RHSC->isZero() &&
- !N->hasAnyUseOfValue(1))
+ if (LHS.getOpcode() == ISD::ADD && RHSC && RHSC->isZero())
return DAG.getNode(X86ISD::ADC, SDLoc(N), N->getVTList(), LHS.getOperand(0),
LHS.getOperand(1), CarryIn);
diff --git a/llvm/test/CodeGen/X86/combine-adc.ll b/llvm/test/CodeGen/X86/combine-adc.ll
index 03e60c10cec4b..75023f1afeae9 100644
--- a/llvm/test/CodeGen/X86/combine-adc.ll
+++ b/llvm/test/CodeGen/X86/combine-adc.ll
@@ -136,8 +136,8 @@ define i32 @adc_merge_sub(i32 %a0) nounwind {
ret i32 %result
}
-define i32 @optimize_adc(i32 %0, i32 %1, i32 %2) {
-; X86-LABEL: optimize_adc:
+define i32 @optimize_adc_test1(i32 %0, i32 %1, i32 %2) {
+; X86-LABEL: optimize_adc_test1:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %edx
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
@@ -150,7 +150,7 @@ define i32 @optimize_adc(i32 %0, i32 %1, i32 %2) {
; X86-NEXT: .LBB4_2:
; X86-NEXT: retl
;
-; X64-LABEL: optimize_adc:
+; X64-LABEL: optimize_adc_test1:
; X64: # %bb.0:
; X64-NEXT: movl %edi, %eax
; X64-NEXT: cmpl %esi, %edi
@@ -166,5 +166,35 @@ define i32 @optimize_adc(i32 %0, i32 %1, i32 %2) {
ret i32 %9
}
+define i32 @optimize_adc_test2(i32 %0, i32 %1, i32 %2) {
+; X86-LABEL: optimize_adc_test2:
+; X86: # %bb.0:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT: cmpl %eax, %ecx
+; X86-NEXT: movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT: adcl %ecx, %edx
+; X86-NEXT: js .LBB5_2
+; X86-NEXT: # %bb.1:
+; X86-NEXT: movl %ecx, %eax
+; X86-NEXT: .LBB5_2:
+; X86-NEXT: retl
+;
+; X64-LABEL: optimize_adc_test2:
+; X64: # %bb.0:
+; X64-NEXT: movl %edi, %eax
+; X64-NEXT: cmpl %esi, %edi
+; X64-NEXT: adcl %edi, %edx
+; X64-NEXT: cmovsl %esi, %eax
+; X64-NEXT: retq
+ %4 = icmp ult i32 %0, %1
+ %5 = zext i1 %4 to i32
+ %6 = add i32 %2, %0
+ %7 = add i32 %6, %5
+ %8 = icmp slt i32 %7, 0
+ %9 = select i1 %8, i32 %1, i32 %0
+ ret i32 %9
+}
+
declare { i8, i32 } @llvm.x86.addcarry.32(i8, i32, i32)
declare void @use(i8)
>From 426e49924134e22ba1002d73cc3d1f650397a38f Mon Sep 17 00:00:00 2001
From: Chauhan Jaydeep Ashwinbhai <chauhan.jaydeep.ashwinbhai at intel.com>
Date: Thu, 1 Jan 2026 01:43:31 -0800
Subject: [PATCH 04/13] Updated dyn_cast to cast
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 841f39bb4d8b9..6dfd34245911d 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -58168,8 +58168,8 @@ static SDValue combineX86AddSub(SDNode *N, SelectionDAG &DAG,
if (!IsSub && LHS.getOpcode() == X86ISD::ADC &&
isa<ConstantSDNode>(LHS.getOperand(1)) && isa<ConstantSDNode>(RHS) &&
!needCarryOrOverflowFlag(SDValue(N, 1))) {
- auto *C1 = dyn_cast<ConstantSDNode>(LHS.getOperand(1));
- auto *C2 = dyn_cast<ConstantSDNode>(RHS);
+ auto *C1 = cast<ConstantSDNode>(LHS.getOperand(1));
+ auto *C2 = cast<ConstantSDNode>(RHS);
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));
>From fc8e192b242f2b3a1ef57a6ade73689571086ab1 Mon Sep 17 00:00:00 2001
From: Chauhan Jaydeep Ashwinbhai <chauhan.jaydeep.ashwinbhai at intel.com>
Date: Fri, 2 Jan 2026 08:25:09 -0800
Subject: [PATCH 05/13] Addressed the review comments2
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 2 +-
llvm/test/CodeGen/X86/add-sub-bool.ll | 53 ++++++++++++-------
llvm/test/CodeGen/X86/addcarry.ll | 12 +++--
llvm/test/CodeGen/X86/apx/adc.ll | 52 ++++++++++++------
.../X86/large-code-model-sext-small-symbol.ll | 3 +-
5 files changed, 81 insertions(+), 41 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index f23b7f49fe668..a890d9a420925 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -58252,7 +58252,7 @@ static SDValue combineADC(SDNode *N, SelectionDAG &DAG,
// Fold ADC(ADD(X,Y),0,Carry) -> ADC(X,Y,Carry)
// iff the flag result is dead.
- if (LHS.getOpcode() == ISD::ADD && RHSC && RHSC->isZero())
+ if (LHS.getOpcode() == ISD::ADD && RHSC && RHSC->isZero() && !needCarryOrOverflowFlag(SDValue(N, 1)))
return DAG.getNode(X86ISD::ADC, SDLoc(N), N->getVTList(), LHS.getOperand(0),
LHS.getOperand(1), CarryIn);
diff --git a/llvm/test/CodeGen/X86/add-sub-bool.ll b/llvm/test/CodeGen/X86/add-sub-bool.ll
index 1df284fb9fe2c..e42c5fa42b95c 100644
--- a/llvm/test/CodeGen/X86/add-sub-bool.ll
+++ b/llvm/test/CodeGen/X86/add-sub-bool.ll
@@ -18,15 +18,18 @@ define i32 @test_i32_add_add_idx(i32 %x, i32 %y, i32 %z) nounwind {
; X86-LABEL: test_i32_add_add_idx:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: addl {{[0-9]+}}(%esp), %eax
; X86-NEXT: btl $30, {{[0-9]+}}(%esp)
-; X86-NEXT: adcl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: adcl $0, %eax
; X86-NEXT: retl
;
; X64-LABEL: test_i32_add_add_idx:
; X64: # %bb.0:
-; X64-NEXT: movl %edi, %eax
+; X64-NEXT: # kill: def $esi killed $esi def $rsi
+; X64-NEXT: # kill: def $edi killed $edi def $rdi
+; X64-NEXT: leal (%rdi,%rsi), %eax
; X64-NEXT: btl $30, %edx
-; X64-NEXT: adcl %esi, %eax
+; X64-NEXT: adcl $0, %eax
; X64-NEXT: retq
%add = add i32 %y, %x
%shift = lshr i32 %z, 30
@@ -39,15 +42,18 @@ define i32 @test_i32_add_add_commute_idx(i32 %x, i32 %y, i32 %z) nounwind {
; X86-LABEL: test_i32_add_add_commute_idx:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: addl {{[0-9]+}}(%esp), %eax
; X86-NEXT: btl $2, {{[0-9]+}}(%esp)
-; X86-NEXT: adcl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: adcl $0, %eax
; X86-NEXT: retl
;
; X64-LABEL: test_i32_add_add_commute_idx:
; X64: # %bb.0:
-; X64-NEXT: movl %edi, %eax
+; X64-NEXT: # kill: def $esi killed $esi def $rsi
+; X64-NEXT: # kill: def $edi killed $edi def $rdi
+; X64-NEXT: leal (%rdi,%rsi), %eax
; X64-NEXT: btl $2, %edx
-; X64-NEXT: adcl %esi, %eax
+; X64-NEXT: adcl $0, %eax
; X64-NEXT: retq
%add = add i32 %y, %x
%shift = lshr i32 %z, 2
@@ -84,15 +90,18 @@ define i24 @test_i24_add_add_idx(i24 %x, i24 %y, i24 %z) nounwind {
; X86-LABEL: test_i24_add_add_idx:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: addl {{[0-9]+}}(%esp), %eax
; X86-NEXT: btl $15, {{[0-9]+}}(%esp)
-; X86-NEXT: adcl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: adcl $0, %eax
; X86-NEXT: retl
;
; X64-LABEL: test_i24_add_add_idx:
; X64: # %bb.0:
-; X64-NEXT: movl %edi, %eax
+; X64-NEXT: # kill: def $esi killed $esi def $rsi
+; X64-NEXT: # kill: def $edi killed $edi def $rdi
+; X64-NEXT: leal (%rdi,%rsi), %eax
; X64-NEXT: btl $15, %edx
-; X64-NEXT: adcl %esi, %eax
+; X64-NEXT: adcl $0, %eax
; X64-NEXT: retq
%add = add i24 %y, %x
%shift = lshr i24 %z, 15
@@ -346,18 +355,21 @@ define i32 @test_i32_sub_sum_idx(i32 %x, i32 %y, i32 %z) nounwind {
define i32 @test_i32_add_add_var(i32 %x, i32 %y, i32 %z, i32 %w) nounwind {
; X86-LABEL: test_i32_add_add_var:
; X86: # %bb.0:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
; X86-NEXT: movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: addl {{[0-9]+}}(%esp), %eax
; X86-NEXT: btl %ecx, %edx
-; X86-NEXT: adcl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: adcl $0, %eax
; X86-NEXT: retl
;
; X64-LABEL: test_i32_add_add_var:
; X64: # %bb.0:
-; X64-NEXT: movl %edi, %eax
+; X64-NEXT: # kill: def $esi killed $esi def $rsi
+; X64-NEXT: # kill: def $edi killed $edi def $rdi
+; X64-NEXT: leal (%rdi,%rsi), %eax
; X64-NEXT: btl %ecx, %edx
-; X64-NEXT: adcl %esi, %eax
+; X64-NEXT: adcl $0, %eax
; X64-NEXT: retq
%add = add i32 %y, %x
%shift = lshr i32 %z, %w
@@ -369,18 +381,21 @@ define i32 @test_i32_add_add_var(i32 %x, i32 %y, i32 %z, i32 %w) nounwind {
define i32 @test_i32_add_add_commute_var(i32 %x, i32 %y, i32 %z, i32 %w) nounwind {
; X86-LABEL: test_i32_add_add_commute_var:
; X86: # %bb.0:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
; X86-NEXT: movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: addl {{[0-9]+}}(%esp), %eax
; X86-NEXT: btl %ecx, %edx
-; X86-NEXT: adcl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: adcl $0, %eax
; X86-NEXT: retl
;
; X64-LABEL: test_i32_add_add_commute_var:
; X64: # %bb.0:
-; X64-NEXT: movl %edi, %eax
+; X64-NEXT: # kill: def $esi killed $esi def $rsi
+; X64-NEXT: # kill: def $edi killed $edi def $rdi
+; X64-NEXT: leal (%rdi,%rsi), %eax
; X64-NEXT: btl %ecx, %edx
-; X64-NEXT: adcl %esi, %eax
+; X64-NEXT: adcl $0, %eax
; X64-NEXT: retq
%add = add i32 %y, %x
%shift = lshr i32 %z, %w
@@ -420,9 +435,9 @@ define i64 @test_i64_add_add_var(i64 %x, i64 %y, i64 %z, i64 %w) nounwind {
;
; X64-LABEL: test_i64_add_add_var:
; X64: # %bb.0:
-; X64-NEXT: movq %rdi, %rax
+; X64-NEXT: leaq (%rdi,%rsi), %rax
; X64-NEXT: btq %rcx, %rdx
-; X64-NEXT: adcq %rsi, %rax
+; X64-NEXT: adcq $0, %rax
; X64-NEXT: retq
%add = add i64 %y, %x
%shift = lshr i64 %z, %w
diff --git a/llvm/test/CodeGen/X86/addcarry.ll b/llvm/test/CodeGen/X86/addcarry.ll
index ee4482062df31..f44fd6a0ab553 100644
--- a/llvm/test/CodeGen/X86/addcarry.ll
+++ b/llvm/test/CodeGen/X86/addcarry.ll
@@ -1382,9 +1382,11 @@ define void @add_U256_without_i128_or_recursive(ptr sret(%uint256) %0, ptr %1, p
define i32 @addcarry_ult(i32 %a, i32 %b, i32 %x, i32 %y) nounwind {
; CHECK-LABEL: addcarry_ult:
; CHECK: # %bb.0:
-; CHECK-NEXT: movl %edi, %eax
+; CHECK-NEXT: # kill: def $esi killed $esi def $rsi
+; CHECK-NEXT: # kill: def $edi killed $edi def $rdi
+; CHECK-NEXT: leal (%rdi,%rsi), %eax
; CHECK-NEXT: cmpl %ecx, %edx
-; CHECK-NEXT: adcl %esi, %eax
+; CHECK-NEXT: adcl $0, %eax
; CHECK-NEXT: retq
%s = add i32 %a, %b
%k = icmp ult i32 %x, %y
@@ -1396,9 +1398,11 @@ define i32 @addcarry_ult(i32 %a, i32 %b, i32 %x, i32 %y) nounwind {
define i32 @addcarry_ugt(i32 %a, i32 %b, i32 %x, i32 %y) nounwind {
; CHECK-LABEL: addcarry_ugt:
; CHECK: # %bb.0:
-; CHECK-NEXT: movl %edi, %eax
+; CHECK-NEXT: # kill: def $esi killed $esi def $rsi
+; CHECK-NEXT: # kill: def $edi killed $edi def $rdi
+; CHECK-NEXT: leal (%rdi,%rsi), %eax
; CHECK-NEXT: cmpl %edx, %ecx
-; CHECK-NEXT: adcl %esi, %eax
+; CHECK-NEXT: adcl $0, %eax
; CHECK-NEXT: retq
%s = add i32 %a, %b
%k = icmp ugt i32 %x, %y
diff --git a/llvm/test/CodeGen/X86/apx/adc.ll b/llvm/test/CodeGen/X86/apx/adc.ll
index ec9800ddc69ae..f40c4c0d7c601 100644
--- a/llvm/test/CodeGen/X86/apx/adc.ll
+++ b/llvm/test/CodeGen/X86/apx/adc.ll
@@ -4,8 +4,9 @@
define i8 @adc8rr(i8 %a, i8 %b, i8 %x, i8 %y) nounwind {
; CHECK-LABEL: adc8rr:
; CHECK: # %bb.0:
+; CHECK-NEXT: addb %sil, %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x00,0xf7]
; CHECK-NEXT: cmpb %dl, %cl # encoding: [0x38,0xd1]
-; CHECK-NEXT: adcb %sil, %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x10,0xf7]
+; CHECK-NEXT: adcb $0, %al # EVEX TO LEGACY Compression encoding: [0x14,0x00]
; CHECK-NEXT: retq # encoding: [0xc3]
%s = add i8 %a, %b
%k = icmp ugt i8 %x, %y
@@ -17,8 +18,9 @@ define i8 @adc8rr(i8 %a, i8 %b, i8 %x, i8 %y) nounwind {
define i16 @adc16rr(i16 %a, i16 %b, i16 %x, i16 %y) nounwind {
; CHECK-LABEL: adc16rr:
; CHECK: # %bb.0:
+; CHECK-NEXT: addw %si, %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x01,0xf7]
; CHECK-NEXT: cmpw %dx, %cx # encoding: [0x66,0x39,0xd1]
-; CHECK-NEXT: adcw %si, %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x11,0xf7]
+; CHECK-NEXT: adcw $0, %ax # EVEX TO LEGACY Compression encoding: [0x66,0x83,0xd0,0x00]
; CHECK-NEXT: retq # encoding: [0xc3]
%s = add i16 %a, %b
%k = icmp ugt i16 %x, %y
@@ -30,8 +32,9 @@ define i16 @adc16rr(i16 %a, i16 %b, i16 %x, i16 %y) nounwind {
define i32 @adc32rr(i32 %a, i32 %b, i32 %x, i32 %y) nounwind {
; CHECK-LABEL: adc32rr:
; CHECK: # %bb.0:
+; CHECK-NEXT: leal (%rdi,%rsi), %eax # encoding: [0x8d,0x04,0x37]
; CHECK-NEXT: cmpl %edx, %ecx # encoding: [0x39,0xd1]
-; CHECK-NEXT: adcl %esi, %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x11,0xf7]
+; CHECK-NEXT: adcl $0, %eax # EVEX TO LEGACY Compression encoding: [0x83,0xd0,0x00]
; CHECK-NEXT: retq # encoding: [0xc3]
%s = add i32 %a, %b
%k = icmp ugt i32 %x, %y
@@ -43,8 +46,9 @@ define i32 @adc32rr(i32 %a, i32 %b, i32 %x, i32 %y) nounwind {
define i64 @adc64rr(i64 %a, i64 %b, i64 %x, i64 %y) nounwind {
; CHECK-LABEL: adc64rr:
; CHECK: # %bb.0:
+; CHECK-NEXT: leaq (%rdi,%rsi), %rax # encoding: [0x48,0x8d,0x04,0x37]
; CHECK-NEXT: cmpq %rdx, %rcx # encoding: [0x48,0x39,0xd1]
-; CHECK-NEXT: adcq %rsi, %rdi, %rax # encoding: [0x62,0xf4,0xfc,0x18,0x11,0xf7]
+; CHECK-NEXT: adcq $0, %rax # EVEX TO LEGACY Compression encoding: [0x48,0x83,0xd0,0x00]
; CHECK-NEXT: retq # encoding: [0xc3]
%s = add i64 %a, %b
%k = icmp ugt i64 %x, %y
@@ -56,8 +60,9 @@ define i64 @adc64rr(i64 %a, i64 %b, i64 %x, i64 %y) nounwind {
define i8 @adc8rm(i8 %a, ptr %ptr, i8 %x, i8 %y) nounwind {
; CHECK-LABEL: adc8rm:
; CHECK: # %bb.0:
+; CHECK-NEXT: addb (%rsi), %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x02,0x3e]
; CHECK-NEXT: cmpb %dl, %cl # encoding: [0x38,0xd1]
-; CHECK-NEXT: adcb (%rsi), %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x12,0x3e]
+; CHECK-NEXT: adcb $0, %al # EVEX TO LEGACY Compression encoding: [0x14,0x00]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i8, ptr %ptr
%s = add i8 %a, %b
@@ -70,8 +75,9 @@ define i8 @adc8rm(i8 %a, ptr %ptr, i8 %x, i8 %y) nounwind {
define i16 @adc16rm(i16 %a, ptr %ptr, i16 %x, i16 %y) nounwind {
; CHECK-LABEL: adc16rm:
; CHECK: # %bb.0:
+; CHECK-NEXT: addw (%rsi), %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x03,0x3e]
; CHECK-NEXT: cmpw %dx, %cx # encoding: [0x66,0x39,0xd1]
-; CHECK-NEXT: adcw (%rsi), %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x13,0x3e]
+; CHECK-NEXT: adcw $0, %ax # EVEX TO LEGACY Compression encoding: [0x66,0x83,0xd0,0x00]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i16, ptr %ptr
%s = add i16 %a, %b
@@ -84,8 +90,9 @@ define i16 @adc16rm(i16 %a, ptr %ptr, i16 %x, i16 %y) nounwind {
define i32 @adc32rm(i32 %a, ptr %ptr, i32 %x, i32 %y) nounwind {
; CHECK-LABEL: adc32rm:
; CHECK: # %bb.0:
+; CHECK-NEXT: addl (%rsi), %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x03,0x3e]
; CHECK-NEXT: cmpl %edx, %ecx # encoding: [0x39,0xd1]
-; CHECK-NEXT: adcl (%rsi), %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x13,0x3e]
+; CHECK-NEXT: adcl $0, %eax # EVEX TO LEGACY Compression encoding: [0x83,0xd0,0x00]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i32, ptr %ptr
%s = add i32 %a, %b
@@ -98,8 +105,9 @@ define i32 @adc32rm(i32 %a, ptr %ptr, i32 %x, i32 %y) nounwind {
define i64 @adc64rm(i64 %a, ptr %ptr, i64 %x, i64 %y) nounwind {
; CHECK-LABEL: adc64rm:
; CHECK: # %bb.0:
+; CHECK-NEXT: addq (%rsi), %rdi, %rax # encoding: [0x62,0xf4,0xfc,0x18,0x03,0x3e]
; CHECK-NEXT: cmpq %rdx, %rcx # encoding: [0x48,0x39,0xd1]
-; CHECK-NEXT: adcq (%rsi), %rdi, %rax # encoding: [0x62,0xf4,0xfc,0x18,0x13,0x3e]
+; CHECK-NEXT: adcq $0, %rax # EVEX TO LEGACY Compression encoding: [0x48,0x83,0xd0,0x00]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i64, ptr %ptr
%s = add i64 %a, %b
@@ -206,8 +214,9 @@ define i64 @adc64ri(i64 %a, i64 %x, i64 %y) nounwind {
define i8 @adc8mr(i8 %a, ptr %ptr, i8 %x, i8 %y) nounwind {
; CHECK-LABEL: adc8mr:
; CHECK: # %bb.0:
+; CHECK-NEXT: addb (%rsi), %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x02,0x3e]
; CHECK-NEXT: cmpb %dl, %cl # encoding: [0x38,0xd1]
-; CHECK-NEXT: adcb (%rsi), %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x12,0x3e]
+; CHECK-NEXT: adcb $0, %al # EVEX TO LEGACY Compression encoding: [0x14,0x00]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i8, ptr %ptr
%s = add i8 %b, %a
@@ -220,8 +229,9 @@ define i8 @adc8mr(i8 %a, ptr %ptr, i8 %x, i8 %y) nounwind {
define i16 @adc16mr(i16 %a, ptr %ptr, i16 %x, i16 %y) nounwind {
; CHECK-LABEL: adc16mr:
; CHECK: # %bb.0:
+; CHECK-NEXT: addw (%rsi), %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x03,0x3e]
; CHECK-NEXT: cmpw %dx, %cx # encoding: [0x66,0x39,0xd1]
-; CHECK-NEXT: adcw (%rsi), %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x13,0x3e]
+; CHECK-NEXT: adcw $0, %ax # EVEX TO LEGACY Compression encoding: [0x66,0x83,0xd0,0x00]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i16, ptr %ptr
%s = add i16 %b, %a
@@ -234,8 +244,9 @@ define i16 @adc16mr(i16 %a, ptr %ptr, i16 %x, i16 %y) nounwind {
define i32 @adc32mr(i32 %a, ptr %ptr, i32 %x, i32 %y) nounwind {
; CHECK-LABEL: adc32mr:
; CHECK: # %bb.0:
+; CHECK-NEXT: addl (%rsi), %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x03,0x3e]
; CHECK-NEXT: cmpl %edx, %ecx # encoding: [0x39,0xd1]
-; CHECK-NEXT: adcl (%rsi), %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x13,0x3e]
+; CHECK-NEXT: adcl $0, %eax # EVEX TO LEGACY Compression encoding: [0x83,0xd0,0x00]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i32, ptr %ptr
%s = add i32 %b, %a
@@ -248,8 +259,9 @@ define i32 @adc32mr(i32 %a, ptr %ptr, i32 %x, i32 %y) nounwind {
define i64 @adc64mr(i64 %a, ptr %ptr, i64 %x, i64 %y) nounwind {
; CHECK-LABEL: adc64mr:
; CHECK: # %bb.0:
+; CHECK-NEXT: addq (%rsi), %rdi, %rax # encoding: [0x62,0xf4,0xfc,0x18,0x03,0x3e]
; CHECK-NEXT: cmpq %rdx, %rcx # encoding: [0x48,0x39,0xd1]
-; CHECK-NEXT: adcq (%rsi), %rdi, %rax # encoding: [0x62,0xf4,0xfc,0x18,0x13,0x3e]
+; CHECK-NEXT: adcq $0, %rax # EVEX TO LEGACY Compression encoding: [0x48,0x83,0xd0,0x00]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i64, ptr %ptr
%s = add i64 %b, %a
@@ -363,8 +375,10 @@ define i64 @adc64mi(ptr %ptr, i64 %x, i64 %y) nounwind {
define void @adc8mr_legacy(i8 %a, ptr %ptr, i8 %x, i8 %y) nounwind {
; CHECK-LABEL: adc8mr_legacy:
; CHECK: # %bb.0:
+; CHECK-NEXT: addb (%rsi), %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x02,0x3e]
; CHECK-NEXT: cmpb %dl, %cl # encoding: [0x38,0xd1]
-; CHECK-NEXT: adcb %dil, (%rsi) # encoding: [0x40,0x10,0x3e]
+; CHECK-NEXT: adcb $0, %al # EVEX TO LEGACY Compression encoding: [0x14,0x00]
+; CHECK-NEXT: movb %al, (%rsi) # encoding: [0x88,0x06]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i8, ptr %ptr
%s = add i8 %b, %a
@@ -378,8 +392,10 @@ define void @adc8mr_legacy(i8 %a, ptr %ptr, i8 %x, i8 %y) nounwind {
define void @adc16mr_legacy(i16 %a, ptr %ptr, i16 %x, i16 %y) nounwind {
; CHECK-LABEL: adc16mr_legacy:
; CHECK: # %bb.0:
+; CHECK-NEXT: addw (%rsi), %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x03,0x3e]
; CHECK-NEXT: cmpw %dx, %cx # encoding: [0x66,0x39,0xd1]
-; CHECK-NEXT: adcw %di, (%rsi) # encoding: [0x66,0x11,0x3e]
+; CHECK-NEXT: adcw $0, %ax # EVEX TO LEGACY Compression encoding: [0x66,0x83,0xd0,0x00]
+; CHECK-NEXT: movw %ax, (%rsi) # encoding: [0x66,0x89,0x06]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i16, ptr %ptr
%s = add i16 %b, %a
@@ -393,8 +409,10 @@ define void @adc16mr_legacy(i16 %a, ptr %ptr, i16 %x, i16 %y) nounwind {
define void @adc32mr_legacy(i32 %a, ptr %ptr, i32 %x, i32 %y) nounwind {
; CHECK-LABEL: adc32mr_legacy:
; CHECK: # %bb.0:
+; CHECK-NEXT: addl (%rsi), %edi # EVEX TO LEGACY Compression encoding: [0x03,0x3e]
; CHECK-NEXT: cmpl %edx, %ecx # encoding: [0x39,0xd1]
-; CHECK-NEXT: adcl %edi, (%rsi) # encoding: [0x11,0x3e]
+; CHECK-NEXT: adcl $0, %edi # EVEX TO LEGACY Compression encoding: [0x83,0xd7,0x00]
+; CHECK-NEXT: movl %edi, (%rsi) # encoding: [0x89,0x3e]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i32, ptr %ptr
%s = add i32 %b, %a
@@ -408,8 +426,10 @@ define void @adc32mr_legacy(i32 %a, ptr %ptr, i32 %x, i32 %y) nounwind {
define void @adc64mr_legacy(i64 %a, ptr %ptr, i64 %x, i64 %y) nounwind {
; CHECK-LABEL: adc64mr_legacy:
; CHECK: # %bb.0:
+; CHECK-NEXT: addq (%rsi), %rdi # EVEX TO LEGACY Compression encoding: [0x48,0x03,0x3e]
; CHECK-NEXT: cmpq %rdx, %rcx # encoding: [0x48,0x39,0xd1]
-; CHECK-NEXT: adcq %rdi, (%rsi) # encoding: [0x48,0x11,0x3e]
+; CHECK-NEXT: adcq $0, %rdi # EVEX TO LEGACY Compression encoding: [0x48,0x83,0xd7,0x00]
+; CHECK-NEXT: movq %rdi, (%rsi) # encoding: [0x48,0x89,0x3e]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i64, ptr %ptr
%s = add i64 %b, %a
diff --git a/llvm/test/CodeGen/X86/large-code-model-sext-small-symbol.ll b/llvm/test/CodeGen/X86/large-code-model-sext-small-symbol.ll
index 0a4b3d3cff903..d3d9737f24c86 100644
--- a/llvm/test/CodeGen/X86/large-code-model-sext-small-symbol.ll
+++ b/llvm/test/CodeGen/X86/large-code-model-sext-small-symbol.ll
@@ -17,8 +17,9 @@ define ptr @f(i64 %0) {
; CHECK-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L0$pb, %rcx
; CHECK-NEXT: addq %rax, %rcx
; CHECK-NEXT: movabsq $g at GOTOFF, %rax
+; CHECK-NEXT: addq %rcx, %rax
; CHECK-NEXT: cmpq $1, %rdi
-; CHECK-NEXT: adcq %rcx, %rax
+; CHECK-NEXT: adcq $0, %rax
; CHECK-NEXT: retq
%2 = icmp eq i64 %0, 0
%3 = zext i1 %2 to i64
>From b459a1fee24f98817337a7bb523d4653ef76cace Mon Sep 17 00:00:00 2001
From: Chauhan Jaydeep Ashwinbhai <chauhan.jaydeep.ashwinbhai at intel.com>
Date: Fri, 2 Jan 2026 08:27:17 -0800
Subject: [PATCH 06/13] Fixed formatting issue
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index a890d9a420925..fbbcea2756952 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -58252,7 +58252,8 @@ static SDValue combineADC(SDNode *N, SelectionDAG &DAG,
// Fold ADC(ADD(X,Y),0,Carry) -> ADC(X,Y,Carry)
// iff the flag result is dead.
- if (LHS.getOpcode() == ISD::ADD && RHSC && RHSC->isZero() && !needCarryOrOverflowFlag(SDValue(N, 1)))
+ if (LHS.getOpcode() == ISD::ADD && RHSC && RHSC->isZero() &&
+ !needCarryOrOverflowFlag(SDValue(N, 1)))
return DAG.getNode(X86ISD::ADC, SDLoc(N), N->getVTList(), LHS.getOperand(0),
LHS.getOperand(1), CarryIn);
>From e451e86f704a8f3240c7aec48c485078983d18f2 Mon Sep 17 00:00:00 2001
From: Chauhan Jaydeep Ashwinbhai <chauhan.jaydeep.ashwinbhai at intel.com>
Date: Sat, 3 Jan 2026 00:07:43 -0800
Subject: [PATCH 07/13] Addressed the review comments3
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 5 +-
llvm/test/CodeGen/X86/add-sub-bool.ll | 53 +++++++------------
llvm/test/CodeGen/X86/addcarry.ll | 12 ++---
llvm/test/CodeGen/X86/apx/adc.ll | 52 ++++++------------
.../X86/large-code-model-sext-small-symbol.ll | 3 +-
5 files changed, 44 insertions(+), 81 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index fbbcea2756952..986f70deee760 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -57898,7 +57898,10 @@ static SDValue combineFunnelShift(SDNode *N, SelectionDAG &DAG,
static bool needCarryOrOverflowFlag(SDValue Flags) {
assert(Flags.getValueType() == MVT::i32 && "Unexpected VT!");
- for (const SDNode *User : Flags->users()) {
+ for (const SDUse &Use : Flags->uses()) {
+ if (Use != Flags)
+ continue;
+ const SDNode *User = Use.getUser();
X86::CondCode CC;
switch (User->getOpcode()) {
default:
diff --git a/llvm/test/CodeGen/X86/add-sub-bool.ll b/llvm/test/CodeGen/X86/add-sub-bool.ll
index e42c5fa42b95c..1df284fb9fe2c 100644
--- a/llvm/test/CodeGen/X86/add-sub-bool.ll
+++ b/llvm/test/CodeGen/X86/add-sub-bool.ll
@@ -18,18 +18,15 @@ define i32 @test_i32_add_add_idx(i32 %x, i32 %y, i32 %z) nounwind {
; X86-LABEL: test_i32_add_add_idx:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: addl {{[0-9]+}}(%esp), %eax
; X86-NEXT: btl $30, {{[0-9]+}}(%esp)
-; X86-NEXT: adcl $0, %eax
+; X86-NEXT: adcl {{[0-9]+}}(%esp), %eax
; X86-NEXT: retl
;
; X64-LABEL: test_i32_add_add_idx:
; X64: # %bb.0:
-; X64-NEXT: # kill: def $esi killed $esi def $rsi
-; X64-NEXT: # kill: def $edi killed $edi def $rdi
-; X64-NEXT: leal (%rdi,%rsi), %eax
+; X64-NEXT: movl %edi, %eax
; X64-NEXT: btl $30, %edx
-; X64-NEXT: adcl $0, %eax
+; X64-NEXT: adcl %esi, %eax
; X64-NEXT: retq
%add = add i32 %y, %x
%shift = lshr i32 %z, 30
@@ -42,18 +39,15 @@ define i32 @test_i32_add_add_commute_idx(i32 %x, i32 %y, i32 %z) nounwind {
; X86-LABEL: test_i32_add_add_commute_idx:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: addl {{[0-9]+}}(%esp), %eax
; X86-NEXT: btl $2, {{[0-9]+}}(%esp)
-; X86-NEXT: adcl $0, %eax
+; X86-NEXT: adcl {{[0-9]+}}(%esp), %eax
; X86-NEXT: retl
;
; X64-LABEL: test_i32_add_add_commute_idx:
; X64: # %bb.0:
-; X64-NEXT: # kill: def $esi killed $esi def $rsi
-; X64-NEXT: # kill: def $edi killed $edi def $rdi
-; X64-NEXT: leal (%rdi,%rsi), %eax
+; X64-NEXT: movl %edi, %eax
; X64-NEXT: btl $2, %edx
-; X64-NEXT: adcl $0, %eax
+; X64-NEXT: adcl %esi, %eax
; X64-NEXT: retq
%add = add i32 %y, %x
%shift = lshr i32 %z, 2
@@ -90,18 +84,15 @@ define i24 @test_i24_add_add_idx(i24 %x, i24 %y, i24 %z) nounwind {
; X86-LABEL: test_i24_add_add_idx:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: addl {{[0-9]+}}(%esp), %eax
; X86-NEXT: btl $15, {{[0-9]+}}(%esp)
-; X86-NEXT: adcl $0, %eax
+; X86-NEXT: adcl {{[0-9]+}}(%esp), %eax
; X86-NEXT: retl
;
; X64-LABEL: test_i24_add_add_idx:
; X64: # %bb.0:
-; X64-NEXT: # kill: def $esi killed $esi def $rsi
-; X64-NEXT: # kill: def $edi killed $edi def $rdi
-; X64-NEXT: leal (%rdi,%rsi), %eax
+; X64-NEXT: movl %edi, %eax
; X64-NEXT: btl $15, %edx
-; X64-NEXT: adcl $0, %eax
+; X64-NEXT: adcl %esi, %eax
; X64-NEXT: retq
%add = add i24 %y, %x
%shift = lshr i24 %z, 15
@@ -355,21 +346,18 @@ define i32 @test_i32_sub_sum_idx(i32 %x, i32 %y, i32 %z) nounwind {
define i32 @test_i32_add_add_var(i32 %x, i32 %y, i32 %z, i32 %w) nounwind {
; X86-LABEL: test_i32_add_add_var:
; X86: # %bb.0:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
; X86-NEXT: movl {{[0-9]+}}(%esp), %edx
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: addl {{[0-9]+}}(%esp), %eax
; X86-NEXT: btl %ecx, %edx
-; X86-NEXT: adcl $0, %eax
+; X86-NEXT: adcl {{[0-9]+}}(%esp), %eax
; X86-NEXT: retl
;
; X64-LABEL: test_i32_add_add_var:
; X64: # %bb.0:
-; X64-NEXT: # kill: def $esi killed $esi def $rsi
-; X64-NEXT: # kill: def $edi killed $edi def $rdi
-; X64-NEXT: leal (%rdi,%rsi), %eax
+; X64-NEXT: movl %edi, %eax
; X64-NEXT: btl %ecx, %edx
-; X64-NEXT: adcl $0, %eax
+; X64-NEXT: adcl %esi, %eax
; X64-NEXT: retq
%add = add i32 %y, %x
%shift = lshr i32 %z, %w
@@ -381,21 +369,18 @@ define i32 @test_i32_add_add_var(i32 %x, i32 %y, i32 %z, i32 %w) nounwind {
define i32 @test_i32_add_add_commute_var(i32 %x, i32 %y, i32 %z, i32 %w) nounwind {
; X86-LABEL: test_i32_add_add_commute_var:
; X86: # %bb.0:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
; X86-NEXT: movl {{[0-9]+}}(%esp), %edx
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: addl {{[0-9]+}}(%esp), %eax
; X86-NEXT: btl %ecx, %edx
-; X86-NEXT: adcl $0, %eax
+; X86-NEXT: adcl {{[0-9]+}}(%esp), %eax
; X86-NEXT: retl
;
; X64-LABEL: test_i32_add_add_commute_var:
; X64: # %bb.0:
-; X64-NEXT: # kill: def $esi killed $esi def $rsi
-; X64-NEXT: # kill: def $edi killed $edi def $rdi
-; X64-NEXT: leal (%rdi,%rsi), %eax
+; X64-NEXT: movl %edi, %eax
; X64-NEXT: btl %ecx, %edx
-; X64-NEXT: adcl $0, %eax
+; X64-NEXT: adcl %esi, %eax
; X64-NEXT: retq
%add = add i32 %y, %x
%shift = lshr i32 %z, %w
@@ -435,9 +420,9 @@ define i64 @test_i64_add_add_var(i64 %x, i64 %y, i64 %z, i64 %w) nounwind {
;
; X64-LABEL: test_i64_add_add_var:
; X64: # %bb.0:
-; X64-NEXT: leaq (%rdi,%rsi), %rax
+; X64-NEXT: movq %rdi, %rax
; X64-NEXT: btq %rcx, %rdx
-; X64-NEXT: adcq $0, %rax
+; X64-NEXT: adcq %rsi, %rax
; X64-NEXT: retq
%add = add i64 %y, %x
%shift = lshr i64 %z, %w
diff --git a/llvm/test/CodeGen/X86/addcarry.ll b/llvm/test/CodeGen/X86/addcarry.ll
index f44fd6a0ab553..ee4482062df31 100644
--- a/llvm/test/CodeGen/X86/addcarry.ll
+++ b/llvm/test/CodeGen/X86/addcarry.ll
@@ -1382,11 +1382,9 @@ define void @add_U256_without_i128_or_recursive(ptr sret(%uint256) %0, ptr %1, p
define i32 @addcarry_ult(i32 %a, i32 %b, i32 %x, i32 %y) nounwind {
; CHECK-LABEL: addcarry_ult:
; CHECK: # %bb.0:
-; CHECK-NEXT: # kill: def $esi killed $esi def $rsi
-; CHECK-NEXT: # kill: def $edi killed $edi def $rdi
-; CHECK-NEXT: leal (%rdi,%rsi), %eax
+; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: cmpl %ecx, %edx
-; CHECK-NEXT: adcl $0, %eax
+; CHECK-NEXT: adcl %esi, %eax
; CHECK-NEXT: retq
%s = add i32 %a, %b
%k = icmp ult i32 %x, %y
@@ -1398,11 +1396,9 @@ define i32 @addcarry_ult(i32 %a, i32 %b, i32 %x, i32 %y) nounwind {
define i32 @addcarry_ugt(i32 %a, i32 %b, i32 %x, i32 %y) nounwind {
; CHECK-LABEL: addcarry_ugt:
; CHECK: # %bb.0:
-; CHECK-NEXT: # kill: def $esi killed $esi def $rsi
-; CHECK-NEXT: # kill: def $edi killed $edi def $rdi
-; CHECK-NEXT: leal (%rdi,%rsi), %eax
+; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: cmpl %edx, %ecx
-; CHECK-NEXT: adcl $0, %eax
+; CHECK-NEXT: adcl %esi, %eax
; CHECK-NEXT: retq
%s = add i32 %a, %b
%k = icmp ugt i32 %x, %y
diff --git a/llvm/test/CodeGen/X86/apx/adc.ll b/llvm/test/CodeGen/X86/apx/adc.ll
index f40c4c0d7c601..ec9800ddc69ae 100644
--- a/llvm/test/CodeGen/X86/apx/adc.ll
+++ b/llvm/test/CodeGen/X86/apx/adc.ll
@@ -4,9 +4,8 @@
define i8 @adc8rr(i8 %a, i8 %b, i8 %x, i8 %y) nounwind {
; CHECK-LABEL: adc8rr:
; CHECK: # %bb.0:
-; CHECK-NEXT: addb %sil, %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x00,0xf7]
; CHECK-NEXT: cmpb %dl, %cl # encoding: [0x38,0xd1]
-; CHECK-NEXT: adcb $0, %al # EVEX TO LEGACY Compression encoding: [0x14,0x00]
+; CHECK-NEXT: adcb %sil, %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x10,0xf7]
; CHECK-NEXT: retq # encoding: [0xc3]
%s = add i8 %a, %b
%k = icmp ugt i8 %x, %y
@@ -18,9 +17,8 @@ define i8 @adc8rr(i8 %a, i8 %b, i8 %x, i8 %y) nounwind {
define i16 @adc16rr(i16 %a, i16 %b, i16 %x, i16 %y) nounwind {
; CHECK-LABEL: adc16rr:
; CHECK: # %bb.0:
-; CHECK-NEXT: addw %si, %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x01,0xf7]
; CHECK-NEXT: cmpw %dx, %cx # encoding: [0x66,0x39,0xd1]
-; CHECK-NEXT: adcw $0, %ax # EVEX TO LEGACY Compression encoding: [0x66,0x83,0xd0,0x00]
+; CHECK-NEXT: adcw %si, %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x11,0xf7]
; CHECK-NEXT: retq # encoding: [0xc3]
%s = add i16 %a, %b
%k = icmp ugt i16 %x, %y
@@ -32,9 +30,8 @@ define i16 @adc16rr(i16 %a, i16 %b, i16 %x, i16 %y) nounwind {
define i32 @adc32rr(i32 %a, i32 %b, i32 %x, i32 %y) nounwind {
; CHECK-LABEL: adc32rr:
; CHECK: # %bb.0:
-; CHECK-NEXT: leal (%rdi,%rsi), %eax # encoding: [0x8d,0x04,0x37]
; CHECK-NEXT: cmpl %edx, %ecx # encoding: [0x39,0xd1]
-; CHECK-NEXT: adcl $0, %eax # EVEX TO LEGACY Compression encoding: [0x83,0xd0,0x00]
+; CHECK-NEXT: adcl %esi, %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x11,0xf7]
; CHECK-NEXT: retq # encoding: [0xc3]
%s = add i32 %a, %b
%k = icmp ugt i32 %x, %y
@@ -46,9 +43,8 @@ define i32 @adc32rr(i32 %a, i32 %b, i32 %x, i32 %y) nounwind {
define i64 @adc64rr(i64 %a, i64 %b, i64 %x, i64 %y) nounwind {
; CHECK-LABEL: adc64rr:
; CHECK: # %bb.0:
-; CHECK-NEXT: leaq (%rdi,%rsi), %rax # encoding: [0x48,0x8d,0x04,0x37]
; CHECK-NEXT: cmpq %rdx, %rcx # encoding: [0x48,0x39,0xd1]
-; CHECK-NEXT: adcq $0, %rax # EVEX TO LEGACY Compression encoding: [0x48,0x83,0xd0,0x00]
+; CHECK-NEXT: adcq %rsi, %rdi, %rax # encoding: [0x62,0xf4,0xfc,0x18,0x11,0xf7]
; CHECK-NEXT: retq # encoding: [0xc3]
%s = add i64 %a, %b
%k = icmp ugt i64 %x, %y
@@ -60,9 +56,8 @@ define i64 @adc64rr(i64 %a, i64 %b, i64 %x, i64 %y) nounwind {
define i8 @adc8rm(i8 %a, ptr %ptr, i8 %x, i8 %y) nounwind {
; CHECK-LABEL: adc8rm:
; CHECK: # %bb.0:
-; CHECK-NEXT: addb (%rsi), %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x02,0x3e]
; CHECK-NEXT: cmpb %dl, %cl # encoding: [0x38,0xd1]
-; CHECK-NEXT: adcb $0, %al # EVEX TO LEGACY Compression encoding: [0x14,0x00]
+; CHECK-NEXT: adcb (%rsi), %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x12,0x3e]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i8, ptr %ptr
%s = add i8 %a, %b
@@ -75,9 +70,8 @@ define i8 @adc8rm(i8 %a, ptr %ptr, i8 %x, i8 %y) nounwind {
define i16 @adc16rm(i16 %a, ptr %ptr, i16 %x, i16 %y) nounwind {
; CHECK-LABEL: adc16rm:
; CHECK: # %bb.0:
-; CHECK-NEXT: addw (%rsi), %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x03,0x3e]
; CHECK-NEXT: cmpw %dx, %cx # encoding: [0x66,0x39,0xd1]
-; CHECK-NEXT: adcw $0, %ax # EVEX TO LEGACY Compression encoding: [0x66,0x83,0xd0,0x00]
+; CHECK-NEXT: adcw (%rsi), %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x13,0x3e]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i16, ptr %ptr
%s = add i16 %a, %b
@@ -90,9 +84,8 @@ define i16 @adc16rm(i16 %a, ptr %ptr, i16 %x, i16 %y) nounwind {
define i32 @adc32rm(i32 %a, ptr %ptr, i32 %x, i32 %y) nounwind {
; CHECK-LABEL: adc32rm:
; CHECK: # %bb.0:
-; CHECK-NEXT: addl (%rsi), %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x03,0x3e]
; CHECK-NEXT: cmpl %edx, %ecx # encoding: [0x39,0xd1]
-; CHECK-NEXT: adcl $0, %eax # EVEX TO LEGACY Compression encoding: [0x83,0xd0,0x00]
+; CHECK-NEXT: adcl (%rsi), %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x13,0x3e]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i32, ptr %ptr
%s = add i32 %a, %b
@@ -105,9 +98,8 @@ define i32 @adc32rm(i32 %a, ptr %ptr, i32 %x, i32 %y) nounwind {
define i64 @adc64rm(i64 %a, ptr %ptr, i64 %x, i64 %y) nounwind {
; CHECK-LABEL: adc64rm:
; CHECK: # %bb.0:
-; CHECK-NEXT: addq (%rsi), %rdi, %rax # encoding: [0x62,0xf4,0xfc,0x18,0x03,0x3e]
; CHECK-NEXT: cmpq %rdx, %rcx # encoding: [0x48,0x39,0xd1]
-; CHECK-NEXT: adcq $0, %rax # EVEX TO LEGACY Compression encoding: [0x48,0x83,0xd0,0x00]
+; CHECK-NEXT: adcq (%rsi), %rdi, %rax # encoding: [0x62,0xf4,0xfc,0x18,0x13,0x3e]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i64, ptr %ptr
%s = add i64 %a, %b
@@ -214,9 +206,8 @@ define i64 @adc64ri(i64 %a, i64 %x, i64 %y) nounwind {
define i8 @adc8mr(i8 %a, ptr %ptr, i8 %x, i8 %y) nounwind {
; CHECK-LABEL: adc8mr:
; CHECK: # %bb.0:
-; CHECK-NEXT: addb (%rsi), %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x02,0x3e]
; CHECK-NEXT: cmpb %dl, %cl # encoding: [0x38,0xd1]
-; CHECK-NEXT: adcb $0, %al # EVEX TO LEGACY Compression encoding: [0x14,0x00]
+; CHECK-NEXT: adcb (%rsi), %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x12,0x3e]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i8, ptr %ptr
%s = add i8 %b, %a
@@ -229,9 +220,8 @@ define i8 @adc8mr(i8 %a, ptr %ptr, i8 %x, i8 %y) nounwind {
define i16 @adc16mr(i16 %a, ptr %ptr, i16 %x, i16 %y) nounwind {
; CHECK-LABEL: adc16mr:
; CHECK: # %bb.0:
-; CHECK-NEXT: addw (%rsi), %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x03,0x3e]
; CHECK-NEXT: cmpw %dx, %cx # encoding: [0x66,0x39,0xd1]
-; CHECK-NEXT: adcw $0, %ax # EVEX TO LEGACY Compression encoding: [0x66,0x83,0xd0,0x00]
+; CHECK-NEXT: adcw (%rsi), %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x13,0x3e]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i16, ptr %ptr
%s = add i16 %b, %a
@@ -244,9 +234,8 @@ define i16 @adc16mr(i16 %a, ptr %ptr, i16 %x, i16 %y) nounwind {
define i32 @adc32mr(i32 %a, ptr %ptr, i32 %x, i32 %y) nounwind {
; CHECK-LABEL: adc32mr:
; CHECK: # %bb.0:
-; CHECK-NEXT: addl (%rsi), %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x03,0x3e]
; CHECK-NEXT: cmpl %edx, %ecx # encoding: [0x39,0xd1]
-; CHECK-NEXT: adcl $0, %eax # EVEX TO LEGACY Compression encoding: [0x83,0xd0,0x00]
+; CHECK-NEXT: adcl (%rsi), %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x13,0x3e]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i32, ptr %ptr
%s = add i32 %b, %a
@@ -259,9 +248,8 @@ define i32 @adc32mr(i32 %a, ptr %ptr, i32 %x, i32 %y) nounwind {
define i64 @adc64mr(i64 %a, ptr %ptr, i64 %x, i64 %y) nounwind {
; CHECK-LABEL: adc64mr:
; CHECK: # %bb.0:
-; CHECK-NEXT: addq (%rsi), %rdi, %rax # encoding: [0x62,0xf4,0xfc,0x18,0x03,0x3e]
; CHECK-NEXT: cmpq %rdx, %rcx # encoding: [0x48,0x39,0xd1]
-; CHECK-NEXT: adcq $0, %rax # EVEX TO LEGACY Compression encoding: [0x48,0x83,0xd0,0x00]
+; CHECK-NEXT: adcq (%rsi), %rdi, %rax # encoding: [0x62,0xf4,0xfc,0x18,0x13,0x3e]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i64, ptr %ptr
%s = add i64 %b, %a
@@ -375,10 +363,8 @@ define i64 @adc64mi(ptr %ptr, i64 %x, i64 %y) nounwind {
define void @adc8mr_legacy(i8 %a, ptr %ptr, i8 %x, i8 %y) nounwind {
; CHECK-LABEL: adc8mr_legacy:
; CHECK: # %bb.0:
-; CHECK-NEXT: addb (%rsi), %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x02,0x3e]
; CHECK-NEXT: cmpb %dl, %cl # encoding: [0x38,0xd1]
-; CHECK-NEXT: adcb $0, %al # EVEX TO LEGACY Compression encoding: [0x14,0x00]
-; CHECK-NEXT: movb %al, (%rsi) # encoding: [0x88,0x06]
+; CHECK-NEXT: adcb %dil, (%rsi) # encoding: [0x40,0x10,0x3e]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i8, ptr %ptr
%s = add i8 %b, %a
@@ -392,10 +378,8 @@ define void @adc8mr_legacy(i8 %a, ptr %ptr, i8 %x, i8 %y) nounwind {
define void @adc16mr_legacy(i16 %a, ptr %ptr, i16 %x, i16 %y) nounwind {
; CHECK-LABEL: adc16mr_legacy:
; CHECK: # %bb.0:
-; CHECK-NEXT: addw (%rsi), %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x03,0x3e]
; CHECK-NEXT: cmpw %dx, %cx # encoding: [0x66,0x39,0xd1]
-; CHECK-NEXT: adcw $0, %ax # EVEX TO LEGACY Compression encoding: [0x66,0x83,0xd0,0x00]
-; CHECK-NEXT: movw %ax, (%rsi) # encoding: [0x66,0x89,0x06]
+; CHECK-NEXT: adcw %di, (%rsi) # encoding: [0x66,0x11,0x3e]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i16, ptr %ptr
%s = add i16 %b, %a
@@ -409,10 +393,8 @@ define void @adc16mr_legacy(i16 %a, ptr %ptr, i16 %x, i16 %y) nounwind {
define void @adc32mr_legacy(i32 %a, ptr %ptr, i32 %x, i32 %y) nounwind {
; CHECK-LABEL: adc32mr_legacy:
; CHECK: # %bb.0:
-; CHECK-NEXT: addl (%rsi), %edi # EVEX TO LEGACY Compression encoding: [0x03,0x3e]
; CHECK-NEXT: cmpl %edx, %ecx # encoding: [0x39,0xd1]
-; CHECK-NEXT: adcl $0, %edi # EVEX TO LEGACY Compression encoding: [0x83,0xd7,0x00]
-; CHECK-NEXT: movl %edi, (%rsi) # encoding: [0x89,0x3e]
+; CHECK-NEXT: adcl %edi, (%rsi) # encoding: [0x11,0x3e]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i32, ptr %ptr
%s = add i32 %b, %a
@@ -426,10 +408,8 @@ define void @adc32mr_legacy(i32 %a, ptr %ptr, i32 %x, i32 %y) nounwind {
define void @adc64mr_legacy(i64 %a, ptr %ptr, i64 %x, i64 %y) nounwind {
; CHECK-LABEL: adc64mr_legacy:
; CHECK: # %bb.0:
-; CHECK-NEXT: addq (%rsi), %rdi # EVEX TO LEGACY Compression encoding: [0x48,0x03,0x3e]
; CHECK-NEXT: cmpq %rdx, %rcx # encoding: [0x48,0x39,0xd1]
-; CHECK-NEXT: adcq $0, %rdi # EVEX TO LEGACY Compression encoding: [0x48,0x83,0xd7,0x00]
-; CHECK-NEXT: movq %rdi, (%rsi) # encoding: [0x48,0x89,0x3e]
+; CHECK-NEXT: adcq %rdi, (%rsi) # encoding: [0x48,0x11,0x3e]
; CHECK-NEXT: retq # encoding: [0xc3]
%b = load i64, ptr %ptr
%s = add i64 %b, %a
diff --git a/llvm/test/CodeGen/X86/large-code-model-sext-small-symbol.ll b/llvm/test/CodeGen/X86/large-code-model-sext-small-symbol.ll
index d3d9737f24c86..0a4b3d3cff903 100644
--- a/llvm/test/CodeGen/X86/large-code-model-sext-small-symbol.ll
+++ b/llvm/test/CodeGen/X86/large-code-model-sext-small-symbol.ll
@@ -17,9 +17,8 @@ define ptr @f(i64 %0) {
; CHECK-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L0$pb, %rcx
; CHECK-NEXT: addq %rax, %rcx
; CHECK-NEXT: movabsq $g at GOTOFF, %rax
-; CHECK-NEXT: addq %rcx, %rax
; CHECK-NEXT: cmpq $1, %rdi
-; CHECK-NEXT: adcq $0, %rax
+; CHECK-NEXT: adcq %rcx, %rax
; CHECK-NEXT: retq
%2 = icmp eq i64 %0, 0
%3 = zext i1 %2 to i64
>From c9215c3c7ae30d2b7e243e64eb8417c8868ac2ab Mon Sep 17 00:00:00 2001
From: Chauhan Jaydeep Ashwinbhai <chauhan.jaydeep.ashwinbhai at intel.com>
Date: Wed, 11 Feb 2026 06:48:44 -0800
Subject: [PATCH 08/13] Added combine and updated testcase
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 11 +++++++++++
llvm/test/CodeGen/X86/combine-add.ll | 3 +--
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 9c6cc95cc5eac..ed840f649037d 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -58807,6 +58807,17 @@ static SDValue combineX86AddSub(SDNode *N, SelectionDAG &DAG,
}
}
+ // Fold ADD(ADC(Y, C1, CF), C2) -> ADC(Y, C1 + C2, CF)
+ if (!IsSub && LHS.getOpcode() == X86ISD::ADC && LHS.hasOneUse() &&
+ isa<ConstantSDNode>(LHS.getOperand(1)) && isa<ConstantSDNode>(RHS) &&
+ !needCarryOrOverflowFlag(SDValue(N, 1))) {
+ auto *C1 = cast<ConstantSDNode>(LHS.getOperand(1));
+ auto *C2 = cast<ConstantSDNode>(RHS);
+ 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));
+ }
+
// 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,
diff --git a/llvm/test/CodeGen/X86/combine-add.ll b/llvm/test/CodeGen/X86/combine-add.ll
index b9e7a54075677..80ee046d74c62 100644
--- a/llvm/test/CodeGen/X86/combine-add.ll
+++ b/llvm/test/CodeGen/X86/combine-add.ll
@@ -568,8 +568,7 @@ define i32 @add_adc_to_adc(i32 %0, i32 %1, i32 %2) {
; CHECK: # %bb.0:
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: cmpl %esi, %edi
-; CHECK-NEXT: adcl $0, %edx
-; CHECK-NEXT: addl $42, %edx
+; CHECK-NEXT: adcl $42, %edx
; CHECK-NEXT: cmovsl %esi, %eax
; CHECK-NEXT: retq
%4 = icmp ult i32 %0, %1
>From 16de72bf820f9a7dcc4d779f97ebcd747a0cedee Mon Sep 17 00:00:00 2001
From: Chauhan Jaydeep Ashwinbhai <chauhan.jaydeep.ashwinbhai at intel.com>
Date: Fri, 13 Feb 2026 07:12:18 -0800
Subject: [PATCH 09/13] Addressed the review comments3
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 16 ++++++++++------
llvm/test/CodeGen/X86/combine-adc.ll | 8 ++++----
llvm/test/CodeGen/X86/combine-add.ll | 24 +++++++++++++++++++++---
3 files changed, 35 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 7c48b33fba84b..d818f03a6c852 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -58809,15 +58809,19 @@ static SDValue combineX86AddSub(SDNode *N, SelectionDAG &DAG,
}
}
- // Fold ADD(ADC(Y, C1, CF), C2) -> ADC(Y, C1 + C2, CF)
+ // Fold ADD(ADC(Y, A, CF), B) -> ADC(Y, ADD(A, B), CF)
if (!IsSub && LHS.getOpcode() == X86ISD::ADC && LHS.hasOneUse() &&
- isa<ConstantSDNode>(LHS.getOperand(1)) && isa<ConstantSDNode>(RHS) &&
!needCarryOrOverflowFlag(SDValue(N, 1))) {
- auto *C1 = cast<ConstantSDNode>(LHS.getOperand(1));
- auto *C2 = cast<ConstantSDNode>(RHS);
- APInt Sum = C1->getAPIntValue() + C2->getAPIntValue();
+ SDValue A = LHS.getOperand(1);
+ SDValue B = RHS;
+ EVT VT = A.getValueType();
+
+ if (B.getValueType() != VT)
+ return SDValue();
+
+ SDValue NewAdd = DAG.getNode(ISD::ADD, DL, VT, A, B);
return DAG.getNode(X86ISD::ADC, DL, N->getVTList(), LHS.getOperand(0),
- DAG.getConstant(Sum, DL, VT), LHS.getOperand(2));
+ NewAdd, LHS.getOperand(2));
}
// TODO: Can we drop the ZeroSecondOpOnly limit? This is to guarantee that the
diff --git a/llvm/test/CodeGen/X86/combine-adc.ll b/llvm/test/CodeGen/X86/combine-adc.ll
index cb934c8664e45..98996ec3b9930 100644
--- a/llvm/test/CodeGen/X86/combine-adc.ll
+++ b/llvm/test/CodeGen/X86/combine-adc.ll
@@ -213,10 +213,10 @@ define i32 @adc_add_multi_use(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, ptr %5) no
; X86-NEXT: movl {{[0-9]+}}(%esp), %esi
; X86-NEXT: movl {{[0-9]+}}(%esp), %edi
; X86-NEXT: leal (%edi,%esi), %ebx
+; X86-NEXT: addl {{[0-9]+}}(%esp), %esi
; X86-NEXT: cmpl %ecx, %eax
; X86-NEXT: movl %ebx, (%edx)
-; X86-NEXT: adcl %esi, %edi
-; X86-NEXT: addl {{[0-9]+}}(%esp), %edi
+; X86-NEXT: adcl %edi, %esi
; X86-NEXT: js .LBB6_2
; X86-NEXT: # %bb.1:
; X86-NEXT: movl %ecx, %eax
@@ -232,10 +232,10 @@ define i32 @adc_add_multi_use(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, ptr %5) no
; X64-NEXT: # kill: def $edx killed $edx def $rdx
; X64-NEXT: movl %esi, %eax
; X64-NEXT: leal (%rcx,%rdx), %esi
+; X64-NEXT: addl %edx, %r8d
; X64-NEXT: cmpl %eax, %edi
; X64-NEXT: movl %esi, (%r9)
-; X64-NEXT: adcl %edx, %ecx
-; X64-NEXT: addl %r8d, %ecx
+; X64-NEXT: adcl %ecx, %r8d
; X64-NEXT: cmovsl %edi, %eax
; X64-NEXT: retq
%7 = icmp ult i32 %0, %1
diff --git a/llvm/test/CodeGen/X86/combine-add.ll b/llvm/test/CodeGen/X86/combine-add.ll
index 80ee046d74c62..5efc8cd111d1f 100644
--- a/llvm/test/CodeGen/X86/combine-add.ll
+++ b/llvm/test/CodeGen/X86/combine-add.ll
@@ -563,7 +563,7 @@ define i64 @add_notx_x(i64 %v0) nounwind {
}
; Basic positive test
-define i32 @add_adc_to_adc(i32 %0, i32 %1, i32 %2) {
+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
@@ -580,8 +580,26 @@ define i32 @add_adc_to_adc(i32 %0, i32 %1, i32 %2) {
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) {
+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
@@ -601,7 +619,7 @@ define i32 @add_adc_wrong_flags(i32 %0, i32 %1, i32 %2) {
}
; Negative test: Multi-use
-define i32 @add_adc_multi_use(i32 %0, i32 %1, i32 %2) {
+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
>From a7db36bc6f919102e12a9bf4df92298637c4ba1a Mon Sep 17 00:00:00 2001
From: Chauhan Jaydeep Ashwinbhai <chauhan.jaydeep.ashwinbhai at intel.com>
Date: Sat, 28 Feb 2026 00:44:05 -0800
Subject: [PATCH 10/13] Addressed the review comments4
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 31 ++++++++++++++++++-------
llvm/test/CodeGen/X86/combine-adc.ll | 8 +++----
2 files changed, 26 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index c3adae4287840..75ab829816056 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -58896,19 +58896,32 @@ static SDValue combineX86AddSub(SDNode *N, SelectionDAG &DAG,
}
}
- // Fold ADD(ADC(Y, A, CF), B) -> ADC(Y, ADD(A, B), CF)
+ // Fold ADD(ADC(Y, C1, CF), C2) -> ADC(Y, C1 + C2, CF) and
+ // ADD(ADC(Y, 0, CF), X) -> ADC(Y, X, CF) and
+ // ADD(ADC(Y, X, CF), 0) -> ADC(Y, X, CF)
if (!IsSub && LHS.getOpcode() == X86ISD::ADC && LHS.hasOneUse() &&
!needCarryOrOverflowFlag(SDValue(N, 1))) {
- SDValue A = LHS.getOperand(1);
- SDValue B = RHS;
- EVT VT = A.getValueType();
- if (B.getValueType() != VT)
- return SDValue();
+ 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));
+ }
- SDValue NewAdd = DAG.getNode(ISD::ADD, DL, VT, A, B);
- return DAG.getNode(X86ISD::ADC, DL, N->getVTList(), LHS.getOperand(0),
- NewAdd, 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;
+ }
}
// TODO: Can we drop the ZeroSecondOpOnly limit? This is to guarantee that the
diff --git a/llvm/test/CodeGen/X86/combine-adc.ll b/llvm/test/CodeGen/X86/combine-adc.ll
index 98996ec3b9930..cb934c8664e45 100644
--- a/llvm/test/CodeGen/X86/combine-adc.ll
+++ b/llvm/test/CodeGen/X86/combine-adc.ll
@@ -213,10 +213,10 @@ define i32 @adc_add_multi_use(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, ptr %5) no
; X86-NEXT: movl {{[0-9]+}}(%esp), %esi
; X86-NEXT: movl {{[0-9]+}}(%esp), %edi
; X86-NEXT: leal (%edi,%esi), %ebx
-; X86-NEXT: addl {{[0-9]+}}(%esp), %esi
; X86-NEXT: cmpl %ecx, %eax
; X86-NEXT: movl %ebx, (%edx)
-; X86-NEXT: adcl %edi, %esi
+; X86-NEXT: adcl %esi, %edi
+; X86-NEXT: addl {{[0-9]+}}(%esp), %edi
; X86-NEXT: js .LBB6_2
; X86-NEXT: # %bb.1:
; X86-NEXT: movl %ecx, %eax
@@ -232,10 +232,10 @@ define i32 @adc_add_multi_use(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, ptr %5) no
; X64-NEXT: # kill: def $edx killed $edx def $rdx
; X64-NEXT: movl %esi, %eax
; X64-NEXT: leal (%rcx,%rdx), %esi
-; X64-NEXT: addl %edx, %r8d
; X64-NEXT: cmpl %eax, %edi
; X64-NEXT: movl %esi, (%r9)
-; X64-NEXT: adcl %ecx, %r8d
+; X64-NEXT: adcl %edx, %ecx
+; X64-NEXT: addl %r8d, %ecx
; X64-NEXT: cmovsl %edi, %eax
; X64-NEXT: retq
%7 = icmp ult i32 %0, %1
>From 5d30f179154dbe6ef4617106f8857e900ca756c7 Mon Sep 17 00:00:00 2001
From: Chauhan Jaydeep Ashwinbhai <chauhan.jaydeep.ashwinbhai at intel.com>
Date: Sat, 28 Feb 2026 05:48:19 -0800
Subject: [PATCH 11/13] Addressed the review comments5
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 5 -----
1 file changed, 5 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 75ab829816056..f624c3a310736 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -58917,11 +58917,6 @@ static SDValue combineX86AddSub(SDNode *N, SelectionDAG &DAG,
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;
- }
}
// TODO: Can we drop the ZeroSecondOpOnly limit? This is to guarantee that the
>From 85c825676eef9a957b5047c5860234c83c8e1917 Mon Sep 17 00:00:00 2001
From: Chauhan Jaydeep Ashwinbhai <chauhan.jaydeep.ashwinbhai at intel.com>
Date: Sat, 28 Feb 2026 05:51:55 -0800
Subject: [PATCH 12/13] Addressed the review comments6
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index f624c3a310736..14cec75bf8a47 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -58898,7 +58898,6 @@ 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
- // ADD(ADC(Y, X, CF), 0) -> ADC(Y, X, CF)
if (!IsSub && LHS.getOpcode() == X86ISD::ADC && LHS.hasOneUse() &&
!needCarryOrOverflowFlag(SDValue(N, 1))) {
>From 187c4fdd960b72ddeec5ac89ca6e791376f9d29b Mon Sep 17 00:00:00 2001
From: Chauhan Jaydeep Ashwinbhai <chauhan.jaydeep.ashwinbhai at intel.com>
Date: Sat, 28 Feb 2026 05:55:24 -0800
Subject: [PATCH 13/13] Remove comment
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 14cec75bf8a47..569cf8c4f6665 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -58897,7 +58897,7 @@ 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
+ // ADD(ADC(Y, 0, CF), X) -> ADC(Y, X, CF)
if (!IsSub && LHS.getOpcode() == X86ISD::ADC && LHS.hasOneUse() &&
!needCarryOrOverflowFlag(SDValue(N, 1))) {
More information about the llvm-commits
mailing list