[llvm] 13a62ae - [X86] Rewrite MOVUPD/MOVAPD to MOVUPS/MOVAPS in X86FixupInstTuning (#217676)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 25 14:46:51 PDT 2026
Author: Wiktor Ludwichowski
Date: 2026-08-25T21:46:45Z
New Revision: 13a62ae24c6f7efb3a34bc9b5bdef576ad809efd
URL: https://github.com/llvm/llvm-project/commit/13a62ae24c6f7efb3a34bc9b5bdef576ad809efd
DIFF: https://github.com/llvm/llvm-project/commit/13a62ae24c6f7efb3a34bc9b5bdef576ad809efd.diff
LOG: [X86] Rewrite MOVUPD/MOVAPD to MOVUPS/MOVAPS in X86FixupInstTuning (#217676)
MOVUPD/MOVUPS and MOVAPD/MOVAPS perform identical 16-byte moves, but the
packed double forms carry a mandatory 0x66 prefix, making them one byte
larger. We rewrite only when no domain delay would happen after this
replacement. VEX/EVEX VMOVUPD/VMOVAPD are deliberately left alone, the
0x66 requirement is folded into the pp field of the prefix, so both
encode to the same size as their packed single versions and there is
nothing to gain.
Added:
llvm/test/CodeGen/X86/inst-tuning-movpd.mir
Modified:
llvm/lib/Target/X86/X86FixupInstTuning.cpp
llvm/test/CodeGen/X86/2011-10-21-widen-cmp.ll
llvm/test/CodeGen/X86/break-false-dep.ll
llvm/test/CodeGen/X86/sink-hoist.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/X86/X86FixupInstTuning.cpp b/llvm/lib/Target/X86/X86FixupInstTuning.cpp
index 621fd35a03cd5..c8b0dbf597223 100644
--- a/llvm/lib/Target/X86/X86FixupInstTuning.cpp
+++ b/llvm/lib/Target/X86/X86FixupInstTuning.cpp
@@ -255,6 +255,19 @@ bool X86FixupInstTuningImpl::processInstruction(
return ProcessUNPCKToIntDomain(NewOpc);
};
+ // MOVUPS/MOVAPS takes 1 less byte of code size. Only replace when
+ // there is no move domain-delay penalty on the target, or -Oz is set.
+ auto ProcessMOVPDToMOVPS = [&](unsigned NewOpc) -> bool {
+ assert(NewOpcPreferable(NewOpc) &&
+ "MOVUPS/MOVAPS should be preferred over MOVUPD/MOVAPD");
+ if (!ST->hasNoDomainDelayMov() && !MF.getFunction().hasMinSize())
+ return false;
+ LLVM_DEBUG(dbgs() << "Replacing: " << MI);
+ MI.setDesc(TII->get(NewOpc));
+ LLVM_DEBUG(dbgs() << " With: " << MI);
+ return true;
+ };
+
// If we're permuting the lower halves of the 256-bit registers, use a
// subvector insertion instead.
auto ProcessVPERM2x128ToVINSERT128 = [&](unsigned InsertOpc) -> bool {
@@ -697,6 +710,18 @@ bool X86FixupInstTuningImpl::processInstruction(
return ProcessShiftLeftToAdd(X86::VPADDQZ256rr);
case X86::VPSLLQZri:
return ProcessShiftLeftToAdd(X86::VPADDQZrr);
+ case X86::MOVUPDrr:
+ return ProcessMOVPDToMOVPS(X86::MOVUPSrr);
+ case X86::MOVUPDrm:
+ return ProcessMOVPDToMOVPS(X86::MOVUPSrm);
+ case X86::MOVUPDmr:
+ return ProcessMOVPDToMOVPS(X86::MOVUPSmr);
+ case X86::MOVAPDrr:
+ return ProcessMOVPDToMOVPS(X86::MOVAPSrr);
+ case X86::MOVAPDrm:
+ return ProcessMOVPDToMOVPS(X86::MOVAPSrm);
+ case X86::MOVAPDmr:
+ return ProcessMOVPDToMOVPS(X86::MOVAPSmr);
default:
return false;
diff --git a/llvm/test/CodeGen/X86/2011-10-21-widen-cmp.ll b/llvm/test/CodeGen/X86/2011-10-21-widen-cmp.ll
index f3f541af4bd13..87ef44a9408c0 100644
--- a/llvm/test/CodeGen/X86/2011-10-21-widen-cmp.ll
+++ b/llvm/test/CodeGen/X86/2011-10-21-widen-cmp.ll
@@ -23,11 +23,11 @@ entry:
define void @cmp_2_doubles(<2 x double> %a, <2 x double> %b, <2 x double> %c) {
; CHECK-LABEL: cmp_2_doubles:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: movapd %xmm0, %xmm3
+; CHECK-NEXT: movaps %xmm0, %xmm3
; CHECK-NEXT: cmpordpd %xmm2, %xmm2
-; CHECK-NEXT: movapd %xmm2, %xmm0
+; CHECK-NEXT: movaps %xmm2, %xmm0
; CHECK-NEXT: blendvpd %xmm0, %xmm3, %xmm1
-; CHECK-NEXT: movapd %xmm1, (%rax)
+; CHECK-NEXT: movaps %xmm1, (%rax)
; CHECK-NEXT: retq
entry:
%0 = fcmp oeq <2 x double> %c, %c
diff --git a/llvm/test/CodeGen/X86/break-false-dep.ll b/llvm/test/CodeGen/X86/break-false-dep.ll
index 6943622fac7f2..38199607ca6fd 100644
--- a/llvm/test/CodeGen/X86/break-false-dep.ll
+++ b/llvm/test/CodeGen/X86/break-false-dep.ll
@@ -1318,7 +1318,7 @@ define dso_local void @loopclearance2(ptr nocapture %y, ptr %x, double %c1, doub
; SSE-LINUX-NEXT: leaq 1(%rax), %r8
; SSE-LINUX-NEXT: xorps %xmm4, %xmm4
; SSE-LINUX-NEXT: cvtsi2sd %r8, %xmm4
-; SSE-LINUX-NEXT: movapd %xmm0, %xmm5
+; SSE-LINUX-NEXT: movaps %xmm0, %xmm5
; SSE-LINUX-NEXT: subsd %xmm4, %xmm5
; SSE-LINUX-NEXT: mulsd %xmm1, %xmm5
; SSE-LINUX-NEXT: leaq -1(%rcx), %r9
@@ -1390,7 +1390,7 @@ define dso_local void @loopclearance2(ptr nocapture %y, ptr %x, double %c1, doub
; SSE-WIN-NEXT: leaq 1(%r8), %r10
; SSE-WIN-NEXT: xorps %xmm4, %xmm4
; SSE-WIN-NEXT: cvtsi2sd %r10, %xmm4
-; SSE-WIN-NEXT: movapd %xmm2, %xmm5
+; SSE-WIN-NEXT: movaps %xmm2, %xmm5
; SSE-WIN-NEXT: subsd %xmm4, %xmm5
; SSE-WIN-NEXT: mulsd %xmm3, %xmm5
; SSE-WIN-NEXT: leaq -1(%r9), %r11
diff --git a/llvm/test/CodeGen/X86/inst-tuning-movpd.mir b/llvm/test/CodeGen/X86/inst-tuning-movpd.mir
new file mode 100644
index 0000000000000..1001d7ebeae5d
--- /dev/null
+++ b/llvm/test/CodeGen/X86/inst-tuning-movpd.mir
@@ -0,0 +1,180 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc %s -mtriple=x86_64-- -mattr=+no-bypass-delay-mov -run-pass=x86-fixup-inst-tuning -o - | FileCheck %s --check-prefixes=CHECK,NODELAY
+# RUN: llc %s -mtriple=x86_64-- -mattr=-no-bypass-delay-mov -run-pass=x86-fixup-inst-tuning -o - | FileCheck %s --check-prefixes=CHECK,DELAY
+
+---
+name: movupd_rr
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $xmm0
+ ; NODELAY-LABEL: name: movupd_rr
+ ; NODELAY: liveins: $xmm0
+ ; NODELAY-NEXT: {{ $}}
+ ; NODELAY-NEXT: renamable $xmm1 = MOVUPSrr killed renamable $xmm0
+ ; NODELAY-NEXT: RET64 implicit $xmm1
+ ;
+ ; DELAY-LABEL: name: movupd_rr
+ ; DELAY: liveins: $xmm0
+ ; DELAY-NEXT: {{ $}}
+ ; DELAY-NEXT: renamable $xmm1 = MOVUPDrr killed renamable $xmm0
+ ; DELAY-NEXT: RET64 implicit $xmm1
+ renamable $xmm1 = MOVUPDrr killed renamable $xmm0
+ RET64 implicit $xmm1
+...
+---
+name: movupd_rm
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $rdi
+ ; NODELAY-LABEL: name: movupd_rm
+ ; NODELAY: liveins: $rdi
+ ; NODELAY-NEXT: {{ $}}
+ ; NODELAY-NEXT: renamable $xmm0 = MOVUPSrm killed renamable $rdi, 1, $noreg, 0, $noreg
+ ; NODELAY-NEXT: RET64 implicit $xmm0
+ ;
+ ; DELAY-LABEL: name: movupd_rm
+ ; DELAY: liveins: $rdi
+ ; DELAY-NEXT: {{ $}}
+ ; DELAY-NEXT: renamable $xmm0 = MOVUPDrm killed renamable $rdi, 1, $noreg, 0, $noreg
+ ; DELAY-NEXT: RET64 implicit $xmm0
+ renamable $xmm0 = MOVUPDrm killed renamable $rdi, 1, $noreg, 0, $noreg
+ RET64 implicit $xmm0
+...
+---
+name: movupd_mr
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $rdi, $xmm0
+ ; NODELAY-LABEL: name: movupd_mr
+ ; NODELAY: liveins: $rdi, $xmm0
+ ; NODELAY-NEXT: {{ $}}
+ ; NODELAY-NEXT: MOVUPSmr killed renamable $rdi, 1, $noreg, 0, $noreg, killed renamable $xmm0
+ ; NODELAY-NEXT: RET64
+ ;
+ ; DELAY-LABEL: name: movupd_mr
+ ; DELAY: liveins: $rdi, $xmm0
+ ; DELAY-NEXT: {{ $}}
+ ; DELAY-NEXT: MOVUPDmr killed renamable $rdi, 1, $noreg, 0, $noreg, killed renamable $xmm0
+ ; DELAY-NEXT: RET64
+ MOVUPDmr killed renamable $rdi, 1, $noreg, 0, $noreg, killed renamable $xmm0
+ RET64
+...
+---
+name: movapd_rr
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $xmm0
+ ; NODELAY-LABEL: name: movapd_rr
+ ; NODELAY: liveins: $xmm0
+ ; NODELAY-NEXT: {{ $}}
+ ; NODELAY-NEXT: renamable $xmm1 = MOVAPSrr killed renamable $xmm0
+ ; NODELAY-NEXT: RET64 implicit $xmm1
+ ;
+ ; DELAY-LABEL: name: movapd_rr
+ ; DELAY: liveins: $xmm0
+ ; DELAY-NEXT: {{ $}}
+ ; DELAY-NEXT: renamable $xmm1 = MOVAPDrr killed renamable $xmm0
+ ; DELAY-NEXT: RET64 implicit $xmm1
+ renamable $xmm1 = MOVAPDrr killed renamable $xmm0
+ RET64 implicit $xmm1
+...
+---
+name: movapd_rm
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $rdi
+ ; NODELAY-LABEL: name: movapd_rm
+ ; NODELAY: liveins: $rdi
+ ; NODELAY-NEXT: {{ $}}
+ ; NODELAY-NEXT: renamable $xmm0 = MOVAPSrm killed renamable $rdi, 1, $noreg, 0, $noreg
+ ; NODELAY-NEXT: RET64 implicit $xmm0
+ ;
+ ; DELAY-LABEL: name: movapd_rm
+ ; DELAY: liveins: $rdi
+ ; DELAY-NEXT: {{ $}}
+ ; DELAY-NEXT: renamable $xmm0 = MOVAPDrm killed renamable $rdi, 1, $noreg, 0, $noreg
+ ; DELAY-NEXT: RET64 implicit $xmm0
+ renamable $xmm0 = MOVAPDrm killed renamable $rdi, 1, $noreg, 0, $noreg
+ RET64 implicit $xmm0
+...
+---
+name: movapd_mr
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $rdi, $xmm0
+ ; NODELAY-LABEL: name: movapd_mr
+ ; NODELAY: liveins: $rdi, $xmm0
+ ; NODELAY-NEXT: {{ $}}
+ ; NODELAY-NEXT: MOVAPSmr killed renamable $rdi, 1, $noreg, 0, $noreg, killed renamable $xmm0
+ ; NODELAY-NEXT: RET64
+ ;
+ ; DELAY-LABEL: name: movapd_mr
+ ; DELAY: liveins: $rdi, $xmm0
+ ; DELAY-NEXT: {{ $}}
+ ; DELAY-NEXT: MOVAPDmr killed renamable $rdi, 1, $noreg, 0, $noreg, killed renamable $xmm0
+ ; DELAY-NEXT: RET64
+ MOVAPDmr killed renamable $rdi, 1, $noreg, 0, $noreg, killed renamable $xmm0
+ RET64
+...
+---
+name: vmovupd_rr
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $xmm0
+ ; CHECK-LABEL: name: vmovupd_rr
+ ; CHECK: liveins: $xmm0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: renamable $xmm1 = VMOVUPDrr killed renamable $xmm0
+ ; CHECK-NEXT: RET64 implicit $xmm1
+ renamable $xmm1 = VMOVUPDrr killed renamable $xmm0
+ RET64 implicit $xmm1
+...
+---
+name: vmovupd_ymm
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $ymm0
+ ; CHECK-LABEL: name: vmovupd_ymm
+ ; CHECK: liveins: $ymm0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: renamable $ymm1 = VMOVUPDYrr killed renamable $ymm0
+ ; CHECK-NEXT: RET64 implicit $ymm1
+ renamable $ymm1 = VMOVUPDYrr killed renamable $ymm0
+ RET64 implicit $ymm1
+...
+---
+name: vmovapd_rr
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $xmm0
+ ; CHECK-LABEL: name: vmovapd_rr
+ ; CHECK: liveins: $xmm0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: renamable $xmm1 = VMOVAPDrr killed renamable $xmm0
+ ; CHECK-NEXT: RET64 implicit $xmm1
+ renamable $xmm1 = VMOVAPDrr killed renamable $xmm0
+ RET64 implicit $xmm1
+...
+---
+name: vmovapd_ymm
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $ymm0
+ ; CHECK-LABEL: name: vmovapd_ymm
+ ; CHECK: liveins: $ymm0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: renamable $ymm1 = VMOVAPDYrr killed renamable $ymm0
+ ; CHECK-NEXT: RET64 implicit $ymm1
+ renamable $ymm1 = VMOVAPDYrr killed renamable $ymm0
+ RET64 implicit $ymm1
+...
diff --git a/llvm/test/CodeGen/X86/sink-hoist.ll b/llvm/test/CodeGen/X86/sink-hoist.ll
index a5777ac4a27e8..58323e663b2cb 100644
--- a/llvm/test/CodeGen/X86/sink-hoist.ll
+++ b/llvm/test/CodeGen/X86/sink-hoist.ll
@@ -9,7 +9,7 @@
; CHECK-NEXT: testb $1, %dil
; CHECK-NEXT: jne
; CHECK-NEXT: divsd
-; CHECK-NEXT: movapd
+; CHECK-NEXT: movaps
; CHECK-NEXT: ret
; CHECK: divsd
@@ -28,7 +28,7 @@ define double @foo(double %x, double %y, i1 %c) nounwind {
; CHECK-NEXT: testb $1, %dil
; CHECK-NEXT: je
; CHECK: divsd
-; CHECK: movapd
+; CHECK: movaps
; CHECK: ret
define double @split(double %x, double %y, i1 %c) nounwind {
%a = fdiv double %x, 3.2
More information about the llvm-commits
mailing list