[llvm] [X86] Rewrite MOVUPD to MOVUPS in X86FixupInstTuning (PR #217676)
Wiktor Ludwichowski via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 20 09:00:18 PDT 2026
https://github.com/AlnandoFeronso created https://github.com/llvm/llvm-project/pull/217676
MOVUPD and MOVUPS perform an identical unaligned 16-byte move, but MOVUPD carries a mandatory 0x66 prefix, making it one byte larger. We rewrite only when no domain delay would happen after this replacement. VEX/EVEX VMOVUPD is deliberately left, the 0x66 requirement is folded into the pp field of the prefix, so VMOVUPD and VMOVUPS encode to the same size and there is nothing to gain.
>From 11a5d309cea4e8d994e06eb77a0766c71d131c32 Mon Sep 17 00:00:00 2001
From: "Ludwichowski, Wiktor" <wiktor.ludwichowski at intel.com>
Date: Thu, 20 Aug 2026 16:20:56 +0200
Subject: [PATCH] Add pass processing movupd to movups
---
llvm/lib/Target/X86/X86FixupInstTuning.cpp | 18 ++++++
llvm/test/CodeGen/X86/inst-tuning-movupd.mir | 64 ++++++++++++++++++++
2 files changed, 82 insertions(+)
create mode 100644 llvm/test/CodeGen/X86/inst-tuning-movupd.mir
diff --git a/llvm/lib/Target/X86/X86FixupInstTuning.cpp b/llvm/lib/Target/X86/X86FixupInstTuning.cpp
index 621fd35a03cd5..b21846f5df004 100644
--- a/llvm/lib/Target/X86/X86FixupInstTuning.cpp
+++ b/llvm/lib/Target/X86/X86FixupInstTuning.cpp
@@ -255,6 +255,18 @@ bool X86FixupInstTuningImpl::processInstruction(
return ProcessUNPCKToIntDomain(NewOpc);
};
+ // MOVUPS takes 1 less byte of code size. Only replace when
+ // there is no move domain-delay penalty on the target.
+ auto ProcessMOVUPDToMOVUPS = [&](unsigned NewOpc) -> bool {
+ if (!ST->hasNoDomainDelayMov() ||
+ !NewOpcPreferable(NewOpc, /*ReplaceInTie*/ true))
+ 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 +709,12 @@ bool X86FixupInstTuningImpl::processInstruction(
return ProcessShiftLeftToAdd(X86::VPADDQZ256rr);
case X86::VPSLLQZri:
return ProcessShiftLeftToAdd(X86::VPADDQZrr);
+ case X86::MOVUPDrr:
+ return ProcessMOVUPDToMOVUPS(X86::MOVUPSrr);
+ case X86::MOVUPDrm:
+ return ProcessMOVUPDToMOVUPS(X86::MOVUPSrm);
+ case X86::MOVUPDmr:
+ return ProcessMOVUPDToMOVUPS(X86::MOVUPSmr);
default:
return false;
diff --git a/llvm/test/CodeGen/X86/inst-tuning-movupd.mir b/llvm/test/CodeGen/X86/inst-tuning-movupd.mir
new file mode 100644
index 0000000000000..916ebb8e94a01
--- /dev/null
+++ b/llvm/test/CodeGen/X86/inst-tuning-movupd.mir
@@ -0,0 +1,64 @@
+# 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-prefix=MOV
+# RUN: llc %s -mtriple=x86_64-- -mattr=-no-bypass-delay-mov -run-pass=x86-fixup-inst-tuning -o - | FileCheck %s --check-prefix=NODELAY
+
+---
+name: movupd_rr
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $xmm0
+ ; MOV-LABEL: name: movupd_rr
+ ; MOV: liveins: $xmm0
+ ; MOV-NEXT: {{ $}}
+ ; MOV-NEXT: renamable $xmm1 = MOVUPSrr killed renamable $xmm0
+ ; MOV-NEXT: RET64 implicit $xmm1
+ ;
+ ; NODELAY-LABEL: name: movupd_rr
+ ; NODELAY: liveins: $xmm0
+ ; NODELAY-NEXT: {{ $}}
+ ; NODELAY-NEXT: renamable $xmm1 = MOVUPDrr killed renamable $xmm0
+ ; NODELAY-NEXT: RET64 implicit $xmm1
+ renamable $xmm1 = MOVUPDrr killed renamable $xmm0
+ RET64 implicit $xmm1
+...
+---
+name: vmovupd_rr
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $xmm0
+ ; MOV-LABEL: name: vmovupd_rr
+ ; MOV: liveins: $xmm0
+ ; MOV-NEXT: {{ $}}
+ ; MOV-NEXT: renamable $xmm1 = VMOVUPDrr killed renamable $xmm0
+ ; MOV-NEXT: RET64 implicit $xmm1
+ ;
+ ; NODELAY-LABEL: name: vmovupd_rr
+ ; NODELAY: liveins: $xmm0
+ ; NODELAY-NEXT: {{ $}}
+ ; NODELAY-NEXT: renamable $xmm1 = VMOVUPDrr killed renamable $xmm0
+ ; NODELAY-NEXT: RET64 implicit $xmm1
+ renamable $xmm1 = VMOVUPDrr killed renamable $xmm0
+ RET64 implicit $xmm1
+...
+---
+name: vmovupd_ymm
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $ymm0
+ ; MOV-LABEL: name: vmovupd_ymm
+ ; MOV: liveins: $ymm0
+ ; MOV-NEXT: {{ $}}
+ ; MOV-NEXT: renamable $ymm1 = VMOVUPDYrr killed renamable $ymm0
+ ; MOV-NEXT: RET64 implicit $ymm1
+ ;
+ ; NODELAY-LABEL: name: vmovupd_ymm
+ ; NODELAY: liveins: $ymm0
+ ; NODELAY-NEXT: {{ $}}
+ ; NODELAY-NEXT: renamable $ymm1 = VMOVUPDYrr killed renamable $ymm0
+ ; NODELAY-NEXT: RET64 implicit $ymm1
+ renamable $ymm1 = VMOVUPDYrr killed renamable $ymm0
+ RET64 implicit $ymm1
+...
More information about the llvm-commits
mailing list