[llvm] [ARM] Add MVE support to canCombineStoreAndExtract (PR #194649)

via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 28 07:58:23 PDT 2026


https://github.com/LumioseSil created https://github.com/llvm/llvm-project/pull/194649

MVE can do a store + vector extract on any vector that fits perfectly in a Q register.

>From c846e2d9c06be6d93010d7964fa2d39240f64292 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Tue, 28 Apr 2026 10:55:03 -0400
Subject: [PATCH 1/2] Pre-commit test (NFC)

---
 llvm/test/CodeGen/ARM/vector-promotion.ll | 47 +++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/llvm/test/CodeGen/ARM/vector-promotion.ll b/llvm/test/CodeGen/ARM/vector-promotion.ll
index 344014ad80449..4e3fdd0d353ba 100644
--- a/llvm/test/CodeGen/ARM/vector-promotion.ll
+++ b/llvm/test/CodeGen/ARM/vector-promotion.ll
@@ -1,6 +1,9 @@
 ; RUN: opt -passes='require<profile-summary>,function(codegenprepare)' -mtriple=thumbv7-apple-ios %s -o - -mattr=+neon -S | FileCheck --check-prefix=IR-BOTH --check-prefix=IR-NORMAL %s
 ; RUN: opt -passes='require<profile-summary>,function(codegenprepare)' -mtriple=thumbv7-apple-ios %s -o - -mattr=+neon -S -stress-cgp-store-extract | FileCheck --check-prefix=IR-BOTH --check-prefix=IR-STRESS %s
 ; RUN: llc -mtriple=thumbv7-apple-ios %s -o - -mattr=+neon | FileCheck --check-prefix=ASM %s
+; RUN: opt -passes='require<profile-summary>,function(codegenprepare)' -mtriple=thumbv8.1m.main-none-eabi %s -o - -mattr=+mve -S | FileCheck --check-prefix=IR-MVE %s
+; RUN: opt -passes='require<profile-summary>,function(codegenprepare)' -mtriple=thumbv8.1m.main-none-eabi %s -o - -mattr=+mve -S -stress-cgp-store-extract | FileCheck --check-prefix=IR-MVE-STRESS %s
+; RUN: llc -mtriple=thumbv8.1m.main-none-eabi %s -o - -mattr=+mve | FileCheck --check-prefix=ASM-MVE %s
 
 ; IR-BOTH-LABEL: @simpleOneInstructionPromotion
 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x i32>, ptr %addr1
@@ -393,3 +396,47 @@ define void @simpleOneInstructionPromotion4x32(ptr %addr1, ptr %dest) {
   store i32 %out, ptr %dest, align 1
   ret void
 }
+
+; MVE only supports the Q-register (128-bit) case for this combine.
+; IR-MVE-LABEL: @simpleOneInstructionPromotionMVE4x32
+; IR-MVE: [[LOAD:%[a-zA-Z_0-9-]+]] = load <4 x i32>, ptr %addr1
+; IR-MVE-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <4 x i32> [[LOAD]], i32 1
+; IR-MVE-NEXT: [[OUT:%[a-zA-Z_0-9-]+]] = or i32 [[EXTRACT]], 1
+; IR-MVE-NEXT: store i32 [[OUT]], ptr %dest
+; IR-MVE-NEXT: ret
+; IR-MVE-STRESS-LABEL: @simpleOneInstructionPromotionMVE4x32
+; IR-MVE-STRESS: [[LOAD:%[a-zA-Z_0-9-]+]] = load <4 x i32>, ptr %addr1
+; IR-MVE-STRESS-NEXT: [[VECTOR_OR:%[a-zA-Z_0-9-]+]] = or <4 x i32> [[LOAD]], <i32 poison, i32 1, i32 poison, i32 poison>
+; IR-MVE-STRESS-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <4 x i32> [[VECTOR_OR]], i32 1
+; IR-MVE-STRESS-NEXT: store i32 [[EXTRACT]], ptr %dest
+; IR-MVE-STRESS-NEXT: ret
+; ASM-MVE-LABEL: simpleOneInstructionPromotionMVE4x32:
+define void @simpleOneInstructionPromotionMVE4x32(ptr %addr1, ptr %dest) {
+  %in1 = load <4 x i32>, ptr %addr1, align 16
+  %extract = extractelement <4 x i32> %in1, i32 1
+  %out = or i32 %extract, 1
+  store i32 %out, ptr %dest, align 4
+  ret void
+}
+
+; For MVE-only targets, 64-bit vectors should not use this combine.
+; IR-MVE-LABEL: @simpleOneInstructionPromotionMVE2x32
+; IR-MVE: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x i32>, ptr %addr1
+; IR-MVE-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <2 x i32> [[LOAD]], i32 1
+; IR-MVE-NEXT: [[OUT:%[a-zA-Z_0-9-]+]] = or i32 [[EXTRACT]], 1
+; IR-MVE-NEXT: store i32 [[OUT]], ptr %dest
+; IR-MVE-NEXT: ret
+; IR-MVE-STRESS-LABEL: @simpleOneInstructionPromotionMVE2x32
+; IR-MVE-STRESS: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x i32>, ptr %addr1
+; IR-MVE-STRESS-NEXT: [[VECTOR_OR:%[a-zA-Z_0-9-]+]] = or <2 x i32> [[LOAD]], <i32 poison, i32 1>
+; IR-MVE-STRESS-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <2 x i32> [[VECTOR_OR]], i32 1
+; IR-MVE-STRESS-NEXT: store i32 [[EXTRACT]], ptr %dest
+; IR-MVE-STRESS-NEXT: ret
+; ASM-MVE-LABEL: simpleOneInstructionPromotionMVE2x32:
+define void @simpleOneInstructionPromotionMVE2x32(ptr %addr1, ptr %dest) {
+  %in1 = load <2 x i32>, ptr %addr1, align 8
+  %extract = extractelement <2 x i32> %in1, i32 1
+  %out = or i32 %extract, 1
+  store i32 %out, ptr %dest, align 4
+  ret void
+}

>From f58964fab80d4d0efe9c7389ae2dff19bc17bba2 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Tue, 28 Apr 2026 10:57:54 -0400
Subject: [PATCH 2/2] [ARM] Add MVE support to canCombineStoreAndExtract

MVE can do a store + vector extract on any vector that fits perfectly in a Q register.
---
 llvm/lib/Target/ARM/ARMISelLowering.cpp   | 11 ++++++++---
 llvm/test/CodeGen/ARM/vector-promotion.ll |  6 +++---
 2 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 17d57c1a24407..75fa5cefbf6b3 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -21436,8 +21436,8 @@ void ARMTargetLowering::insertSSPDeclarations(
 
 bool ARMTargetLowering::canCombineStoreAndExtract(Type *VectorTy, Value *Idx,
                                                   unsigned &Cost) const {
-  // If we do not have NEON, vector types are not natively supported.
-  if (!Subtarget->hasNEON())
+  // If we do not have NEON or MVE, vector types are not natively supported.
+  if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
     return false;
 
   // Floating point values and vector values map to the same register file.
@@ -21456,7 +21456,12 @@ bool ARMTargetLowering::canCombineStoreAndExtract(Type *VectorTy, Value *Idx,
   unsigned BitWidth = VectorTy->getPrimitiveSizeInBits().getFixedValue();
   // We can do a store + vector extract on any vector that fits perfectly in a D
   // or Q register.
-  if (BitWidth == 64 || BitWidth == 128) {
+  if (Subtarget->hasNEON() && (BitWidth == 64 || BitWidth == 128)) {
+    Cost = 0;
+    return true;
+  }
+
+  if (Subtarget->hasMVEIntegerOps() && BitWidth == 128) {
     Cost = 0;
     return true;
   }
diff --git a/llvm/test/CodeGen/ARM/vector-promotion.ll b/llvm/test/CodeGen/ARM/vector-promotion.ll
index 4e3fdd0d353ba..59916a5a6fcdc 100644
--- a/llvm/test/CodeGen/ARM/vector-promotion.ll
+++ b/llvm/test/CodeGen/ARM/vector-promotion.ll
@@ -400,9 +400,9 @@ define void @simpleOneInstructionPromotion4x32(ptr %addr1, ptr %dest) {
 ; MVE only supports the Q-register (128-bit) case for this combine.
 ; IR-MVE-LABEL: @simpleOneInstructionPromotionMVE4x32
 ; IR-MVE: [[LOAD:%[a-zA-Z_0-9-]+]] = load <4 x i32>, ptr %addr1
-; IR-MVE-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <4 x i32> [[LOAD]], i32 1
-; IR-MVE-NEXT: [[OUT:%[a-zA-Z_0-9-]+]] = or i32 [[EXTRACT]], 1
-; IR-MVE-NEXT: store i32 [[OUT]], ptr %dest
+; IR-MVE-NEXT: [[VECTOR_OR:%[a-zA-Z_0-9-]+]] = or <4 x i32> [[LOAD]], <i32 poison, i32 1, i32 poison, i32 poison>
+; IR-MVE-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <4 x i32> [[VECTOR_OR]], i32 1
+; IR-MVE-NEXT: store i32 [[EXTRACT]], ptr %dest
 ; IR-MVE-NEXT: ret
 ; IR-MVE-STRESS-LABEL: @simpleOneInstructionPromotionMVE4x32
 ; IR-MVE-STRESS: [[LOAD:%[a-zA-Z_0-9-]+]] = load <4 x i32>, ptr %addr1



More information about the llvm-commits mailing list