Skip to content

[X86] Optimized ADC + ADD to ADC - #176713

Merged
JaydeepChauhan14 merged 5 commits into
llvm:mainfrom
JaydeepChauhan14:optimizeadcaddwithadc
Feb 9, 2026
Merged

[X86] Optimized ADC + ADD to ADC#176713
JaydeepChauhan14 merged 5 commits into
llvm:mainfrom
JaydeepChauhan14:optimizeadcaddwithadc

Conversation

@JaydeepChauhan14

Copy link
Copy Markdown
Contributor

No description provided.

@JaydeepChauhan14
JaydeepChauhan14 marked this pull request as ready for review January 22, 2026 05:04
@llvmbot

llvmbot commented Jan 22, 2026

Copy link
Copy Markdown
Member

@llvm/pr-subscribers-backend-x86

Author: None (JaydeepChauhan14)

Changes

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

2 Files Affected:

  • (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+6-2)
  • (modified) llvm/test/CodeGen/X86/combine-add.ll (+96)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 640d9c5f5bc07..d0f59fb95eec0 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -58197,7 +58197,11 @@ 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()) {
+    // Only check things that use the flags.
+    if (Use.getResNo() != Flags.getResNo())
+      continue;
+    const SDNode *User = Use.getUser();
     X86::CondCode CC;
     switch (User->getOpcode()) {
     default:
@@ -58541,7 +58545,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))
+      !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/combine-add.ll b/llvm/test/CodeGen/X86/combine-add.ll
index 51a8bf5b48415..7bacb3c495b50 100644
--- a/llvm/test/CodeGen/X86/combine-add.ll
+++ b/llvm/test/CodeGen/X86/combine-add.ll
@@ -561,3 +561,99 @@ define i64 @add_notx_x(i64 %v0) nounwind {
   %y = add i64 %x, %v0
   ret i64 %y
 }
+
+; Basic positive test
+define i32 @add_adc(i32 %0, i32 %1, i32 %2) {
+; CHECK-LABEL: add_adc:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    cmpl %esi, %edi
+; CHECK-NEXT:    adcl %edi, %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, %0
+  %7 = add i32 %6, %5
+  %8 = icmp slt i32 %7, 0
+  %9 = select i1 %8, i32 %1, i32 %0
+  ret i32 %9
+}
+
+; Negative test: Carry or overflow flag is used
+define i32 @add_adc_wrong_flags(i32 %0, i32 %1, i32 %2, i32 %3) {
+; CHECK-LABEL: add_adc_wrong_flags:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    cmpl %esi, %edi
+; CHECK-NEXT:    adcl $0, %edx
+; CHECK-NEXT:    addl %ecx, %edx
+; CHECK-NEXT:    cmovbl %edi, %eax
+; CHECK-NEXT:    retq
+  %5 = icmp ult i32 %0, %1
+  %6 = zext i1 %5 to i32
+  %7 = add i32 %2, %6
+  %8 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %7, i32 %3)
+  %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, i32 %3, ptr %4) {
+; CHECK-LABEL: add_adc_multi_use:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    cmpl %esi, %edi
+; CHECK-NEXT:    adcl $0, %edx
+; CHECK-NEXT:    movl %edx, (%r8)
+; CHECK-NEXT:    addl %ecx, %edx
+; CHECK-NEXT:    cmovsl %edi, %eax
+; CHECK-NEXT:    retq
+  %6 = icmp ult i32 %0, %1
+  %7 = zext i1 %6 to i32
+  %8 = add i32 %2, %7
+  store i32 %8, ptr %4, align 4
+  %9 = add i32 %8, %3
+  %10 = icmp slt i32 %9, 0
+  %11 = select i1 %10, i32 %0, i32 %1
+  ret i32 %11
+}
+
+; Positive test: Both adc operands are constants
+define i32 @add_adc_constants(i32 %0, i32 %1, i32 %2) {
+; CHECK-LABEL: add_adc_constants:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    cmpl %esi, %edi
+; CHECK-NEXT:    adcl $42, %eax
+; CHECK-NEXT:    addl %edx, %eax
+; CHECK-NEXT:    retq
+  %4 = icmp ult i32 %0, %1
+  %5 = zext i1 %4 to i8
+  %6 = tail call { i8, i32 } @llvm.x86.addcarry.32(i8 %5, i32 0, i32 42)
+  %7 = extractvalue { i8, i32 } %6, 1
+  %8 = add i32 %7, %2
+  ret i32 %8
+}
+
+; Negative test: Multi-use
+define i32 @add_adc_constants_multi_use(i32 %0, i32 %1, i32 %2, ptr %3) {
+; CHECK-LABEL: add_adc_constants_multi_use:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    xorl %esi, %esi
+; CHECK-NEXT:    cmpl %eax, %edi
+; CHECK-NEXT:    adcl $42, %esi
+; CHECK-NEXT:    movl %esi, (%rcx)
+; CHECK-NEXT:    addl %edx, %esi
+; CHECK-NEXT:    cmovsl %edi, %eax
+; CHECK-NEXT:    retq
+  %5 = icmp ult i32 %0, %1
+  %6 = select i1 %5, i32 43, i32 42
+  store i32 %6, ptr %3, align 4
+  %7 = add i32 %6, %2
+  %8 = icmp slt i32 %7, 0
+  %9 = select i1 %8, i32 %0, i32 %1
+  ret i32 %9
+}

@topperc

topperc commented Jan 22, 2026

Copy link
Copy Markdown
Contributor

Can you split the commit into 2 commits within the PR? One that adds tests with the existing codegen, and one that changes X86ISelLowering.cpp and updates the tests to show the new codegen. Then reviewers can review each commit individually within the PR to see how the output changes.

@JaydeepChauhan14

Copy link
Copy Markdown
Contributor Author

Can you split the commit into 2 commits within the PR? One that adds tests with the existing codegen, and one that changes X86ISelLowering.cpp and updates the tests to show the new codegen. Then reviewers can review each commit individually within the PR to see how the output changes.

Sure

@JaydeepChauhan14
JaydeepChauhan14 marked this pull request as draft January 23, 2026 08:26
@topperc

topperc commented Feb 6, 2026

Copy link
Copy Markdown
Contributor

Can you split the commit into 2 commits within the PR? One that adds tests with the existing codegen, and one that changes X86ISelLowering.cpp and updates the tests to show the new codegen. Then reviewers can review each commit individually within the PR to see how the output changes.

Sure

I didn't mean you needed to make a new PR. You can put multiple commits into one PR. The github webview will let reviewers look at each commit individually.

@JaydeepChauhan14
JaydeepChauhan14 marked this pull request as ready for review February 6, 2026 08:23
llvm-sync Bot pushed a commit to arm/arm-toolchain that referenced this pull request Feb 6, 2026

@topperc topperc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

AlexisPerry pushed a commit to llvm-project-tlp/llvm-project that referenced this pull request Feb 6, 2026
@JaydeepChauhan14

Copy link
Copy Markdown
Contributor Author

Ping @RKSimon, @phoebewang

@phoebewang phoebewang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@JaydeepChauhan14

Copy link
Copy Markdown
Contributor Author

Thank you @topperc and @phoebewang

@JaydeepChauhan14
JaydeepChauhan14 merged commit fad32ff into llvm:main Feb 9, 2026
12 checks passed
@JaydeepChauhan14
JaydeepChauhan14 deleted the optimizeadcaddwithadc branch February 9, 2026 06:14
@llvm-ci

llvm-ci commented Feb 9, 2026

Copy link
Copy Markdown

LLVM Buildbot has detected a new failure on builder lldb-aarch64-ubuntu running on linaro-lldb-aarch64-ubuntu while building llvm at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/59/builds/31483

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
PASS: lldb-api :: commands/frame/var/TestFrameVar.py (193 of 2472)
PASS: lldb-api :: commands/help/TestHelp.py (194 of 2472)
PASS: lldb-api :: commands/log/invalid-args/TestInvalidArgsLog.py (195 of 2472)
PASS: lldb-api :: commands/memory/write/TestMemoryWrite.py (196 of 2472)
PASS: lldb-api :: commands/platform/basic/TestPlatformPython.py (197 of 2472)
PASS: lldb-api :: commands/platform/basic/TestPlatformCommand.py (198 of 2472)
PASS: lldb-api :: commands/platform/file/close/TestPlatformFileClose.py (199 of 2472)
PASS: lldb-api :: commands/platform/file/read/TestPlatformFileRead.py (200 of 2472)
PASS: lldb-api :: commands/memory/read/TestMemoryRead.py (201 of 2472)
UNRESOLVED: lldb-api :: commands/gui/spawn-threads/TestGuiSpawnThreads.py (202 of 2472)
******************** TEST 'lldb-api :: commands/gui/spawn-threads/TestGuiSpawnThreads.py' FAILED ********************
Script:
--
/usr/bin/python3.10 /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./lib --env LLVM_INCLUDE_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/include --env LLVM_TOOLS_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin --arch aarch64 --build-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex --lldb-module-cache-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/lldb --compiler /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/clang --dsymutil /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin --lldb-obj-root /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/tools/lldb --lldb-libs-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./lib --cmake-build-type Release /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/commands/gui/spawn-threads -p TestGuiSpawnThreads.py
--
Exit Code: 1

Command Output (stdout):
--
lldb version 23.0.0git (https://github.com/llvm/llvm-project.git revision fad32ff3eaf09c140bf441600f7907e8e20af2a2)
  clang revision fad32ff3eaf09c140bf441600f7907e8e20af2a2
  llvm revision fad32ff3eaf09c140bf441600f7907e8e20af2a2
Skipping the following test categories: libc++, msvcstl, dsym, pdb, gmodules, debugserver, objc

--
Command Output (stderr):
--
FAIL: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_gui (TestGuiSpawnThreads.TestGuiSpawnThreadsTest)
======================================================================
ERROR: test_gui (TestGuiSpawnThreads.TestGuiSpawnThreadsTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/packages/Python/lldbsuite/test/decorators.py", line 160, in wrapper
    return func(*args, **kwargs)
  File "/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/commands/gui/spawn-threads/TestGuiSpawnThreads.py", line 44, in test_gui
    self.child.expect_exact(f"thread #{i + 2}: tid =")
  File "/usr/local/lib/python3.10/dist-packages/pexpect/spawnbase.py", line 432, in expect_exact
    return exp.expect_loop(timeout)
  File "/usr/local/lib/python3.10/dist-packages/pexpect/expect.py", line 179, in expect_loop
    return self.eof(e)
  File "/usr/local/lib/python3.10/dist-packages/pexpect/expect.py", line 122, in eof
    raise exc
pexpect.exceptions.EOF: End Of File (EOF). Exception style platform.
<pexpect.pty_spawn.spawn object at 0xe9e207fdc790>
command: /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/lldb
args: ['/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/lldb', '--no-lldbinit', '--no-use-colors', '-O', 'settings clear --all', '-O', 'settings set symbols.enable-external-lookup false', '-O', 'settings set target.inherit-tcc true', '-O', 'settings set target.disable-aslr false', '-O', 'settings set target.detach-on-error false', '-O', 'settings set target.auto-apply-fixits false', '-O', 'settings set plugin.process.gdb-remote.packet-timeout 60', '-O', 'settings set symbols.clang-modules-cache-path "/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api"', '-O', 'settings set use-color false', '-O', 'settings set show-statusline false', '--file', '/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/commands/gui/spawn-threads/TestGuiSpawnThreads.test_gui/a.out']
buffer (last 100 chars): b''
before (last 100 chars): b'thread_create.c:442:8\n#20 0x0000e5ec0ef09e9c ./misc/../sysdeps/unix/sysv/linux/aarch64/clone.S:82:0\n'
after: <class 'pexpect.exceptions.EOF'>

@JaydeepChauhan14

Copy link
Copy Markdown
Contributor Author

LLVM Buildbot has detected a new failure on builder lldb-aarch64-ubuntu running on linaro-lldb-aarch64-ubuntu while building llvm at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/59/builds/31483

Here is the relevant piece of the build log for the reference

It seems it is not related to current PR.

@llvm-ci

llvm-ci commented Feb 9, 2026

Copy link
Copy Markdown

LLVM Buildbot has detected a new failure on builder clang-ppc64le-linux-test-suite running on ppc64le-clang-test-suite while building llvm at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/95/builds/20014

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'SanitizerCommon-msan-powerpc64le-Linux :: Linux/getpwnam_r_invalid_user.cpp' FAILED ********************
Exit Code: -6

Command Output (stdout):
--
# RUN: at line 2
/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/build/./bin/clang  --driver-mode=g++ -gline-tables-only -fsanitize=memory  -m64 -fno-function-sections -funwind-tables  -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/compiler-rt/test -ldl -O0 -g /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cpp -o /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/build/runtimes/runtimes-bins/compiler-rt/test/sanitizer_common/msan-powerpc64le-Linux/Linux/Output/getpwnam_r_invalid_user.cpp.tmp &&  /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/build/runtimes/runtimes-bins/compiler-rt/test/sanitizer_common/msan-powerpc64le-Linux/Linux/Output/getpwnam_r_invalid_user.cpp.tmp
# executed command: /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/build/./bin/clang --driver-mode=g++ -gline-tables-only -fsanitize=memory -m64 -fno-function-sections -funwind-tables -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/compiler-rt/test -ldl -O0 -g /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cpp -o /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/build/runtimes/runtimes-bins/compiler-rt/test/sanitizer_common/msan-powerpc64le-Linux/Linux/Output/getpwnam_r_invalid_user.cpp.tmp
# executed command: /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/build/runtimes/runtimes-bins/compiler-rt/test/sanitizer_common/msan-powerpc64le-Linux/Linux/Output/getpwnam_r_invalid_user.cpp.tmp
# .---command stderr------------
# | Result: 110
# | getpwnam_r_invalid_user.cpp.tmp: /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cpp:19: int main(): Assertion `res == 0 || res == ENOENT' failed.
# `-----------------------------
# error: command failed with exit status: -6

--

********************


rishabhmadan19 pushed a commit to rishabhmadan19/llvm-project that referenced this pull request Feb 9, 2026
rishabhmadan19 pushed a commit to rishabhmadan19/llvm-project that referenced this pull request Feb 9, 2026
markrvmurray pushed a commit to markrvmurray/llvm-mc6809 that referenced this pull request Jun 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants