[llvm] [AArch64][GISel] Regbank G_BITCAST using src regbank. (PR #191522)

David Green via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 17 22:57:21 PDT 2026


https://github.com/davemgreen updated https://github.com/llvm/llvm-project/pull/191522

>From 61fceb343fd4b7366e2248950b2dcca6d0e04f2c Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Mon, 13 Apr 2026 12:01:11 +0100
Subject: [PATCH 1/2] [AArch64][GISel] Regbank G_BITCAST using src regbank.

This takes the regbank of a G_BITCAST from the input srcreg that has already
been allocated, keeping the bitcast on the same bank. A copy then might be
added to the dst if needed.

onlyUsesFP is also improved for G_BITCAST, allowing operations to guess the
correct type through a onlyUsesFP too.

Originally from #177158 by Ryan Cowan with modifications.
---
 .../AArch64/GISel/AArch64RegisterBankInfo.cpp | 27 +++++--
 .../GlobalISel/arm64-regbankselect.mir        | 45 +++++-------
 llvm/test/CodeGen/AArch64/add.ll              |  3 +-
 llvm/test/CodeGen/AArch64/andorxor.ll         |  9 +--
 .../test/CodeGen/AArch64/arm64-neon-3vdiff.ll | 72 +++++++------------
 llvm/test/CodeGen/AArch64/concat-vector.ll    | 48 ++++++-------
 llvm/test/CodeGen/AArch64/ctlz.ll             |  3 +-
 llvm/test/CodeGen/AArch64/ctpop.ll            |  7 +-
 llvm/test/CodeGen/AArch64/cttz.ll             |  3 +-
 .../CodeGen/AArch64/highextractbitcast.ll     |  5 +-
 llvm/test/CodeGen/AArch64/mul.ll              |  3 +-
 llvm/test/CodeGen/AArch64/popcount.ll         | 39 +++++-----
 llvm/test/CodeGen/AArch64/qmovn.ll            | 40 +++++------
 llvm/test/CodeGen/AArch64/sadd_sat_vec.ll     |  3 +-
 llvm/test/CodeGen/AArch64/ssub_sat_vec.ll     |  3 +-
 llvm/test/CodeGen/AArch64/sub.ll              |  3 +-
 llvm/test/CodeGen/AArch64/uadd_sat_vec.ll     |  3 +-
 llvm/test/CodeGen/AArch64/usub_sat_vec.ll     |  3 +-
 18 files changed, 139 insertions(+), 180 deletions(-)

diff --git a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
index de0577a893005..fba8323e62ff8 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
@@ -712,6 +712,15 @@ bool AArch64RegisterBankInfo::onlyUsesFP(const MachineInstr &MI,
                                          const AArch64RegisterInfo &TRI,
                                          unsigned Depth) const {
   switch (MI.getOpcode()) {
+  case TargetOpcode::G_BITCAST: {
+    Register DstReg = MI.getOperand(0).getReg();
+    return all_of(MRI.use_nodbg_instructions(DstReg),
+                  [&](const MachineInstr &UseMI) {
+                    return onlyUsesFP(UseMI, MRI, TRI, Depth + 1) ||
+                           prefersFPUse(UseMI, MRI, TRI);
+                  });
+  }
+
   case TargetOpcode::G_FPTOSI:
   case TargetOpcode::G_FPTOUI:
   case TargetOpcode::G_FPTOSI_SAT:
@@ -897,6 +906,19 @@ AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
                                    &ValMappings[Shift64Imm], 3);
     return getSameKindOfOperandsMapping(MI);
   }
+  case TargetOpcode::G_BITCAST: {
+    Register SrcReg = MI.getOperand(1).getReg();
+    const RegisterBank *SrcRB = getRegBank(SrcReg, MRI, TRI);
+    if (SrcRB) {
+      TypeSize Size = getSizeInBits(SrcReg, MRI, TRI);
+      return getInstructionMapping(
+          DefaultMappingID, 0,
+          getCopyMapping(SrcRB->getID(), SrcRB->getID(), Size),
+          // We only care about the mapping of the destination.
+          /*NumOperands*/ 2);
+    }
+    [[fallthrough]];
+  }
   case TargetOpcode::COPY: {
     Register DstReg = MI.getOperand(0).getReg();
     Register SrcReg = MI.getOperand(1).getReg();
@@ -919,10 +941,7 @@ AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
           // We only care about the mapping of the destination.
           /*NumOperands*/ 1);
     }
-    // Both registers are generic, use G_BITCAST.
-    [[fallthrough]];
-  }
-  case TargetOpcode::G_BITCAST: {
+    // Both registers are generic
     LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
     LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
     TypeSize Size = DstTy.getSizeInBits();
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-regbankselect.mir b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-regbankselect.mir
index a29a46bd43e49..b1eded3d40387 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-regbankselect.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-regbankselect.mir
@@ -398,16 +398,14 @@ legalized:       true
 
 # CHECK:      registers:
 # CHECK-NEXT:  - { id: 0, class: gpr, preferred-register: '', flags: [  ] }
-# FAST-NEXT:   - { id: 1, class: fpr, preferred-register: '', flags: [  ] }
-# GREEDY-NEXT: - { id: 1, class: gpr, preferred-register: '', flags: [  ] }
+# CHECK-NEXT:  - { id: 1, class: gpr, preferred-register: '', flags: [  ] }
 registers:
   - { id: 0, class: _ }
   - { id: 1, class: _ }
 
 # CHECK:  body:
-# CHECK:    %0:gpr(s32) = COPY $w0
-# FAST-NEXT:   %1:fpr(<4 x s8>) = G_BITCAST %0
-# GREEDY-NEXT: %1:gpr(<4 x s8>) = G_BITCAST %0
+# CHECK:      %0:gpr(s32) = COPY $w0
+# CHECK-NEXT: %1:gpr(<4 x s8>) = G_BITCAST %0
 # The greedy check is incorrect and should produce fpr.
 body:             |
   bb.0:
@@ -423,17 +421,15 @@ name:            bitcast_s32_fpr
 legalized:       true
 
 # CHECK:      registers:
-# CHECK-NEXT:  - { id: 0, class: fpr, preferred-register: '', flags: [  ] }
-# FAST-NEXT:   - { id: 1, class: gpr, preferred-register: '', flags: [  ] }
-# GREEDY-NEXT: - { id: 1, class: fpr, preferred-register: '', flags: [  ] }
+# CHECK-NEXT: - { id: 0, class: fpr, preferred-register: '', flags: [  ] }
+# CHECK-NEXT: - { id: 1, class: fpr, preferred-register: '', flags: [  ] }
 registers:
   - { id: 0, class: _ }
   - { id: 1, class: _ }
 
 # CHECK:  body:
 # CHECK:    %0:fpr(<2 x s16>) = COPY $s0
-# FAST:     %1:gpr(s32) = G_BITCAST %0
-# GREEDY:   %1:fpr(s32) = G_BITCAST %0
+# CHECK:    %1:fpr(s32) = G_BITCAST %0
 body:             |
   bb.0:
     liveins: $s0
@@ -449,16 +445,14 @@ legalized:       true
 
 # CHECK:      registers:
 # CHECK-NEXT:  - { id: 0, class: gpr, preferred-register: '', flags: [  ] }
-# FAST-NEXT:  - { id: 1, class: fpr, preferred-register: '', flags: [  ] }
-# GREEDY-NEXT:  - { id: 1, class: gpr, preferred-register: '', flags: [  ] }
+# CHECK-NEXT:  - { id: 1, class: gpr, preferred-register: '', flags: [  ] }
 registers:
   - { id: 0, class: _ }
   - { id: 1, class: _ }
 
 # CHECK:  body:
 # CHECK:    %0:gpr(s32) = COPY $w0
-# FAST:     %1:fpr(<2 x s16>) = G_BITCAST %0
-# GREEDY:   %1:gpr(<2 x s16>) = G_BITCAST %0
+# CHECK:    %1:gpr(<2 x s16>) = G_BITCAST %0
 body:             |
   bb.0:
     liveins: $w0
@@ -476,8 +470,7 @@ registers:
   - { id: 1, class: _ }
 # CHECK:  body:
 # CHECK:    %0:fpr(<2 x s16>) = COPY $s0
-# FAST:     %1:gpr(s32) = G_BITCAST %0
-# GREEDY:   %1:fpr(s32) = G_BITCAST %0
+# CHECK:    %1:fpr(s32) = G_BITCAST %0
 body:             |
   bb.0:
     liveins: $s0
@@ -495,8 +488,7 @@ registers:
   - { id: 1, class: _ }
 # CHECK:  body:
 # CHECK:    %0:gpr(s64) = COPY $x0
-# FAST:    %1:fpr(<2 x s32>) = G_BITCAST %0
-# GREEDY:  %1:gpr(<2 x s32>) = G_BITCAST %0
+# CHECK:    %1:gpr(<2 x s32>) = G_BITCAST %0
 body:             |
   bb.0:
     liveins: $x0
@@ -514,8 +506,7 @@ registers:
   - { id: 1, class: _ }
 # CHECK:  body:
 # CHECK:    %0:fpr(<2 x s32>) = COPY $d0
-# FAST:     %1:gpr(s64) = G_BITCAST %0
-# GREEDY:   %1:fpr(s64) = G_BITCAST %0
+# CHECK:    %1:fpr(s64) = G_BITCAST %0
 body:             |
   bb.0:
     liveins: $d0
@@ -533,8 +524,7 @@ registers:
   - { id: 1, class: _ }
 # CHECK:  body:
 # CHECK:    %0:gpr(s64) = COPY $x0
-# FAST:     %1:fpr(<2 x s32>) = G_BITCAST %0
-# GREEDY:   %1:gpr(<2 x s32>) = G_BITCAST %0
+# CHECK:    %1:gpr(<2 x s32>) = G_BITCAST %0
 body:             |
   bb.0:
     liveins: $x0
@@ -552,8 +542,7 @@ registers:
   - { id: 1, class: _ }
 # CHECK:  body:
 # CHECK:    %0:fpr(<2 x s32>) = COPY $d0
-# FAST:     %1:gpr(s64) = G_BITCAST %0
-# GREEDY:   %1:fpr(s64) = G_BITCAST %0
+# CHECK:    %1:fpr(s64) = G_BITCAST %0
 body:             |
   bb.0:
     liveins: $d0
@@ -691,13 +680,15 @@ registers:
 # No repairing should be necessary for both modes.
 # CHECK:         %0:gpr(s64) = COPY $x0
 # CHECK-NEXT:    %1:gpr(p0) = COPY $x1
-# FAST-NEXT:     %2:fpr(<2 x s32>) = G_BITCAST %0(s64)
+# FAST-NEXT:     %2:gpr(<2 x s32>) = G_BITCAST %0(s64)
 # FAST-NEXT:     %3:fpr(<2 x s32>) = G_LOAD %1(p0) :: (load (<2 x s32>) from %ir.addr)
-# FAST-NEXT:     %4:fpr(<2 x s32>) = G_OR %2, %3
+# FAST-NEXT:     %6:fpr(<2 x s32>) = COPY %2
+# FAST-NEXT:     %4:fpr(<2 x s32>) = G_OR %6, %3
+# FAST-NEXT:     %5:fpr(s64) = G_BITCAST %4(<2 x s32>)
 # GREEDY-NEXT:   %2:gpr(<2 x s32>) = G_BITCAST %0(s64)
 # GREEDY-NEXT:   %3:gpr(<2 x s32>) = G_LOAD %1(p0) :: (load (<2 x s32>) from %ir.addr)
 # GREEDY-NEXT:   %4:gpr(<2 x s32>) = G_OR %2, %3
-# CHECK-NEXT:    %5:gpr(s64) = G_BITCAST %4(<2 x s32>)
+# GREEDY-NEXT:   %5:gpr(s64) = G_BITCAST %4(<2 x s32>)
 # CHECK-NEXT:    $x0 = COPY %5(s64)
 # CHECK-NEXT:    RET_ReallyLR implicit $x0
 body:             |
diff --git a/llvm/test/CodeGen/AArch64/add.ll b/llvm/test/CodeGen/AArch64/add.ll
index 7502db4c5aa93..f2c7ca7bac03d 100644
--- a/llvm/test/CodeGen/AArch64/add.ll
+++ b/llvm/test/CodeGen/AArch64/add.ll
@@ -174,8 +174,7 @@ define void @v4i8(ptr %p1, ptr %p2) {
 ; CHECK-GI-NEXT:    mov v1.h[3], w9
 ; CHECK-GI-NEXT:    add v0.4h, v0.4h, v1.4h
 ; CHECK-GI-NEXT:    uzp1 v0.8b, v0.8b, v0.8b
-; CHECK-GI-NEXT:    fmov w8, s0
-; CHECK-GI-NEXT:    str w8, [x0]
+; CHECK-GI-NEXT:    str s0, [x0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %d = load <4 x i8>, ptr %p1
diff --git a/llvm/test/CodeGen/AArch64/andorxor.ll b/llvm/test/CodeGen/AArch64/andorxor.ll
index d8d003c85eed6..f967bf2fbaefc 100644
--- a/llvm/test/CodeGen/AArch64/andorxor.ll
+++ b/llvm/test/CodeGen/AArch64/andorxor.ll
@@ -472,8 +472,7 @@ define void @and_v4i8(ptr %p1, ptr %p2) {
 ; CHECK-GI-NEXT:    mov v1.h[3], w9
 ; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
 ; CHECK-GI-NEXT:    uzp1 v0.8b, v0.8b, v0.8b
-; CHECK-GI-NEXT:    fmov w8, s0
-; CHECK-GI-NEXT:    str w8, [x0]
+; CHECK-GI-NEXT:    str s0, [x0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %d = load <4 x i8>, ptr %p1
@@ -521,8 +520,7 @@ define void @or_v4i8(ptr %p1, ptr %p2) {
 ; CHECK-GI-NEXT:    mov v1.h[3], w9
 ; CHECK-GI-NEXT:    orr v0.8b, v0.8b, v1.8b
 ; CHECK-GI-NEXT:    uzp1 v0.8b, v0.8b, v0.8b
-; CHECK-GI-NEXT:    fmov w8, s0
-; CHECK-GI-NEXT:    str w8, [x0]
+; CHECK-GI-NEXT:    str s0, [x0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %d = load <4 x i8>, ptr %p1
@@ -570,8 +568,7 @@ define void @xor_v4i8(ptr %p1, ptr %p2) {
 ; CHECK-GI-NEXT:    mov v1.h[3], w9
 ; CHECK-GI-NEXT:    eor v0.8b, v0.8b, v1.8b
 ; CHECK-GI-NEXT:    uzp1 v0.8b, v0.8b, v0.8b
-; CHECK-GI-NEXT:    fmov w8, s0
-; CHECK-GI-NEXT:    str w8, [x0]
+; CHECK-GI-NEXT:    str s0, [x0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %d = load <4 x i8>, ptr %p1
diff --git a/llvm/test/CodeGen/AArch64/arm64-neon-3vdiff.ll b/llvm/test/CodeGen/AArch64/arm64-neon-3vdiff.ll
index 8cb319b2c3368..79822682c2178 100644
--- a/llvm/test/CodeGen/AArch64/arm64-neon-3vdiff.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-neon-3vdiff.ll
@@ -1076,8 +1076,7 @@ define <16 x i8> @test_vaddhn_high_s16(<8 x i8> %r, <8 x i16> %a, <8 x i16> %b)
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    addhn v1.8b, v1.8h, v2.8h
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vaddhn.i.i = add <8 x i16> %a, %b
@@ -1101,8 +1100,7 @@ define <8 x i16> @test_vaddhn_high_s32(<4 x i16> %r, <4 x i32> %a, <4 x i32> %b)
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    addhn v1.4h, v1.4s, v2.4s
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vaddhn.i.i = add <4 x i32> %a, %b
@@ -1126,8 +1124,7 @@ define <4 x i32> @test_vaddhn_high_s64(<2 x i32> %r, <2 x i64> %a, <2 x i64> %b)
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    addhn v1.2s, v1.2d, v2.2d
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vaddhn.i.i = add <2 x i64> %a, %b
@@ -1151,8 +1148,7 @@ define <16 x i8> @test_vaddhn_high_u16(<8 x i8> %r, <8 x i16> %a, <8 x i16> %b)
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    addhn v1.8b, v1.8h, v2.8h
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vaddhn.i.i = add <8 x i16> %a, %b
@@ -1176,8 +1172,7 @@ define <8 x i16> @test_vaddhn_high_u32(<4 x i16> %r, <4 x i32> %a, <4 x i32> %b)
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    addhn v1.4h, v1.4s, v2.4s
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vaddhn.i.i = add <4 x i32> %a, %b
@@ -1201,8 +1196,7 @@ define <4 x i32> @test_vaddhn_high_u64(<2 x i32> %r, <2 x i64> %a, <2 x i64> %b)
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    addhn v1.2s, v1.2d, v2.2d
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vaddhn.i.i = add <2 x i64> %a, %b
@@ -1286,8 +1280,7 @@ define <16 x i8> @test_vraddhn_high_s16(<8 x i8> %r, <8 x i16> %a, <8 x i16> %b)
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    raddhn v1.8b, v1.8h, v2.8h
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vraddhn2.i.i = tail call <8 x i8> @llvm.aarch64.neon.raddhn.v8i8(<8 x i16> %a, <8 x i16> %b)
@@ -1309,8 +1302,7 @@ define <8 x i16> @test_vraddhn_high_s32(<4 x i16> %r, <4 x i32> %a, <4 x i32> %b
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    raddhn v1.4h, v1.4s, v2.4s
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vraddhn2.i.i = tail call <4 x i16> @llvm.aarch64.neon.raddhn.v4i16(<4 x i32> %a, <4 x i32> %b)
@@ -1332,8 +1324,7 @@ define <4 x i32> @test_vraddhn_high_s64(<2 x i32> %r, <2 x i64> %a, <2 x i64> %b
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    raddhn v1.2s, v1.2d, v2.2d
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vraddhn2.i.i = tail call <2 x i32> @llvm.aarch64.neon.raddhn.v2i32(<2 x i64> %a, <2 x i64> %b)
@@ -1355,8 +1346,7 @@ define <16 x i8> @test_vraddhn_high_u16(<8 x i8> %r, <8 x i16> %a, <8 x i16> %b)
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    raddhn v1.8b, v1.8h, v2.8h
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vraddhn2.i.i = tail call <8 x i8> @llvm.aarch64.neon.raddhn.v8i8(<8 x i16> %a, <8 x i16> %b)
@@ -1378,8 +1368,7 @@ define <8 x i16> @test_vraddhn_high_u32(<4 x i16> %r, <4 x i32> %a, <4 x i32> %b
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    raddhn v1.4h, v1.4s, v2.4s
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vraddhn2.i.i = tail call <4 x i16> @llvm.aarch64.neon.raddhn.v4i16(<4 x i32> %a, <4 x i32> %b)
@@ -1401,8 +1390,7 @@ define <4 x i32> @test_vraddhn_high_u64(<2 x i32> %r, <2 x i64> %a, <2 x i64> %b
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    raddhn v1.2s, v1.2d, v2.2d
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vraddhn2.i.i = tail call <2 x i32> @llvm.aarch64.neon.raddhn.v2i32(<2 x i64> %a, <2 x i64> %b)
@@ -1496,8 +1484,7 @@ define <16 x i8> @test_vsubhn_high_s16(<8 x i8> %r, <8 x i16> %a, <8 x i16> %b)
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    subhn v1.8b, v1.8h, v2.8h
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vsubhn.i.i = sub <8 x i16> %a, %b
@@ -1521,8 +1508,7 @@ define <8 x i16> @test_vsubhn_high_s32(<4 x i16> %r, <4 x i32> %a, <4 x i32> %b)
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    subhn v1.4h, v1.4s, v2.4s
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vsubhn.i.i = sub <4 x i32> %a, %b
@@ -1546,8 +1532,7 @@ define <4 x i32> @test_vsubhn_high_s64(<2 x i32> %r, <2 x i64> %a, <2 x i64> %b)
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    subhn v1.2s, v1.2d, v2.2d
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vsubhn.i.i = sub <2 x i64> %a, %b
@@ -1571,8 +1556,7 @@ define <16 x i8> @test_vsubhn_high_u16(<8 x i8> %r, <8 x i16> %a, <8 x i16> %b)
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    subhn v1.8b, v1.8h, v2.8h
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vsubhn.i.i = sub <8 x i16> %a, %b
@@ -1596,8 +1580,7 @@ define <8 x i16> @test_vsubhn_high_u32(<4 x i16> %r, <4 x i32> %a, <4 x i32> %b)
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    subhn v1.4h, v1.4s, v2.4s
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vsubhn.i.i = sub <4 x i32> %a, %b
@@ -1621,8 +1604,7 @@ define <4 x i32> @test_vsubhn_high_u64(<2 x i32> %r, <2 x i64> %a, <2 x i64> %b)
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    subhn v1.2s, v1.2d, v2.2d
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vsubhn.i.i = sub <2 x i64> %a, %b
@@ -1706,8 +1688,7 @@ define <16 x i8> @test_vrsubhn_high_s16(<8 x i8> %r, <8 x i16> %a, <8 x i16> %b)
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    rsubhn v1.8b, v1.8h, v2.8h
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vrsubhn2.i.i = tail call <8 x i8> @llvm.aarch64.neon.rsubhn.v8i8(<8 x i16> %a, <8 x i16> %b)
@@ -1729,8 +1710,7 @@ define <8 x i16> @test_vrsubhn_high_s32(<4 x i16> %r, <4 x i32> %a, <4 x i32> %b
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    rsubhn v1.4h, v1.4s, v2.4s
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vrsubhn2.i.i = tail call <4 x i16> @llvm.aarch64.neon.rsubhn.v4i16(<4 x i32> %a, <4 x i32> %b)
@@ -1752,8 +1732,7 @@ define <4 x i32> @test_vrsubhn_high_s64(<2 x i32> %r, <2 x i64> %a, <2 x i64> %b
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    rsubhn v1.2s, v1.2d, v2.2d
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vrsubhn2.i.i = tail call <2 x i32> @llvm.aarch64.neon.rsubhn.v2i32(<2 x i64> %a, <2 x i64> %b)
@@ -1775,8 +1754,7 @@ define <16 x i8> @test_vrsubhn_high_u16(<8 x i8> %r, <8 x i16> %a, <8 x i16> %b)
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    rsubhn v1.8b, v1.8h, v2.8h
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vrsubhn2.i.i = tail call <8 x i8> @llvm.aarch64.neon.rsubhn.v8i8(<8 x i16> %a, <8 x i16> %b)
@@ -1798,8 +1776,7 @@ define <8 x i16> @test_vrsubhn_high_u32(<4 x i16> %r, <4 x i32> %a, <4 x i32> %b
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    rsubhn v1.4h, v1.4s, v2.4s
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vrsubhn2.i.i = tail call <4 x i16> @llvm.aarch64.neon.rsubhn.v4i16(<4 x i32> %a, <4 x i32> %b)
@@ -1821,8 +1798,7 @@ define <4 x i32> @test_vrsubhn_high_u64(<2 x i32> %r, <2 x i64> %a, <2 x i64> %b
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    rsubhn v1.2s, v1.2d, v2.2d
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %vrsubhn2.i.i = tail call <2 x i32> @llvm.aarch64.neon.rsubhn.v2i32(<2 x i64> %a, <2 x i64> %b)
diff --git a/llvm/test/CodeGen/AArch64/concat-vector.ll b/llvm/test/CodeGen/AArch64/concat-vector.ll
index e6f27b95d92c8..e6e863b074592 100644
--- a/llvm/test/CodeGen/AArch64/concat-vector.ll
+++ b/llvm/test/CodeGen/AArch64/concat-vector.ll
@@ -32,10 +32,9 @@ define <8 x i8> @concat2(<4 x i8> %A, <4 x i8> %B) {
 ;
 ; CHECK-GI-LABEL: concat2:
 ; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    uzp1 v1.8b, v1.8b, v0.8b
 ; CHECK-GI-NEXT:    uzp1 v0.8b, v0.8b, v0.8b
-; CHECK-GI-NEXT:    fmov w8, s1
-; CHECK-GI-NEXT:    mov v0.s[1], w8
+; CHECK-GI-NEXT:    uzp1 v1.8b, v1.8b, v0.8b
+; CHECK-GI-NEXT:    mov v0.s[1], v1.s[0]
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
 ; CHECK-GI-NEXT:    ret
    %v8i8 = shufflevector <4 x i8> %A, <4 x i8> %B, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
@@ -61,10 +60,9 @@ define <4 x i16> @concat4(<2 x i16> %A, <2 x i16> %B) {
 ;
 ; CHECK-GI-LABEL: concat4:
 ; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    uzp1 v1.4h, v1.4h, v0.4h
 ; CHECK-GI-NEXT:    uzp1 v0.4h, v0.4h, v0.4h
-; CHECK-GI-NEXT:    fmov w8, s1
-; CHECK-GI-NEXT:    mov v0.s[1], w8
+; CHECK-GI-NEXT:    uzp1 v1.4h, v1.4h, v0.4h
+; CHECK-GI-NEXT:    mov v0.s[1], v1.s[0]
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
 ; CHECK-GI-NEXT:    ret
    %v4i16 = shufflevector <2 x i16> %A, <2 x i16> %B, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
@@ -125,9 +123,9 @@ define <4 x half> @concat9(<2 x half> %A, <2 x half> %B) {
 ;
 ; CHECK-GI-LABEL: concat9:
 ; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    fmov w8, s1
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    mov v0.s[1], w8
+; CHECK-GI-NEXT:    // kill: def $d1 killed $d1 def $q1
+; CHECK-GI-NEXT:    mov v0.s[1], v1.s[0]
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
 ; CHECK-GI-NEXT:    ret
    %v4half= shufflevector <2 x half> %A, <2 x half> %B, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
@@ -215,16 +213,13 @@ define <16 x i8> @concat_v16s8_v4s8_reg(<4 x i8> %A, <4 x i8> %B, <4 x i8> %C, <
 ;
 ; CHECK-GI-LABEL: concat_v16s8_v4s8_reg:
 ; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    uzp1 v1.8b, v1.8b, v0.8b
 ; CHECK-GI-NEXT:    uzp1 v0.8b, v0.8b, v0.8b
-; CHECK-GI-NEXT:    fmov w8, s1
+; CHECK-GI-NEXT:    uzp1 v1.8b, v1.8b, v0.8b
 ; CHECK-GI-NEXT:    uzp1 v2.8b, v2.8b, v0.8b
-; CHECK-GI-NEXT:    mov v0.s[1], w8
-; CHECK-GI-NEXT:    fmov w8, s2
+; CHECK-GI-NEXT:    mov v0.s[1], v1.s[0]
 ; CHECK-GI-NEXT:    uzp1 v1.8b, v3.8b, v0.8b
-; CHECK-GI-NEXT:    mov v0.s[2], w8
-; CHECK-GI-NEXT:    fmov w8, s1
-; CHECK-GI-NEXT:    mov v0.s[3], w8
+; CHECK-GI-NEXT:    mov v0.s[2], v2.s[0]
+; CHECK-GI-NEXT:    mov v0.s[3], v1.s[0]
 ; CHECK-GI-NEXT:    ret
     %b = shufflevector <4 x i8> %A, <4 x i8> %B, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
     %c = shufflevector <4 x i8> %C, <4 x i8> %D, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
@@ -246,16 +241,13 @@ define <8 x i16> @concat_v8s16_v2s16_reg(<2 x i16> %A, <2 x i16> %B, <2 x i16> %
 ;
 ; CHECK-GI-LABEL: concat_v8s16_v2s16_reg:
 ; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    uzp1 v1.4h, v1.4h, v0.4h
 ; CHECK-GI-NEXT:    uzp1 v0.4h, v0.4h, v0.4h
-; CHECK-GI-NEXT:    fmov w8, s1
+; CHECK-GI-NEXT:    uzp1 v1.4h, v1.4h, v0.4h
 ; CHECK-GI-NEXT:    uzp1 v2.4h, v2.4h, v0.4h
-; CHECK-GI-NEXT:    mov v0.s[1], w8
-; CHECK-GI-NEXT:    fmov w8, s2
+; CHECK-GI-NEXT:    mov v0.s[1], v1.s[0]
 ; CHECK-GI-NEXT:    uzp1 v1.4h, v3.4h, v0.4h
-; CHECK-GI-NEXT:    mov v0.s[2], w8
-; CHECK-GI-NEXT:    fmov w8, s1
-; CHECK-GI-NEXT:    mov v0.s[3], w8
+; CHECK-GI-NEXT:    mov v0.s[2], v2.s[0]
+; CHECK-GI-NEXT:    mov v0.s[3], v1.s[0]
 ; CHECK-GI-NEXT:    ret
     %b = shufflevector <2 x i16> %A, <2 x i16> %B, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
     %c = shufflevector <2 x i16> %C, <2 x i16> %D, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
@@ -273,9 +265,9 @@ define <4 x i16> @concat_undef_first_use_first(ptr %p1, ptr %p2) {
 ; CHECK-GI:       // %bb.0:
 ; CHECK-GI-NEXT:    ldrh w8, [x0]
 ; CHECK-GI-NEXT:    ldrh w9, [x0, #2]
-; CHECK-GI-NEXT:    fmov s1, w8
-; CHECK-GI-NEXT:    mov v1.h[1], w9
-; CHECK-GI-NEXT:    mov v0.s[1], v1.s[0]
+; CHECK-GI-NEXT:    fmov s0, w8
+; CHECK-GI-NEXT:    mov v0.h[1], w9
+; CHECK-GI-NEXT:    mov v0.s[1], v0.s[0]
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
 ; CHECK-GI-NEXT:    ret
   %l1 = load <2 x i16>, ptr %p1
@@ -296,9 +288,9 @@ define <4 x i16> @concat_undef_first_use_second(ptr %p1, ptr %p2) {
 ; CHECK-GI:       // %bb.0:
 ; CHECK-GI-NEXT:    ldrh w8, [x0]
 ; CHECK-GI-NEXT:    ldrh w9, [x0, #2]
-; CHECK-GI-NEXT:    fmov s1, w8
-; CHECK-GI-NEXT:    mov v1.h[1], w9
-; CHECK-GI-NEXT:    mov v0.s[1], v1.s[0]
+; CHECK-GI-NEXT:    fmov s0, w8
+; CHECK-GI-NEXT:    mov v0.h[1], w9
+; CHECK-GI-NEXT:    mov v0.s[1], v0.s[0]
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
 ; CHECK-GI-NEXT:    ret
   %l1 = load <2 x i16>, ptr %p1
diff --git a/llvm/test/CodeGen/AArch64/ctlz.ll b/llvm/test/CodeGen/AArch64/ctlz.ll
index b45b48d06071b..5740eaa977875 100644
--- a/llvm/test/CodeGen/AArch64/ctlz.ll
+++ b/llvm/test/CodeGen/AArch64/ctlz.ll
@@ -99,8 +99,7 @@ define void @v4i8(ptr %p1) {
 ; CHECK-GI-NEXT:    mov v2.b[2], v3.b[0]
 ; CHECK-GI-NEXT:    mov v2.b[3], v0.b[0]
 ; CHECK-GI-NEXT:    clz v0.8b, v2.8b
-; CHECK-GI-NEXT:    fmov w8, s0
-; CHECK-GI-NEXT:    str w8, [x0]
+; CHECK-GI-NEXT:    str s0, [x0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %d = load <4 x i8>, ptr %p1
diff --git a/llvm/test/CodeGen/AArch64/ctpop.ll b/llvm/test/CodeGen/AArch64/ctpop.ll
index 9e7e5888fa6e6..be62efca6cb6a 100644
--- a/llvm/test/CodeGen/AArch64/ctpop.ll
+++ b/llvm/test/CodeGen/AArch64/ctpop.ll
@@ -97,8 +97,7 @@ define void @v4i8(ptr %p1) {
 ; CHECK-GI-NEXT:    mov v2.b[2], v3.b[0]
 ; CHECK-GI-NEXT:    mov v2.b[3], v0.b[0]
 ; CHECK-GI-NEXT:    cnt v0.8b, v2.8b
-; CHECK-GI-NEXT:    fmov w8, s0
-; CHECK-GI-NEXT:    str w8, [x0]
+; CHECK-GI-NEXT:    str s0, [x0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %d = load <4 x i8>, ptr %p1
@@ -572,7 +571,7 @@ define i32 @i32_mask(i32 %x) {
 ; CHECK-GI-LABEL: i32_mask:
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    and w8, w0, #0xff
-; CHECK-GI-NEXT:    fmov s0, w8
+; CHECK-GI-NEXT:    fmov d0, x8
 ; CHECK-GI-NEXT:    cnt v0.8b, v0.8b
 ; CHECK-GI-NEXT:    uaddlv h0, v0.8b
 ; CHECK-GI-NEXT:    fmov w0, s0
@@ -596,7 +595,7 @@ define i32 @i32_mask_negative(i32 %x) {
 ; CHECK-GI-LABEL: i32_mask_negative:
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    and w8, w0, #0xffff
-; CHECK-GI-NEXT:    fmov s0, w8
+; CHECK-GI-NEXT:    fmov d0, x8
 ; CHECK-GI-NEXT:    cnt v0.8b, v0.8b
 ; CHECK-GI-NEXT:    uaddlv h0, v0.8b
 ; CHECK-GI-NEXT:    fmov w0, s0
diff --git a/llvm/test/CodeGen/AArch64/cttz.ll b/llvm/test/CodeGen/AArch64/cttz.ll
index 86c1aca9ed9e1..b04e8df455357 100644
--- a/llvm/test/CodeGen/AArch64/cttz.ll
+++ b/llvm/test/CodeGen/AArch64/cttz.ll
@@ -127,8 +127,7 @@ define void @v4i8(ptr %p1) {
 ; CHECK-GI-NEXT:    and v0.8b, v2.8b, v0.8b
 ; CHECK-GI-NEXT:    uzp1 v0.8b, v0.8b, v0.8b
 ; CHECK-GI-NEXT:    cnt v0.8b, v0.8b
-; CHECK-GI-NEXT:    fmov w8, s0
-; CHECK-GI-NEXT:    str w8, [x0]
+; CHECK-GI-NEXT:    str s0, [x0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %d = load <4 x i8>, ptr %p1
diff --git a/llvm/test/CodeGen/AArch64/highextractbitcast.ll b/llvm/test/CodeGen/AArch64/highextractbitcast.ll
index bd6c168ce8776..de2911b8a5127 100644
--- a/llvm/test/CodeGen/AArch64/highextractbitcast.ll
+++ b/llvm/test/CodeGen/AArch64/highextractbitcast.ll
@@ -599,10 +599,9 @@ define <8 x i16> @foov8i16(<16 x i8> %a1, <2 x i64> %b1) {
 ;
 ; CHECK-GI-LABEL: foov8i16:
 ; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    shrn v1.4h, v1.4s, #5
 ; CHECK-GI-NEXT:    shrn v0.4h, v0.4s, #5
-; CHECK-GI-NEXT:    fmov x8, d1
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    shrn v1.4h, v1.4s, #5
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-GI-NEXT:    ret
   %a0 = bitcast <16 x i8> %a1 to <4 x i32>
   %b0 = bitcast <2 x i64> %b1 to <4 x i32>
diff --git a/llvm/test/CodeGen/AArch64/mul.ll b/llvm/test/CodeGen/AArch64/mul.ll
index 475bd22c6ebcb..10400fd442cb1 100644
--- a/llvm/test/CodeGen/AArch64/mul.ll
+++ b/llvm/test/CodeGen/AArch64/mul.ll
@@ -186,8 +186,7 @@ define void @v4i8(ptr %p1, ptr %p2) {
 ; CHECK-GI-NEXT:    mov v1.h[3], w9
 ; CHECK-GI-NEXT:    mul v0.4h, v0.4h, v1.4h
 ; CHECK-GI-NEXT:    uzp1 v0.8b, v0.8b, v0.8b
-; CHECK-GI-NEXT:    fmov w8, s0
-; CHECK-GI-NEXT:    str w8, [x0]
+; CHECK-GI-NEXT:    str s0, [x0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %d = load <4 x i8>, ptr %p1
diff --git a/llvm/test/CodeGen/AArch64/popcount.ll b/llvm/test/CodeGen/AArch64/popcount.ll
index 5a759b0be06ac..bb81776a7f6d6 100644
--- a/llvm/test/CodeGen/AArch64/popcount.ll
+++ b/llvm/test/CodeGen/AArch64/popcount.ll
@@ -439,8 +439,6 @@ declare <2 x i64> @llvm.ctpop.v2i64(<2 x i64>)
 define <1 x i64> @popcount1x64(<1 x i64> %0) {
 ; CHECKO0-LABEL: popcount1x64:
 ; CHECKO0:       // %bb.0: // %Entry
-; CHECKO0-NEXT:    fmov x0, d0
-; CHECKO0-NEXT:    fmov d0, x0
 ; CHECKO0-NEXT:    cnt v0.8b, v0.8b
 ; CHECKO0-NEXT:    uaddlv h0, v0.8b
 ; CHECKO0-NEXT:    // kill: def $q0 killed $h0
@@ -492,8 +490,6 @@ define <1 x i64> @popcount1x64(<1 x i64> %0) {
 ;
 ; GISELO0-LABEL: popcount1x64:
 ; GISELO0:       // %bb.0: // %Entry
-; GISELO0-NEXT:    fmov x0, d0
-; GISELO0-NEXT:    fmov d0, x0
 ; GISELO0-NEXT:    cnt v0.8b, v0.8b
 ; GISELO0-NEXT:    uaddlv h0, v0.8b
 ; GISELO0-NEXT:    // kill: def $q0 killed $h0
@@ -776,10 +772,11 @@ define i32 @ctpop_into_extract(ptr %p) {
 ; CHECKO0-NEXT:    // implicit-def: $d2
 ; CHECKO0-NEXT:    fmov s2, w8
 ; CHECKO0-NEXT:    ldr d0, [x0]
-; CHECKO0-NEXT:    fmov s1, s0
-; CHECKO0-NEXT:    fmov w8, s1
-; CHECKO0-NEXT:    fmov s1, w8
-; CHECKO0-NEXT:    // kill: def $d1 killed $s1
+; CHECKO0-NEXT:    // implicit-def: $q1
+; CHECKO0-NEXT:    fmov d1, d0
+; CHECKO0-NEXT:    mov w8, v1.s[0]
+; CHECKO0-NEXT:    mov w1, w8
+; CHECKO0-NEXT:    fmov d1, x1
 ; CHECKO0-NEXT:    cnt v1.8b, v1.8b
 ; CHECKO0-NEXT:    uaddlv h1, v1.8b
 ; CHECKO0-NEXT:    // kill: def $q1 killed $h1
@@ -858,8 +855,8 @@ define i32 @ctpop_into_extract(ptr %p) {
 ; GISEL-NEXT:    ldr d0, [x0]
 ; GISEL-NEXT:    mov x8, x0
 ; GISEL-NEXT:    mov w0, wzr
-; GISEL-NEXT:    fmov w9, s0
-; GISEL-NEXT:    fmov s1, w9
+; GISEL-NEXT:    mov w9, v0.s[0]
+; GISEL-NEXT:    fmov d1, x9
 ; GISEL-NEXT:    mov w9, #-1 // =0xffffffff
 ; GISEL-NEXT:    fmov s2, w9
 ; GISEL-NEXT:    cnt v1.8b, v1.8b
@@ -875,10 +872,11 @@ define i32 @ctpop_into_extract(ptr %p) {
 ; GISELO0-NEXT:    // implicit-def: $d2
 ; GISELO0-NEXT:    fmov s2, w8
 ; GISELO0-NEXT:    ldr d0, [x0]
-; GISELO0-NEXT:    fmov s1, s0
-; GISELO0-NEXT:    fmov w8, s1
-; GISELO0-NEXT:    fmov s1, w8
-; GISELO0-NEXT:    // kill: def $d1 killed $s1
+; GISELO0-NEXT:    // implicit-def: $q1
+; GISELO0-NEXT:    fmov d1, d0
+; GISELO0-NEXT:    mov w8, v1.s[0]
+; GISELO0-NEXT:    mov w1, w8
+; GISELO0-NEXT:    fmov d1, x1
 ; GISELO0-NEXT:    cnt v1.8b, v1.8b
 ; GISELO0-NEXT:    uaddlv h1, v1.8b
 ; GISELO0-NEXT:    // kill: def $q1 killed $h1
@@ -905,8 +903,9 @@ define <8 x i8> @bitcast_upper_bits(i32 %b, <8 x i8> %v) {
 ; CHECKO0-LABEL: bitcast_upper_bits:
 ; CHECKO0:       // %bb.0:
 ; CHECKO0-NEXT:    fmov d1, d0
-; CHECKO0-NEXT:    fmov s0, w0
-; CHECKO0-NEXT:    // kill: def $d0 killed $s0
+; CHECKO0-NEXT:    mov w8, w0
+; CHECKO0-NEXT:    mov w0, w8
+; CHECKO0-NEXT:    fmov d0, x0
 ; CHECKO0-NEXT:    add v0.8b, v0.8b, v1.8b
 ; CHECKO0-NEXT:    ret
 ;
@@ -926,15 +925,17 @@ define <8 x i8> @bitcast_upper_bits(i32 %b, <8 x i8> %v) {
 ;
 ; GISEL-LABEL: bitcast_upper_bits:
 ; GISEL:       // %bb.0:
-; GISEL-NEXT:    fmov s1, w0
+; GISEL-NEXT:    mov w8, w0
+; GISEL-NEXT:    fmov d1, x8
 ; GISEL-NEXT:    add v0.8b, v1.8b, v0.8b
 ; GISEL-NEXT:    ret
 ;
 ; GISELO0-LABEL: bitcast_upper_bits:
 ; GISELO0:       // %bb.0:
 ; GISELO0-NEXT:    fmov d1, d0
-; GISELO0-NEXT:    fmov s0, w0
-; GISELO0-NEXT:    // kill: def $d0 killed $s0
+; GISELO0-NEXT:    mov w8, w0
+; GISELO0-NEXT:    mov w0, w8
+; GISELO0-NEXT:    fmov d0, x0
 ; GISELO0-NEXT:    add v0.8b, v0.8b, v1.8b
 ; GISELO0-NEXT:    ret
   %a = zext i32 %b to i64
diff --git a/llvm/test/CodeGen/AArch64/qmovn.ll b/llvm/test/CodeGen/AArch64/qmovn.ll
index dc1b7df9b32ae..5d534e09cdbd3 100644
--- a/llvm/test/CodeGen/AArch64/qmovn.ll
+++ b/llvm/test/CodeGen/AArch64/qmovn.ll
@@ -645,16 +645,15 @@ define <4 x i16> @sminsmax_range_unsigned_i64_to_i16(<2 x i16> %x, <2 x i64> %y)
 ;
 ; CHECK-GI-LABEL: sminsmax_range_unsigned_i64_to_i16:
 ; CHECK-GI:       // %bb.0: // %entry
-; CHECK-GI-NEXT:    cmgt v2.2d, v1.2d, #0
-; CHECK-GI-NEXT:    movi v3.2d, #0x0000000000ffff
-; CHECK-GI-NEXT:    and v1.16b, v1.16b, v2.16b
-; CHECK-GI-NEXT:    cmgt v2.2d, v3.2d, v1.2d
-; CHECK-GI-NEXT:    bif v1.16b, v3.16b, v2.16b
+; CHECK-GI-NEXT:    cmgt v3.2d, v1.2d, #0
+; CHECK-GI-NEXT:    movi v2.2d, #0x0000000000ffff
+; CHECK-GI-NEXT:    uzp1 v0.4h, v0.4h, v0.4h
+; CHECK-GI-NEXT:    and v1.16b, v1.16b, v3.16b
+; CHECK-GI-NEXT:    cmgt v3.2d, v2.2d, v1.2d
+; CHECK-GI-NEXT:    bif v1.16b, v2.16b, v3.16b
 ; CHECK-GI-NEXT:    xtn v1.2s, v1.2d
 ; CHECK-GI-NEXT:    uzp1 v1.4h, v1.4h, v0.4h
-; CHECK-GI-NEXT:    uzp1 v0.4h, v0.4h, v0.4h
-; CHECK-GI-NEXT:    fmov w8, s1
-; CHECK-GI-NEXT:    mov v0.s[1], w8
+; CHECK-GI-NEXT:    mov v0.s[1], v1.s[0]
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
 ; CHECK-GI-NEXT:    ret
 entry:
@@ -683,6 +682,7 @@ define <4 x i16> @sminsmax_range_signed_i64_to_i16(<2 x i16> %x, <2 x i64> %y) {
 ; CHECK-GI-LABEL: sminsmax_range_signed_i64_to_i16:
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    adrp x8, .LCPI46_1
+; CHECK-GI-NEXT:    uzp1 v0.4h, v0.4h, v0.4h
 ; CHECK-GI-NEXT:    ldr q2, [x8, :lo12:.LCPI46_1]
 ; CHECK-GI-NEXT:    adrp x8, .LCPI46_0
 ; CHECK-GI-NEXT:    cmgt v3.2d, v1.2d, v2.2d
@@ -692,9 +692,7 @@ define <4 x i16> @sminsmax_range_signed_i64_to_i16(<2 x i16> %x, <2 x i64> %y) {
 ; CHECK-GI-NEXT:    bif v1.16b, v2.16b, v3.16b
 ; CHECK-GI-NEXT:    xtn v1.2s, v1.2d
 ; CHECK-GI-NEXT:    uzp1 v1.4h, v1.4h, v0.4h
-; CHECK-GI-NEXT:    uzp1 v0.4h, v0.4h, v0.4h
-; CHECK-GI-NEXT:    fmov w8, s1
-; CHECK-GI-NEXT:    mov v0.s[1], w8
+; CHECK-GI-NEXT:    mov v0.s[1], v1.s[0]
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
 ; CHECK-GI-NEXT:    ret
 entry:
@@ -718,13 +716,12 @@ define <4 x i16> @umin_range_unsigned_i64_to_i16(<2 x i16> %x, <2 x i64> %y) {
 ; CHECK-GI-LABEL: umin_range_unsigned_i64_to_i16:
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    movi v2.2d, #0x0000000000ffff
+; CHECK-GI-NEXT:    uzp1 v0.4h, v0.4h, v0.4h
 ; CHECK-GI-NEXT:    cmhi v3.2d, v2.2d, v1.2d
 ; CHECK-GI-NEXT:    bif v1.16b, v2.16b, v3.16b
 ; CHECK-GI-NEXT:    xtn v1.2s, v1.2d
 ; CHECK-GI-NEXT:    uzp1 v1.4h, v1.4h, v0.4h
-; CHECK-GI-NEXT:    uzp1 v0.4h, v0.4h, v0.4h
-; CHECK-GI-NEXT:    fmov w8, s1
-; CHECK-GI-NEXT:    mov v0.s[1], w8
+; CHECK-GI-NEXT:    mov v0.s[1], v1.s[0]
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
 ; CHECK-GI-NEXT:    ret
 entry:
@@ -750,13 +747,12 @@ define <8 x i8> @sminsmax_range_unsigned_i64_to_i8(<4 x i8> %x, <4 x i32> %y) {
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    movi v2.2d, #0000000000000000
 ; CHECK-GI-NEXT:    movi v3.2d, #0x0000ff000000ff
+; CHECK-GI-NEXT:    uzp1 v0.8b, v0.8b, v0.8b
 ; CHECK-GI-NEXT:    smax v1.4s, v1.4s, v2.4s
 ; CHECK-GI-NEXT:    smin v1.4s, v1.4s, v3.4s
 ; CHECK-GI-NEXT:    xtn v1.4h, v1.4s
 ; CHECK-GI-NEXT:    uzp1 v1.8b, v1.8b, v0.8b
-; CHECK-GI-NEXT:    uzp1 v0.8b, v0.8b, v0.8b
-; CHECK-GI-NEXT:    fmov w8, s1
-; CHECK-GI-NEXT:    mov v0.s[1], w8
+; CHECK-GI-NEXT:    mov v0.s[1], v1.s[0]
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
 ; CHECK-GI-NEXT:    ret
 entry:
@@ -782,13 +778,12 @@ define <8 x i8> @sminsmax_range_signed_i32_to_i8(<4 x i8> %x, <4 x i32> %y) {
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    mvni v2.4s, #127
 ; CHECK-GI-NEXT:    movi v3.4s, #127
+; CHECK-GI-NEXT:    uzp1 v0.8b, v0.8b, v0.8b
 ; CHECK-GI-NEXT:    smax v1.4s, v1.4s, v2.4s
 ; CHECK-GI-NEXT:    smin v1.4s, v1.4s, v3.4s
 ; CHECK-GI-NEXT:    xtn v1.4h, v1.4s
 ; CHECK-GI-NEXT:    uzp1 v1.8b, v1.8b, v0.8b
-; CHECK-GI-NEXT:    uzp1 v0.8b, v0.8b, v0.8b
-; CHECK-GI-NEXT:    fmov w8, s1
-; CHECK-GI-NEXT:    mov v0.s[1], w8
+; CHECK-GI-NEXT:    mov v0.s[1], v1.s[0]
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
 ; CHECK-GI-NEXT:    ret
 entry:
@@ -811,12 +806,11 @@ define <8 x i8> @umin_range_unsigned_i32_to_i8(<4 x i8> %x, <4 x i32> %y) {
 ; CHECK-GI-LABEL: umin_range_unsigned_i32_to_i8:
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    movi v2.2d, #0x0000ff000000ff
+; CHECK-GI-NEXT:    uzp1 v0.8b, v0.8b, v0.8b
 ; CHECK-GI-NEXT:    umin v1.4s, v1.4s, v2.4s
 ; CHECK-GI-NEXT:    xtn v1.4h, v1.4s
 ; CHECK-GI-NEXT:    uzp1 v1.8b, v1.8b, v0.8b
-; CHECK-GI-NEXT:    uzp1 v0.8b, v0.8b, v0.8b
-; CHECK-GI-NEXT:    fmov w8, s1
-; CHECK-GI-NEXT:    mov v0.s[1], w8
+; CHECK-GI-NEXT:    mov v0.s[1], v1.s[0]
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
 ; CHECK-GI-NEXT:    ret
 entry:
diff --git a/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll b/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll
index b31a5ea0b5d79..88f1324762f8f 100644
--- a/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll
+++ b/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll
@@ -146,8 +146,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind {
 ; CHECK-GI-NEXT:    mov v3.b[3], v0.b[0]
 ; CHECK-GI-NEXT:    mov v5.b[3], v1.b[0]
 ; CHECK-GI-NEXT:    sqadd v0.8b, v3.8b, v5.8b
-; CHECK-GI-NEXT:    fmov w8, s0
-; CHECK-GI-NEXT:    str w8, [x2]
+; CHECK-GI-NEXT:    str s0, [x2]
 ; CHECK-GI-NEXT:    ret
   %x = load <4 x i8>, ptr %px
   %y = load <4 x i8>, ptr %py
diff --git a/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll b/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll
index 02eb40b412efd..55608f6ef21b8 100644
--- a/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll
+++ b/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll
@@ -146,8 +146,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind {
 ; CHECK-GI-NEXT:    mov v3.b[3], v0.b[0]
 ; CHECK-GI-NEXT:    mov v5.b[3], v1.b[0]
 ; CHECK-GI-NEXT:    sqsub v0.8b, v3.8b, v5.8b
-; CHECK-GI-NEXT:    fmov w8, s0
-; CHECK-GI-NEXT:    str w8, [x2]
+; CHECK-GI-NEXT:    str s0, [x2]
 ; CHECK-GI-NEXT:    ret
   %x = load <4 x i8>, ptr %px
   %y = load <4 x i8>, ptr %py
diff --git a/llvm/test/CodeGen/AArch64/sub.ll b/llvm/test/CodeGen/AArch64/sub.ll
index dd920b98e18eb..402f35e134dbe 100644
--- a/llvm/test/CodeGen/AArch64/sub.ll
+++ b/llvm/test/CodeGen/AArch64/sub.ll
@@ -174,8 +174,7 @@ define void @v4i8(ptr %p1, ptr %p2) {
 ; CHECK-GI-NEXT:    mov v1.h[3], w9
 ; CHECK-GI-NEXT:    sub v0.4h, v0.4h, v1.4h
 ; CHECK-GI-NEXT:    uzp1 v0.8b, v0.8b, v0.8b
-; CHECK-GI-NEXT:    fmov w8, s0
-; CHECK-GI-NEXT:    str w8, [x0]
+; CHECK-GI-NEXT:    str s0, [x0]
 ; CHECK-GI-NEXT:    ret
 entry:
   %d = load <4 x i8>, ptr %p1
diff --git a/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll b/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll
index cd02d18e61643..644313c953607 100644
--- a/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll
+++ b/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll
@@ -143,8 +143,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind {
 ; CHECK-GI-NEXT:    mov v3.b[3], v0.b[0]
 ; CHECK-GI-NEXT:    mov v5.b[3], v1.b[0]
 ; CHECK-GI-NEXT:    uqadd v0.8b, v3.8b, v5.8b
-; CHECK-GI-NEXT:    fmov w8, s0
-; CHECK-GI-NEXT:    str w8, [x2]
+; CHECK-GI-NEXT:    str s0, [x2]
 ; CHECK-GI-NEXT:    ret
   %x = load <4 x i8>, ptr %px
   %y = load <4 x i8>, ptr %py
diff --git a/llvm/test/CodeGen/AArch64/usub_sat_vec.ll b/llvm/test/CodeGen/AArch64/usub_sat_vec.ll
index ef70137e6deee..9a982f0196755 100644
--- a/llvm/test/CodeGen/AArch64/usub_sat_vec.ll
+++ b/llvm/test/CodeGen/AArch64/usub_sat_vec.ll
@@ -143,8 +143,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind {
 ; CHECK-GI-NEXT:    mov v3.b[3], v0.b[0]
 ; CHECK-GI-NEXT:    mov v5.b[3], v1.b[0]
 ; CHECK-GI-NEXT:    uqsub v0.8b, v3.8b, v5.8b
-; CHECK-GI-NEXT:    fmov w8, s0
-; CHECK-GI-NEXT:    str w8, [x2]
+; CHECK-GI-NEXT:    str s0, [x2]
 ; CHECK-GI-NEXT:    ret
   %x = load <4 x i8>, ptr %px
   %y = load <4 x i8>, ptr %py

>From dd88b49a6f6d7e360365f4f9c8c25365caf89870 Mon Sep 17 00:00:00 2001
From: David Green <dmg862 at gmail.com>
Date: Sat, 18 Apr 2026 06:57:12 +0100
Subject: [PATCH 2/2] Update
 llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp

Co-authored-by: Matt Arsenault <arsenm2 at gmail.com>
---
 llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
index fba8323e62ff8..2ea5951d128bc 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
@@ -915,7 +915,7 @@ AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
           DefaultMappingID, 0,
           getCopyMapping(SrcRB->getID(), SrcRB->getID(), Size),
           // We only care about the mapping of the destination.
-          /*NumOperands*/ 2);
+          /*NumOperands=*/ 2);
     }
     [[fallthrough]];
   }



More information about the llvm-commits mailing list