[llvm] [X86] Rewrite MOVUPD to MOVUPS in X86FixupInstTuning (PR #217676)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 20 09:06:54 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-x86

Author: Wiktor Ludwichowski (AlnandoFeronso)

<details>
<summary>Changes</summary>

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.

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


2 Files Affected:

- (modified) llvm/lib/Target/X86/X86FixupInstTuning.cpp (+18) 
- (added) llvm/test/CodeGen/X86/inst-tuning-movupd.mir (+64) 


``````````diff
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
+...

``````````

</details>


https://github.com/llvm/llvm-project/pull/217676


More information about the llvm-commits mailing list