[llvm] [AArch64][GlobalISel] Lower unmerge to extract_subvector (PR #195046)

via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 30 02:40:55 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-globalisel

Author: David Green (davemgreen)

<details>
<summary>Changes</summary>

This follows and reuses the existing lowering for unmerge -> extract vector element, extending it to also lower unmerge -> subvector extract for half-sized vector extracts. This allows certain tablegen patterns to match.

An extra extract_subvector(dup) combine is needed to optimize away unnecessary instructions. The ext vs mov/dup brings us in-line with SDAG, but we may change both to use mov/dup.

---

Patch is 160.47 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/195046.diff


42 Files Affected:

- (modified) llvm/lib/Target/AArch64/AArch64Combine.td (+15-2) 
- (modified) llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp (+9) 
- (modified) llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerLowering.cpp (+16-3) 
- (modified) llvm/test/CodeGen/AArch64/GlobalISel/postlegalizer-combiner-unmergedup.mir (+6-3) 
- (modified) llvm/test/CodeGen/AArch64/GlobalISel/postlegalizer-lowering-unmerge-ext.mir (+7-6) 
- (modified) llvm/test/CodeGen/AArch64/aarch64-dup-ext.ll (+1-1) 
- (modified) llvm/test/CodeGen/AArch64/aarch64-matrix-umull-smull.ll (+13-13) 
- (modified) llvm/test/CodeGen/AArch64/aarch64-mulv.ll (+16-25) 
- (modified) llvm/test/CodeGen/AArch64/aarch64-smull.ll (+15-15) 
- (modified) llvm/test/CodeGen/AArch64/arm64-ext.ll (+3-3) 
- (modified) llvm/test/CodeGen/AArch64/arm64-extract_subvector.ll (+20-42) 
- (modified) llvm/test/CodeGen/AArch64/arm64-neon-2velem-high.ll (+36-36) 
- (modified) llvm/test/CodeGen/AArch64/arm64-neon-2velem.ll (+65-65) 
- (modified) llvm/test/CodeGen/AArch64/arm64-neon-3vdiff.ll (+1-1) 
- (modified) llvm/test/CodeGen/AArch64/arm64-neon-add-pairwise.ll (+3-3) 
- (modified) llvm/test/CodeGen/AArch64/arm64-neon-mul-div.ll (+4-4) 
- (modified) llvm/test/CodeGen/AArch64/arm64-vabs.ll (+4-4) 
- (modified) llvm/test/CodeGen/AArch64/arm64-vadd.ll (+1-1) 
- (modified) llvm/test/CodeGen/AArch64/arm64-vhadd.ll (+11-19) 
- (modified) llvm/test/CodeGen/AArch64/arm64-vmul.ll (+22-22) 
- (modified) llvm/test/CodeGen/AArch64/arm64-vshift.ll (+6-6) 
- (modified) llvm/test/CodeGen/AArch64/bitreverse.ll (+2-4) 
- (modified) llvm/test/CodeGen/AArch64/bswap.ll (+1-2) 
- (modified) llvm/test/CodeGen/AArch64/concat-vector.ll (+6-12) 
- (modified) llvm/test/CodeGen/AArch64/double_reduct.ll (+31-31) 
- (modified) llvm/test/CodeGen/AArch64/dup.ll (+8-16) 
- (modified) llvm/test/CodeGen/AArch64/ext-narrow-index.ll (+10-20) 
- (modified) llvm/test/CodeGen/AArch64/fptoi.ll (+4-8) 
- (modified) llvm/test/CodeGen/AArch64/highextractbitcast.ll (+25-46) 
- (modified) llvm/test/CodeGen/AArch64/neon-extadd.ll (+52-54) 
- (modified) llvm/test/CodeGen/AArch64/neon-perm.ll (+4-10) 
- (modified) llvm/test/CodeGen/AArch64/neon-shift-left-long.ll (+6-6) 
- (modified) llvm/test/CodeGen/AArch64/phi.ll (+4-8) 
- (modified) llvm/test/CodeGen/AArch64/reduce-and.ll (+6-6) 
- (modified) llvm/test/CodeGen/AArch64/reduce-or.ll (+6-6) 
- (modified) llvm/test/CodeGen/AArch64/reduce-xor.ll (+6-6) 
- (modified) llvm/test/CodeGen/AArch64/rem-by-const.ll (+35-43) 
- (modified) llvm/test/CodeGen/AArch64/rem.ll (+10-10) 
- (modified) llvm/test/CodeGen/AArch64/shift.ll (+6-12) 
- (modified) llvm/test/CodeGen/AArch64/st1-lane.ll (+42-90) 
- (modified) llvm/test/CodeGen/AArch64/vec-combine-compare-to-bitmask.ll (+1-1) 
- (modified) llvm/test/CodeGen/AArch64/vecreduce-fmul.ll (+22-22) 


``````````diff
diff --git a/llvm/lib/Target/AArch64/AArch64Combine.td b/llvm/lib/Target/AArch64/AArch64Combine.td
index fe953a627939d..5d26636fd3fb9 100644
--- a/llvm/lib/Target/AArch64/AArch64Combine.td
+++ b/llvm/lib/Target/AArch64/AArch64Combine.td
@@ -175,7 +175,7 @@ def form_duplane : GICombineRule <
 >;
 
 // Clean up G_UNMERGE(G_DUPLANE16) -> G_DUPLANE16
-class unmerge_duplane<Instruction Op> : GICombineRule <
+class unmerge_duplane<Instruction Op> : GICombineRule<
   (defs root:$root),
   (match (Op $a, $src, $c),
          (G_UNMERGE_VALUES $d1, $d2, $a):$root,
@@ -186,8 +186,21 @@ def unmerge_duplane8 : unmerge_duplane<G_DUPLANE8>;
 def unmerge_duplane16 : unmerge_duplane<G_DUPLANE16>;
 def unmerge_duplane32 : unmerge_duplane<G_DUPLANE32>;
 // G_DUPLANE64 is not included as the result in scalar.
+
+class extract_duplane<Instruction Op> : GICombineRule<
+  (defs root:$root),
+  (match (Op $a, $src, $c),
+         (G_EXTRACT_SUBVECTOR $d1, $a, $l):$root,
+         [{ return MRI.getType(${d1}.getReg()).getSizeInBits() == 64; }]),
+  (apply (Op $d1, $src, $c))
+>;
+def extract_duplane8 : extract_duplane<G_DUPLANE8>;
+def extract_duplane16 : extract_duplane<G_DUPLANE16>;
+def extract_duplane32 : extract_duplane<G_DUPLANE32>;
+
 def unmerge_duplanes : GICombineGroup<[unmerge_duplane8, unmerge_duplane16,
-                                       unmerge_duplane32]>;
+                                       unmerge_duplane32, extract_duplane8,
+                                       extract_duplane16, extract_duplane32]>;
 
 def shuffle_vector_lowering : GICombineGroup<[dup, form_duplane, rev, ext, zip,
                                               uzp, trn, fullrev, shuf_to_ins]>;
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 21e6440d8957c..ae27b5b86c6a6 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -7862,6 +7862,15 @@ AArch64InstructionSelector::selectExtractHigh(MachineOperand &Root) const {
       return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(ExtReg); }}};
     }
   }
+  if (Extract->MI->getOpcode() == TargetOpcode::G_EXTRACT_SUBVECTOR &&
+      Extract->MI->getNumOperands() == 3) {
+    LLT SrcTy = MRI.getType(Extract->MI->getOperand(1).getReg());
+    auto LaneIdx = Extract->MI->getOperand(2).getImm();
+    if (LaneIdx == SrcTy.getNumElements() / 2) {
+      Register ExtReg = Extract->MI->getOperand(1).getReg();
+      return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(ExtReg); }}};
+    }
+  }
 
   return std::nullopt;
 }
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerLowering.cpp b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerLowering.cpp
index 58aa2cc37c9b2..46fb14dbecf32 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerLowering.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerLowering.cpp
@@ -830,7 +830,9 @@ bool matchScalarizeVectorUnmerge(MachineInstr &MI, MachineRegisterInfo &MRI) {
   if (SrcTy.getSizeInBits() != 128 && SrcTy.getSizeInBits() != 64)
     return false;
   return SrcTy.isVector() && !SrcTy.isScalable() &&
-         Unmerge.getNumOperands() == (unsigned)SrcTy.getNumElements() + 1;
+         (Unmerge.getNumOperands() == (unsigned)SrcTy.getNumElements() + 1 ||
+          (Unmerge.getNumDefs() == 2 && SrcTy.getSizeInBits() == 128 &&
+           MRI.getType(Unmerge.getReg(0)).getSizeInBits() == 64));
 }
 
 void applyScalarizeVectorUnmerge(MachineInstr &MI, MachineRegisterInfo &MRI,
@@ -838,11 +840,22 @@ void applyScalarizeVectorUnmerge(MachineInstr &MI, MachineRegisterInfo &MRI,
   auto &Unmerge = cast<GUnmerge>(MI);
   Register Src1Reg = Unmerge.getReg(Unmerge.getNumOperands() - 1);
   const LLT SrcTy = MRI.getType(Src1Reg);
+  const LLT DstTy = MRI.getType(Unmerge.getReg(0));
   assert((SrcTy.isVector() && !SrcTy.isScalable()) &&
          "Expected a fixed length vector");
 
-  for (int I = 0; I < SrcTy.getNumElements(); ++I)
-    B.buildExtractVectorElementConstant(Unmerge.getReg(I), Src1Reg, I);
+  if (DstTy.isVector()) {
+    assert(Unmerge.getNumDefs() == 2);
+    if (!MRI.use_empty(Unmerge.getReg(0)))
+      B.buildExtractSubvector(Unmerge.getReg(0), Src1Reg, 0);
+    if (!MRI.use_empty(Unmerge.getReg(1)))
+      B.buildExtractSubvector(Unmerge.getReg(1), Src1Reg,
+                              SrcTy.getNumElements() / 2);
+  } else {
+    for (int I = 0; I < SrcTy.getNumElements(); ++I)
+      if (!MRI.use_empty(Unmerge.getReg(I)))
+        B.buildExtractVectorElementConstant(Unmerge.getReg(I), Src1Reg, I);
+  }
   MI.eraseFromParent();
 }
 
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/postlegalizer-combiner-unmergedup.mir b/llvm/test/CodeGen/AArch64/GlobalISel/postlegalizer-combiner-unmergedup.mir
index 0b533ff85fe86..1a9f8ed88ef4b 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/postlegalizer-combiner-unmergedup.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/postlegalizer-combiner-unmergedup.mir
@@ -10,8 +10,9 @@ body:             |
     ; CHECK: [[COPY:%[0-9]+]]:_(<16 x s8>) = COPY $q0
     ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
     ; CHECK-NEXT: [[DUPLANE8_:%[0-9]+]]:_(<8 x s8>) = G_DUPLANE8 [[COPY]], [[C]](s64)
+    ; CHECK-NEXT: [[DUPLANE8_1:%[0-9]+]]:_(<8 x s8>) = G_DUPLANE8 [[COPY]], [[C]](s64)
     ; CHECK-NEXT: $d0 = COPY [[DUPLANE8_]](<8 x s8>)
-    ; CHECK-NEXT: $d1 = COPY [[DUPLANE8_]](<8 x s8>)
+    ; CHECK-NEXT: $d1 = COPY [[DUPLANE8_1]](<8 x s8>)
     ; CHECK-NEXT: RET_ReallyLR implicit $x0
     %0:_(<16 x s8>) = COPY $q0
     %1:_(s64) = G_CONSTANT i64 1
@@ -31,8 +32,9 @@ body:             |
     ; CHECK: [[COPY:%[0-9]+]]:_(<8 x s16>) = COPY $q0
     ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
     ; CHECK-NEXT: [[DUPLANE16_:%[0-9]+]]:_(<4 x s16>) = G_DUPLANE16 [[COPY]], [[C]](s64)
+    ; CHECK-NEXT: [[DUPLANE16_1:%[0-9]+]]:_(<4 x s16>) = G_DUPLANE16 [[COPY]], [[C]](s64)
     ; CHECK-NEXT: $d0 = COPY [[DUPLANE16_]](<4 x s16>)
-    ; CHECK-NEXT: $d1 = COPY [[DUPLANE16_]](<4 x s16>)
+    ; CHECK-NEXT: $d1 = COPY [[DUPLANE16_1]](<4 x s16>)
     ; CHECK-NEXT: RET_ReallyLR implicit $x0
     %0:_(<8 x s16>) = COPY $q0
     %1:_(s64) = G_CONSTANT i64 1
@@ -52,8 +54,9 @@ body:             |
     ; CHECK: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0
     ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
     ; CHECK-NEXT: [[DUPLANE32_:%[0-9]+]]:_(<2 x s32>) = G_DUPLANE32 [[COPY]], [[C]](s64)
+    ; CHECK-NEXT: [[DUPLANE32_1:%[0-9]+]]:_(<2 x s32>) = G_DUPLANE32 [[COPY]], [[C]](s64)
     ; CHECK-NEXT: $d0 = COPY [[DUPLANE32_]](<2 x s32>)
-    ; CHECK-NEXT: $d1 = COPY [[DUPLANE32_]](<2 x s32>)
+    ; CHECK-NEXT: $d1 = COPY [[DUPLANE32_1]](<2 x s32>)
     ; CHECK-NEXT: RET_ReallyLR implicit $x0
     %0:_(<4 x s32>) = COPY $q0
     %1:_(s64) = G_CONSTANT i64 1
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/postlegalizer-lowering-unmerge-ext.mir b/llvm/test/CodeGen/AArch64/GlobalISel/postlegalizer-lowering-unmerge-ext.mir
index 2452c3083cc86..52ef2d3578b33 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/postlegalizer-lowering-unmerge-ext.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/postlegalizer-lowering-unmerge-ext.mir
@@ -11,7 +11,7 @@ body: |
     ; CHECK: liveins: $q0
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: %v1:_(<4 x s32>) = COPY $q0
-    ; CHECK-NEXT: %unused:_(<2 x s32>), %unmerge:_(<2 x s32>) = G_UNMERGE_VALUES %v1(<4 x s32>)
+    ; CHECK-NEXT: %unmerge:_(<2 x s32>) = G_EXTRACT_SUBVECTOR %v1(<4 x s32>), 2
     ; CHECK-NEXT: %fpext:_(<2 x s64>) = G_FPEXT %unmerge(<2 x s32>)
     ; CHECK-NEXT: $q0 = COPY %fpext(<2 x s64>)
     ; CHECK-NEXT: RET_ReallyLR implicit $q0
@@ -34,7 +34,7 @@ body: |
     ; CHECK: liveins: $q0
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: %v1:_(<8 x s16>) = COPY $q0
-    ; CHECK-NEXT: %unused:_(<4 x s16>), %unmerge:_(<4 x s16>) = G_UNMERGE_VALUES %v1(<8 x s16>)
+    ; CHECK-NEXT: %unmerge:_(<4 x s16>) = G_EXTRACT_SUBVECTOR %v1(<8 x s16>), 4
     ; CHECK-NEXT: %fpext:_(<4 x s32>) = G_FPEXT %unmerge(<4 x s16>)
     ; CHECK-NEXT: $q0 = COPY %fpext(<4 x s32>)
     ; CHECK-NEXT: RET_ReallyLR implicit $q0
@@ -57,7 +57,7 @@ body: |
     ; CHECK: liveins: $q0
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: %v1:_(<16 x s8>) = COPY $q0
-    ; CHECK-NEXT: %unused:_(<8 x s8>), %unmerge:_(<8 x s8>) = G_UNMERGE_VALUES %v1(<16 x s8>)
+    ; CHECK-NEXT: %unmerge:_(<8 x s8>) = G_EXTRACT_SUBVECTOR %v1(<16 x s8>), 8
     ; CHECK-NEXT: %fpext:_(<8 x s16>) = G_FPEXT %unmerge(<8 x s8>)
     ; CHECK-NEXT: $q0 = COPY %fpext(<8 x s16>)
     ; CHECK-NEXT: RET_ReallyLR implicit $q0
@@ -83,7 +83,7 @@ body: |
     ; CHECK-NEXT: %implicit:_(<16 x s8>) = G_IMPLICIT_DEF
     ; CHECK-NEXT: %C:_(s32) = COPY $w0
     ; CHECK-NEXT: %ext:_(<16 x s8>) = G_EXT %v1, %implicit, %C(s32)
-    ; CHECK-NEXT: %unmerge:_(<8 x s8>), %unused:_(<8 x s8>) = G_UNMERGE_VALUES %ext(<16 x s8>)
+    ; CHECK-NEXT: %unmerge:_(<8 x s8>) = G_EXTRACT_SUBVECTOR %ext(<16 x s8>), 0
     ; CHECK-NEXT: %fpext:_(<8 x s16>) = G_FPEXT %unmerge(<8 x s8>)
     ; CHECK-NEXT: $q0 = COPY %fpext(<8 x s16>)
     ; CHECK-NEXT: RET_ReallyLR implicit $q0
@@ -109,7 +109,8 @@ body: |
     ; CHECK-NEXT: %implicit:_(<16 x s8>) = G_IMPLICIT_DEF
     ; CHECK-NEXT: %C:_(s32) = G_CONSTANT i32 8
     ; CHECK-NEXT: %ext:_(<16 x s8>) = G_EXT %v1, %implicit, %C(s32)
-    ; CHECK-NEXT: %unmerge:_(<8 x s8>), %unused:_(<8 x s8>) = G_UNMERGE_VALUES %ext(<16 x s8>)
+    ; CHECK-NEXT: %unmerge:_(<8 x s8>) = G_EXTRACT_SUBVECTOR %ext(<16 x s8>), 0
+    ; CHECK-NEXT: %unused:_(<8 x s8>) = G_EXTRACT_SUBVECTOR %ext(<16 x s8>), 8
     ; CHECK-NEXT: %fpext:_(<8 x s16>) = G_FPEXT %unmerge(<8 x s8>)
     ; CHECK-NEXT: %fpext2:_(<8 x s16>) = G_FPEXT %unused(<8 x s8>)
     ; CHECK-NEXT: $q0 = COPY %fpext(<8 x s16>)
@@ -139,7 +140,7 @@ body: |
     ; CHECK-NEXT: %implicit:_(<4 x s32>) = G_IMPLICIT_DEF
     ; CHECK-NEXT: %C:_(s32) = G_CONSTANT i32 9
     ; CHECK-NEXT: %ext:_(<4 x s32>) = G_EXT %v1, %implicit, %C(s32)
-    ; CHECK-NEXT: %unmerge:_(<2 x s32>), %unused:_(<2 x s32>) = G_UNMERGE_VALUES %ext(<4 x s32>)
+    ; CHECK-NEXT: %unmerge:_(<2 x s32>) = G_EXTRACT_SUBVECTOR %ext(<4 x s32>), 0
     ; CHECK-NEXT: %fpext:_(<2 x s64>) = G_FPEXT %unmerge(<2 x s32>)
     ; CHECK-NEXT: $q0 = COPY %fpext(<2 x s64>)
     ; CHECK-NEXT: RET_ReallyLR implicit $q0
diff --git a/llvm/test/CodeGen/AArch64/aarch64-dup-ext.ll b/llvm/test/CodeGen/AArch64/aarch64-dup-ext.ll
index 9dfbe1a7f27e8..2334e0603ee43 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-dup-ext.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-dup-ext.ll
@@ -308,7 +308,7 @@ define <2 x i16> @dupsext_v2i8_v2i16(i8 %src, <2 x i8> %b) {
 ; CHECK-GI-NEXT:    sbfx w8, w8, #8, #8
 ; CHECK-GI-NEXT:    sshr v0.2s, v0.2s, #24
 ; CHECK-GI-NEXT:    dup v1.4h, w8
-; CHECK-GI-NEXT:    ushll v1.4s, v1.4h, #0
+; CHECK-GI-NEXT:    zip1 v1.4h, v1.4h, v1.4h
 ; CHECK-GI-NEXT:    mul v0.2s, v1.2s, v0.2s
 ; CHECK-GI-NEXT:    ret
 entry:
diff --git a/llvm/test/CodeGen/AArch64/aarch64-matrix-umull-smull.ll b/llvm/test/CodeGen/AArch64/aarch64-matrix-umull-smull.ll
index ea55c198a70f1..b6e9d248a2d26 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-matrix-umull-smull.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-matrix-umull-smull.ll
@@ -321,8 +321,8 @@ define void @larger_smull(ptr nocapture noundef readonly %x, i16 noundef %y, ptr
 ; CHECK-GI-NEXT:    mov x14, x11
 ; CHECK-GI-NEXT:    subs x13, x13, #16
 ; CHECK-GI-NEXT:    add x12, x12, #32
-; CHECK-GI-NEXT:    mov d3, v1.d[1]
-; CHECK-GI-NEXT:    mov d4, v2.d[1]
+; CHECK-GI-NEXT:    ext v3.16b, v1.16b, v1.16b, #8
+; CHECK-GI-NEXT:    ext v4.16b, v2.16b, v2.16b, #8
 ; CHECK-GI-NEXT:    smull v1.4s, v0.4h, v1.4h
 ; CHECK-GI-NEXT:    smull v2.4s, v0.4h, v2.4h
 ; CHECK-GI-NEXT:    smull v3.4s, v0.4h, v3.4h
@@ -481,8 +481,8 @@ define void @larger_umull(ptr nocapture noundef readonly %x, i16 noundef %y, ptr
 ; CHECK-GI-NEXT:    mov x13, x10
 ; CHECK-GI-NEXT:    subs x12, x12, #16
 ; CHECK-GI-NEXT:    add x11, x11, #32
-; CHECK-GI-NEXT:    mov d3, v1.d[1]
-; CHECK-GI-NEXT:    mov d4, v2.d[1]
+; CHECK-GI-NEXT:    ext v3.16b, v1.16b, v1.16b, #8
+; CHECK-GI-NEXT:    ext v4.16b, v2.16b, v2.16b, #8
 ; CHECK-GI-NEXT:    xtn v0.4h, v0.4s
 ; CHECK-GI-NEXT:    umull v1.4s, v0.4h, v1.4h
 ; CHECK-GI-NEXT:    umull v3.4s, v0.4h, v3.4h
@@ -909,10 +909,10 @@ define i64 @red_mla_dup_ext_u8_s8_s64(ptr noalias noundef readonly captures(none
 ; CHECK-GI-NEXT:    ushll2 v18.4s, v18.8h, #0
 ; CHECK-GI-NEXT:    ushll v20.4s, v17.4h, #0
 ; CHECK-GI-NEXT:    ushll2 v17.4s, v17.8h, #0
-; CHECK-GI-NEXT:    mov d21, v19.d[1]
-; CHECK-GI-NEXT:    mov d22, v18.d[1]
-; CHECK-GI-NEXT:    mov d23, v20.d[1]
-; CHECK-GI-NEXT:    mov d24, v17.d[1]
+; CHECK-GI-NEXT:    ext v21.16b, v19.16b, v19.16b, #8
+; CHECK-GI-NEXT:    ext v22.16b, v18.16b, v18.16b, #8
+; CHECK-GI-NEXT:    ext v23.16b, v20.16b, v20.16b, #8
+; CHECK-GI-NEXT:    ext v24.16b, v17.16b, v17.16b, #8
 ; CHECK-GI-NEXT:    smlal v0.2d, v16.2s, v19.2s
 ; CHECK-GI-NEXT:    smlal v2.2d, v16.2s, v18.2s
 ; CHECK-GI-NEXT:    smlal v4.2d, v16.2s, v20.2s
@@ -1176,7 +1176,7 @@ define void @sink_v4i64_1(ptr %p, ptr %d, i64 %n, <2 x i32> %a) {
 ; CHECK-GI-NEXT:    ldr q1, [x0]
 ; CHECK-GI-NEXT:    subs x2, x2, #8
 ; CHECK-GI-NEXT:    add x8, x8, #8
-; CHECK-GI-NEXT:    mov d2, v1.d[1]
+; CHECK-GI-NEXT:    ext v2.16b, v1.16b, v1.16b, #8
 ; CHECK-GI-NEXT:    smull v1.2d, v1.2s, v0.2s
 ; CHECK-GI-NEXT:    smull v2.2d, v2.2s, v0.2s
 ; CHECK-GI-NEXT:    shrn v1.2s, v1.2d, #15
@@ -1302,7 +1302,7 @@ define void @sink_v16s16_8(ptr %p, ptr %d, i64 %n, <16 x i8> %a) {
 ; CHECK-GI-NEXT:    ldr q1, [x0]
 ; CHECK-GI-NEXT:    subs x2, x2, #8
 ; CHECK-GI-NEXT:    add x8, x8, #8
-; CHECK-GI-NEXT:    mov d2, v1.d[1]
+; CHECK-GI-NEXT:    ext v2.16b, v1.16b, v1.16b, #8
 ; CHECK-GI-NEXT:    smull v1.8h, v1.8b, v0.8b
 ; CHECK-GI-NEXT:    smull v2.8h, v2.8b, v0.8b
 ; CHECK-GI-NEXT:    cmlt v1.8h, v1.8h, #0
@@ -1460,8 +1460,8 @@ define void @matrix_mul_unsigned_and_double(i32 %N, ptr nocapture %C, ptr nocapt
 ; CHECK-GI-NEXT:    ldur q2, [x9, #8]
 ; CHECK-GI-NEXT:    add x9, x1, w0, uxtw #2
 ; CHECK-GI-NEXT:    add w0, w0, #16
-; CHECK-GI-NEXT:    mov d3, v1.d[1]
-; CHECK-GI-NEXT:    mov d4, v2.d[1]
+; CHECK-GI-NEXT:    ext v3.16b, v1.16b, v1.16b, #8
+; CHECK-GI-NEXT:    ext v4.16b, v2.16b, v2.16b, #8
 ; CHECK-GI-NEXT:    umull v1.4s, v0.4h, v1.4h
 ; CHECK-GI-NEXT:    umull v2.4s, v0.4h, v2.4h
 ; CHECK-GI-NEXT:    umull v3.4s, v0.4h, v3.4h
@@ -1731,7 +1731,7 @@ define noundef <8 x i16> @cmplx_mul_combined_re_im(<8 x i16> noundef %a, i64 %sc
 ; CHECK-GI-NEXT:    sqneg v2.8h, v1.8h
 ; CHECK-GI-NEXT:    ldr q1, [x8, :lo12:.LCPI15_0]
 ; CHECK-GI-NEXT:    tbl v1.16b, { v2.16b, v3.16b }, v1.16b
-; CHECK-GI-NEXT:    mov d2, v0.d[1]
+; CHECK-GI-NEXT:    ext v2.16b, v0.16b, v0.16b, #8
 ; CHECK-GI-NEXT:    dup v3.8h, w0
 ; CHECK-GI-NEXT:    sqdmull v2.4s, v2.4h, v3.4h
 ; CHECK-GI-NEXT:    sqdmull v5.4s, v4.4h, v1.4h
diff --git a/llvm/test/CodeGen/AArch64/aarch64-mulv.ll b/llvm/test/CodeGen/AArch64/aarch64-mulv.ll
index fecc6554667fa..27cf4a116bda6 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-mulv.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-mulv.ll
@@ -146,7 +146,7 @@ define i8 @mulv_v16i8(<16 x i8> %a) {
 ;
 ; CHECK-GI-LABEL: mulv_v16i8:
 ; CHECK-GI:       // %bb.0: // %entry
-; CHECK-GI-NEXT:    mov d1, v0.d[1]
+; CHECK-GI-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
 ; CHECK-GI-NEXT:    mul v0.8b, v0.8b, v1.8b
 ; CHECK-GI-NEXT:    umov w8, v0.b[0]
 ; CHECK-GI-NEXT:    umov w9, v0.b[1]
@@ -194,8 +194,8 @@ define i8 @mulv_v32i8(<32 x i8> %a) {
 ;
 ; CHECK-GI-LABEL: mulv_v32i8:
 ; CHECK-GI:       // %bb.0: // %entry
-; CHECK-GI-NEXT:    mov d2, v0.d[1]
-; CHECK-GI-NEXT:    mov d3, v1.d[1]
+; CHECK-GI-NEXT:    ext v2.16b, v0.16b, v0.16b, #8
+; CHECK-GI-NEXT:    ext v3.16b, v1.16b, v1.16b, #8
 ; CHECK-GI-NEXT:    mul v0.8b, v0.8b, v2.8b
 ; CHECK-GI-NEXT:    mul v1.8b, v1.8b, v3.8b
 ; CHECK-GI-NEXT:    mul v0.8b, v0.8b, v1.8b
@@ -303,7 +303,7 @@ define i16 @mulv_v8i16(<8 x i16> %a) {
 ;
 ; CHECK-GI-LABEL: mulv_v8i16:
 ; CHECK-GI:       // %bb.0: // %entry
-; CHECK-GI-NEXT:    mov d1, v0.d[1]
+; CHECK-GI-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
 ; CHECK-GI-NEXT:    mul v0.4h, v0.4h, v1.4h
 ; CHECK-GI-NEXT:    umov w8, v0.h[0]
 ; CHECK-GI-NEXT:    umov w9, v0.h[1]
@@ -335,8 +335,8 @@ define i16 @mulv_v16i16(<16 x i16> %a) {
 ;
 ; CHECK-GI-LABEL: mulv_v16i16:
 ; CHECK-GI:       // %bb.0: // %entry
-; CHECK-GI-NEXT:    mov d2, v0.d[1]
-; CHECK-GI-NEXT:    mov d3, v1.d[1]
+; CHECK-GI-NEXT:    ext v2.16b, v0.16b, v0.16b, #8
+; CHECK-GI-NEXT:    ext v3.16b, v1.16b, v1.16b, #8
 ; CHECK-GI-NEXT:    mul v0.4h, v0.4h, v2.4h
 ; CHECK-GI-NEXT:    mul v1.4h, v1.4h, v3.4h
 ; CHECK-GI-NEXT:    mul v0.4h, v0.4h, v1.4h
@@ -384,23 +384,14 @@ entry:
 }
 
 define i32 @mulv_v4i32(<4 x i32> %a) {
-; CHECK-SD-LABEL: mulv_v4i32:
-; CHECK-SD:       // %bb.0: // %entry
-; CHECK-SD-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
-; CHECK-SD-NEXT:    mul v0.2s, v0.2s, v1.2s
-; CHECK-SD-NEXT:    mov w8, v0.s[1]
-; CHECK-SD-NEXT:    fmov w9, s0
-; CHECK-SD-NEXT:    mul w0, w9, w8
-; CHECK-SD-NEXT:    ret
-;
-; CHECK-GI-LABEL: mulv_v4i32:
-; CHECK-GI:       // %bb.0: // %entry
-; CHECK-GI-NEXT:    mov d1, v0.d[1]
-; CHECK-GI-NEXT:    mul v0.2s, v0.2s, v1.2s
-; CHECK-GI-NEXT:    mov w8, v0.s[1]
-; CHECK-GI-NEXT:    fmov w9, s0
-; CHECK-GI-NEXT:    mul w0, w9, w8
-; CHECK-GI-NEXT:    ret
+; CHECK-LABEL: mulv_v4i32:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
+; CHECK-NEXT:    mul v0.2s, v0.2s, v1.2s
+; CHECK-NEXT:    mov w8, v0.s[1]
+; CHECK-NEXT:    fmov w9, s0
+; CHECK-NEXT:    mul w0, w9, w8
+; CHECK-NEXT:    ret
 entry:
   %arg1 = call i32 @llvm.vector.reduce.mul.v4i32(<4 x i32> %a)
   ret i32 %arg1
@@ -419,8 +410,8 @@ define i32 @mulv_v8i32(<8 x i32> %a) {
 ;
 ; CHECK-GI-LABEL: mulv_v8i32:
 ; CHECK-GI:       // %bb.0: // %entry
-; CHECK-GI-NEXT:    mov d2, v0.d[1]
-; CHECK-GI-NEXT:    mov d3, v1.d[1]
+; CHECK-GI-NEXT:    ext v2.16b, v0.16b, v0.16b, #8
+; CHECK-GI-NEXT:    ext v3.16b, v1.16b, v1.16b, #8
 ; CHECK-GI-NEXT:    mul v0.2s, v0.2s, v2.2s
 ; CHECK-GI-NEXT:    mul v1.2s, v1.2s, v3.2s
 ; CHECK-GI-NEXT:    mul v0.2s, v0.2s, v1.2s
diff --git a/llvm/test/CodeGen/AArch64/aarch64-smull.ll b/llvm/test/CodeGen/AArch64/aarch64-smull.ll
index 5896b408be49c..ee5b2e00c6a69 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-smull.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-smull.ll
@@ -1726,7 +1726,7 @@ define <8 x i32> @umull_and_v8i32(<8 x i16> %src1, <8 x i32> %src2) {
 ; CHECK-GI-NEXT:    movi v3.2d, #0x0000ff000000ff
 ; CHECK-GI-NEXT:    and v1.16b, v1.16b, v3.16b
 ; CHECK-GI-NEXT:    and v2.16b, v2.16b, v3.16b
-; CHECK-GI-NEXT:    mov d3, v0.d[1]
+; CHECK-GI-NEXT:    ext v3.16b, v0.16b, v0.16b, #8
 ; CHECK-GI-NEXT:    xtn v1.4h, v1.4s
 ; CHECK-GI-NEXT:    xtn v2.4h, v2.4s
 ; CHECK-GI-NEXT:    umull v0.4s, v0.4h, v1.4h
@@ -1759,7 +1759,7 @@ define <8 x i32> @umull_and_v8i32_dup(<8 x i16> %src1, i32 %src2) {
 ; CHECK-GI-LABEL: umull_and_v8i32_dup:
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    and w8, w0, #0xff
-; CHECK-GI-NEXT:    mov d2, v0.d[1]
+; CHECK-GI-NEXT:    ext v2.16b, v0.16b, v0.16b, #8
 ; CHECK-GI-NEXT:    dup v1.4s, w8
 ; CHECK-GI-NEXT:    xtn v1.4h, v1.4s
 ; CHECK-GI-NEXT:    umull v0.4s, v0.4h, v1.4h
@@ -1832,7 +1832,7 @@ define <4 x i64> @umull_and_v4i64(<4 x i32> %src1, <4 x i64> %src2) {
 ; CHECK-GI-NEXT:    movi v3.2d, #0x000000000000ff
 ; CHECK-GI-NEXT:    and v1.16b, v1.16b, v3.16b
 ; CHECK-GI-NEXT:    and v2.16b, v2.16b, v3.16b
-; CHECK-GI-NEXT:    mov d3, v0.d[1]
+; CHECK-GI-NEXT:    ext v3.16b, v0.16b, v0.16b, #8
 ; CHECK-GI-NEXT:    xtn v1.2s, v1.2d
 ; CHECK-GI-NEXT:    xtn v2.2s, v2.2d
 ; CHECK-GI-NEXT:    umull v0.2d, v0.2s, v1.2s
@@ -1865,7 +1865,7 @@ define <4 x i64> @umull_and_v4i64_dup(<4 x i32> %src1, i64 %src2) {
 ; CHECK-GI-LABEL: umull_and_v4i64_dup:
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    and x8, x0, #0xff
-; CHECK-GI-NEXT:    mov d2, v0.d[1]
+; CHECK-GI-NEXT:    ext v2.16b, v0.16b, v0.16b, #8
 ; CHECK-GI-NEXT:    dup v1.2d, x8
 ; CHECK-GI-NEXT:    xtn v1.2s, v1.2d
 ; CHECK-GI-NEXT:    umull v0.2d, v0.2s, v1.2s
@@ -1902,7 +1902,7 @@ define void @pmlsl2_v8i16_uzp1(<16 x i8> %0, <8 x i16> %1, ptr %2, ptr %3) {
 ; CHECK-GI-LABEL: pmlsl2_v8i16_uzp1:
 ; CHECK-GI:       // %bb.0:
 ; CHECK-GI-NEXT:    ldr q2, [x1, #16]
-; CHECK-GI-NEXT:    mov d0, v0.d[1]
+; CHECK...
[truncated]

``````````

</details>


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


More information about the llvm-commits mailing list