[llvm] [X86] Let RegAllocFast lower tied operands (PR #228968)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 4 20:24:26 PDT 2026


https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/228968

... so the -O0 pipeline no longer runs TwoAddressInstructionPass.
Follow-ups will enable this for all targets that don't insert passes
with the TwoAddressInstructinPassID anchor.

https://llvm-compile-time-tracker.com/compare.php?from=8ad6c581709df648a2a1e468031a81106a7e00b4&to=33ea7b07c99b9a37f72409029867c50bd1d22a52&stat=instructions:u
-O0 -g, instructions:u geomean: -0.83% (stage1) and -0.85% (stage2).

In a llvm-test-suite build, 2088 of 2563 executables have identical
.text, while 400 have few instructions in total (-0.008%). None gained
extra instructions.

With -O2 -mllvm -regalloc=fast, .text shrinks by 0.12% but the
instruction count grows by 0.09%: RegAllocFast does not convert to
three-address form, so where a tied source stays live,
`leaq 1(%rsi), %rax` becomes `movq %rsi, %rax; incq %rax`.

Test updates:

* O0-pipeline.ll, llc-pipeline-npm.ll: TwoAddressInstructionPass is
  gone.
* 2011-06-12-FastAllocSpill.ll: with no two-address copies,
  RegAllocFast's "copies coalesced" statistic is no longer printed;
  check another statistic.
* switch.ll: the range check now computes in $edi, the argument
  register, saving one move.
* atomic-unordered.ll: rmw_fold_srem1 saves one move. In
  rmw_fold_sdiv1, the loaded value now goes straight into $rax (imulq's
  implicit operand) and is spilled across the imulq, replacing two
  register moves.

>From cf44383e514eb615584b6033af29aaeaca96a623 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Mon, 21 Sep 2026 22:43:23 -0700
Subject: [PATCH] [X86] Let RegAllocFast lower tied operands

... so the -O0 pipeline no longer runs TwoAddressInstructionPass.
Follow-ups will enable this for all targets that don't insert passes
with the TwoAddressInstructinPassID anchor.

https://llvm-compile-time-tracker.com/compare.php?from=8ad6c581709df648a2a1e468031a81106a7e00b4&to=33ea7b07c99b9a37f72409029867c50bd1d22a52&stat=instructions:u
-O0 -g, instructions:u geomean: -0.83% (stage1) and -0.85% (stage2).

In a llvm-test-suite build, 2088 of 2563 executables have identical
.text, while 400 have few instructions in total (-0.008%). None gained
extra instructions.

With -O2 -mllvm -regalloc=fast, .text shrinks by 0.12% but the
instruction count grows by 0.09%: RegAllocFast does not convert to
three-address form, so where a tied source stays live,
`leaq 1(%rsi), %rax` becomes `movq %rsi, %rax; incq %rax`.

Test updates:

* O0-pipeline.ll, llc-pipeline-npm.ll: TwoAddressInstructionPass is
  gone.
* 2011-06-12-FastAllocSpill.ll: with no two-address copies,
  RegAllocFast's "copies coalesced" statistic is no longer printed;
  check another statistic.
* switch.ll: the range check now computes in $edi, the argument
  register, saving one move.
* atomic-unordered.ll: rmw_fold_srem1 saves one move. In
  rmw_fold_sdiv1, the loaded value now goes straight into $rax (imulq's
  implicit operand) and is spilled across the imulq, replacing two
  register moves.
---
 llvm/lib/Target/X86/X86TargetMachine.cpp      |  2 ++
 .../CodeGen/X86/2011-06-12-FastAllocSpill.ll  |  2 +-
 llvm/test/CodeGen/X86/O0-pipeline.ll          |  9 ------
 llvm/test/CodeGen/X86/atomic-unordered.ll     | 31 +++++++++----------
 llvm/test/CodeGen/X86/llc-pipeline-npm.ll     |  2 --
 llvm/test/CodeGen/X86/switch.ll               | 19 +++++-------
 6 files changed, 26 insertions(+), 39 deletions(-)

diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp
index 72dab51b67ece..0866df6ab85ec 100644
--- a/llvm/lib/Target/X86/X86TargetMachine.cpp
+++ b/llvm/lib/Target/X86/X86TargetMachine.cpp
@@ -209,6 +209,8 @@ X86TargetMachine::X86TargetMachine(const Target &T, const Triple &TT,
   // x86 supports the debug entry values.
   setSupportsDebugEntryValues(true);
 
+  setEnableTiedFastRegAlloc(true);
+
   initAsmInfo();
 }
 
diff --git a/llvm/test/CodeGen/X86/2011-06-12-FastAllocSpill.ll b/llvm/test/CodeGen/X86/2011-06-12-FastAllocSpill.ll
index 650cc0a77c7ae..868de7ba9c06a 100644
--- a/llvm/test/CodeGen/X86/2011-06-12-FastAllocSpill.ll
+++ b/llvm/test/CodeGen/X86/2011-06-12-FastAllocSpill.ll
@@ -3,7 +3,7 @@
 ;
 ; This test should not cause any spilling with RAFast.
 ;
-; CHECK: Number of copies coalesced
+; CHECK: Number of machine instrs printed
 ; CHECK-NOT: Number of stores added
 ;
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
diff --git a/llvm/test/CodeGen/X86/O0-pipeline.ll b/llvm/test/CodeGen/X86/O0-pipeline.ll
index f722c37dbc198..479b8825ce7b3 100644
--- a/llvm/test/CodeGen/X86/O0-pipeline.ll
+++ b/llvm/test/CodeGen/X86/O0-pipeline.ll
@@ -2,17 +2,9 @@
 ; pass. Ignore it with 'grep -v'.
 ; RUN: llc -mtriple=x86_64-- -O0 -debug-pass=Structure < %s -o /dev/null 2>&1 \
 ; RUN:   | grep -v 'Verify generated machine code' | FileCheck %s
-; RUN: llc -mtriple=x86_64-- -O0 -debug-pass=Structure -regalloc-fast-tied < %s -o /dev/null 2>&1 \
-; RUN:   | FileCheck %s --check-prefix=TIED
 
 ; REQUIRES: asserts
 
-; The fast register allocator lowers tied operands itself, so
-; TwoAddressInstructionPass drops out while PHIElimination stays.
-; TIED: Eliminate PHI nodes for register allocation
-; TIED-NOT: Two-Address instruction pass
-; TIED: Fast Register Allocator
-
 ; CHECK-LABEL: Pass Arguments:
 ; CHECK-NEXT: Target Library Information
 ; CHECK-NEXT: Runtime Library Function Analysis
@@ -56,7 +48,6 @@
 ; CHECK-NEXT:       X86 DynAlloca Expander
 ; CHECK-NEXT:       Fast Tile Register Preconfigure
 ; CHECK-NEXT:       Eliminate PHI nodes for register allocation
-; CHECK-NEXT:       Two-Address instruction pass
 ; CHECK-NEXT:       Fast Register Allocator
 ; CHECK-NEXT:       Fast Tile Register Configure
 ; CHECK-NEXT:       X86 Lower Tile Copy
diff --git a/llvm/test/CodeGen/X86/atomic-unordered.ll b/llvm/test/CodeGen/X86/atomic-unordered.ll
index d309cdf149bc9..480ed35ec4661 100644
--- a/llvm/test/CodeGen/X86/atomic-unordered.ll
+++ b/llvm/test/CodeGen/X86/atomic-unordered.ll
@@ -1422,17 +1422,17 @@ define void @rmw_fold_mul2(ptr %p, i64 %v) {
 define void @rmw_fold_sdiv1(ptr %p, i64 %v) {
 ; CHECK-O0-LABEL: rmw_fold_sdiv1:
 ; CHECK-O0:       # %bb.0:
-; CHECK-O0-NEXT:    movq (%rdi), %rcx
-; CHECK-O0-NEXT:    movabsq $-8608480567731124087, %rdx # imm = 0x8888888888888889
-; CHECK-O0-NEXT:    movq %rcx, %rax
-; CHECK-O0-NEXT:    imulq %rdx
+; CHECK-O0-NEXT:    movq (%rdi), %rax
+; CHECK-O0-NEXT:    movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-O0-NEXT:    movabsq $-8608480567731124087, %rcx # imm = 0x8888888888888889
+; CHECK-O0-NEXT:    imulq %rcx
+; CHECK-O0-NEXT:    movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload
+; CHECK-O0-NEXT:    addq %rax, %rdx
 ; CHECK-O0-NEXT:    movq %rdx, %rax
-; CHECK-O0-NEXT:    addq %rcx, %rax
-; CHECK-O0-NEXT:    movq %rax, %rcx
-; CHECK-O0-NEXT:    shrq $63, %rcx
-; CHECK-O0-NEXT:    sarq $3, %rax
-; CHECK-O0-NEXT:    addq %rcx, %rax
-; CHECK-O0-NEXT:    movq %rax, (%rdi)
+; CHECK-O0-NEXT:    shrq $63, %rax
+; CHECK-O0-NEXT:    sarq $3, %rdx
+; CHECK-O0-NEXT:    addq %rax, %rdx
+; CHECK-O0-NEXT:    movq %rdx, (%rdi)
 ; CHECK-O0-NEXT:    retq
 ;
 ; CHECK-O3-LABEL: rmw_fold_sdiv1:
@@ -1550,13 +1550,12 @@ define void @rmw_fold_srem1(ptr %p, i64 %v) {
 ; CHECK-O0-NEXT:    movabsq $-8608480567731124087, %rcx # imm = 0x8888888888888889
 ; CHECK-O0-NEXT:    imulq %rcx
 ; CHECK-O0-NEXT:    movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload
+; CHECK-O0-NEXT:    addq %rax, %rdx
 ; CHECK-O0-NEXT:    movq %rdx, %rcx
-; CHECK-O0-NEXT:    addq %rax, %rcx
-; CHECK-O0-NEXT:    movq %rcx, %rdx
-; CHECK-O0-NEXT:    shrq $63, %rdx
-; CHECK-O0-NEXT:    sarq $3, %rcx
-; CHECK-O0-NEXT:    addq %rdx, %rcx
-; CHECK-O0-NEXT:    leaq (%rcx,%rcx,4), %rcx
+; CHECK-O0-NEXT:    shrq $63, %rcx
+; CHECK-O0-NEXT:    sarq $3, %rdx
+; CHECK-O0-NEXT:    addq %rcx, %rdx
+; CHECK-O0-NEXT:    leaq (%rdx,%rdx,4), %rcx
 ; CHECK-O0-NEXT:    leaq (%rcx,%rcx,2), %rcx
 ; CHECK-O0-NEXT:    subq %rcx, %rax
 ; CHECK-O0-NEXT:    movq %rax, (%rdi)
diff --git a/llvm/test/CodeGen/X86/llc-pipeline-npm.ll b/llvm/test/CodeGen/X86/llc-pipeline-npm.ll
index d02b6e9ff4c9f..bc131357f6419 100644
--- a/llvm/test/CodeGen/X86/llc-pipeline-npm.ll
+++ b/llvm/test/CodeGen/X86/llc-pipeline-npm.ll
@@ -49,7 +49,6 @@
 ; O0-NEXT:     x86-dyn-alloca-expander
 ; O0-NEXT:     x86-fast-pre-tile-config
 ; O0-NEXT:     phi-node-elimination
-; O0-NEXT:     two-address-instruction
 ; O0-NEXT:     regallocfast
 ; O0-NEXT:     x86-lower-tile-copy
 ; O0-NEXT:     x86-fp-stackifier
@@ -252,7 +251,6 @@
 ; O0-WINDOWS-NEXT:     x86-dyn-alloca-expander
 ; O0-WINDOWS-NEXT:     x86-fast-pre-tile-config
 ; O0-WINDOWS-NEXT:     phi-node-elimination
-; O0-WINDOWS-NEXT:     two-address-instruction
 ; O0-WINDOWS-NEXT:     regallocfast
 ; O0-WINDOWS-NEXT:     x86-lower-tile-copy
 ; O0-WINDOWS-NEXT:     x86-fp-stackifier
diff --git a/llvm/test/CodeGen/X86/switch.ll b/llvm/test/CodeGen/X86/switch.ll
index c75819c2fd2c5..2489e9123d46d 100644
--- a/llvm/test/CodeGen/X86/switch.ll
+++ b/llvm/test/CodeGen/X86/switch.ll
@@ -27,11 +27,10 @@ define void @basic(i32 %x) {
 ; NOOPT:       # %bb.0: # %entry
 ; NOOPT-NEXT:    pushq %rax
 ; NOOPT-NEXT:    .cfi_def_cfa_offset 16
+; NOOPT-NEXT:    decl %edi
 ; NOOPT-NEXT:    movl %edi, %eax
-; NOOPT-NEXT:    decl %eax
-; NOOPT-NEXT:    movl %eax, %ecx
-; NOOPT-NEXT:    movq %rcx, (%rsp) # 8-byte Spill
-; NOOPT-NEXT:    subl $4, %eax
+; NOOPT-NEXT:    movq %rax, (%rsp) # 8-byte Spill
+; NOOPT-NEXT:    subl $4, %edi
 ; NOOPT-NEXT:    ja .LBB0_4
 ; NOOPT-NEXT:  # %bb.5: # %entry
 ; NOOPT-NEXT:    movq (%rsp), %rax # 8-byte Reload
@@ -166,11 +165,10 @@ define void @basic_nojumptable_false(i32 %x) "no-jump-tables"="false" {
 ; NOOPT:       # %bb.0: # %entry
 ; NOOPT-NEXT:    pushq %rax
 ; NOOPT-NEXT:    .cfi_def_cfa_offset 16
+; NOOPT-NEXT:    decl %edi
 ; NOOPT-NEXT:    movl %edi, %eax
-; NOOPT-NEXT:    decl %eax
-; NOOPT-NEXT:    movl %eax, %ecx
-; NOOPT-NEXT:    movq %rcx, (%rsp) # 8-byte Spill
-; NOOPT-NEXT:    subl $4, %eax
+; NOOPT-NEXT:    movq %rax, (%rsp) # 8-byte Spill
+; NOOPT-NEXT:    subl $4, %edi
 ; NOOPT-NEXT:    ja .LBB2_4
 ; NOOPT-NEXT:  # %bb.5: # %entry
 ; NOOPT-NEXT:    movq (%rsp), %rax # 8-byte Reload
@@ -2602,9 +2600,8 @@ define void @range_with_unreachable_fallthrough(i32 %i) {
 ; NOOPT:       # %bb.0: # %entry
 ; NOOPT-NEXT:    pushq %rax
 ; NOOPT-NEXT:    .cfi_def_cfa_offset 16
-; NOOPT-NEXT:    movl %edi, %eax
-; NOOPT-NEXT:    decl %eax
-; NOOPT-NEXT:    subl $3, %eax
+; NOOPT-NEXT:    decl %edi
+; NOOPT-NEXT:    subl $3, %edi
 ; NOOPT-NEXT:    jb .LBB25_1
 ; NOOPT-NEXT:    jmp .LBB25_5
 ; NOOPT-NEXT:  .LBB25_5: # %entry



More information about the llvm-commits mailing list