[llvm] [RISCV][GlobalISel] Legalize Scalable Vector Loads (PR #84965)

Jiahan Xie via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 26 11:00:56 PDT 2024


https://github.com/jiahanxie353 updated https://github.com/llvm/llvm-project/pull/84965

>From a5ed4aa7bfba09dd070fb9b26a04f4253ad2c3f7 Mon Sep 17 00:00:00 2001
From: jiahanxie353 <jx353 at cornell.edu>
Date: Sun, 24 Mar 2024 20:11:14 -0400
Subject: [PATCH 1/2] memory type can be scalable vector and we take the known
 min value

---
 llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index c3a23ea0ad3738..76db2c344796c8 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -3330,8 +3330,9 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerLoad(GAnyLoad &LoadMI) {
   LLT MemTy = MMO.getMemoryType();
   MachineFunction &MF = MIRBuilder.getMF();
 
-  unsigned MemSizeInBits = MemTy.getSizeInBits();
-  unsigned MemStoreSizeInBits = 8 * MemTy.getSizeInBytes();
+  unsigned MinMemSizeInBits = MemTy.getSizeInBits().getKnownMinValue();
+  unsigned MinMemStoreSizeInBits =
+      8 * MemTy.getSizeInBytes().getKnownMinValue();
 
   if (MemSizeInBits != MemStoreSizeInBits) {
     if (MemTy.isVector())

>From 9ce3a848fddb3cdc40f47ae35dae205d49459fb3 Mon Sep 17 00:00:00 2001
From: jiahanxie353 <jx353 at cornell.edu>
Date: Mon, 25 Mar 2024 12:16:36 -0400
Subject: [PATCH 2/2] legalize vload and vstore nxv1s8

---
 .../CodeGen/GlobalISel/LegalizerHelper.cpp    | 18 +++++------
 llvm/lib/CodeGen/MIRParser/MIParser.cpp       |  2 +-
 .../Target/RISCV/GISel/RISCVLegalizerInfo.cpp |  6 +++-
 .../legalizer/rvv/legalize-load.mir           | 29 ++++++++++++++++++
 .../legalizer/rvv/legalize-store.mir          | 30 +++++++++++++++++++
 5 files changed, 74 insertions(+), 11 deletions(-)
 create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-load.mir
 create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-store.mir

diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 76db2c344796c8..603d7d63614579 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -3334,13 +3334,13 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerLoad(GAnyLoad &LoadMI) {
   unsigned MinMemStoreSizeInBits =
       8 * MemTy.getSizeInBytes().getKnownMinValue();
 
-  if (MemSizeInBits != MemStoreSizeInBits) {
+  if (MinMemSizeInBits != MinMemStoreSizeInBits) {
     if (MemTy.isVector())
       return UnableToLegalize;
 
     // Promote to a byte-sized load if not loading an integral number of
     // bytes.  For example, promote EXTLOAD:i20 -> EXTLOAD:i24.
-    LLT WideMemTy = LLT::scalar(MemStoreSizeInBits);
+    LLT WideMemTy = LLT::scalar(MinMemStoreSizeInBits);
     MachineMemOperand *NewMMO =
         MF.getMachineMemOperand(&MMO, MMO.getPointerInfo(), WideMemTy);
 
@@ -3349,19 +3349,19 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerLoad(GAnyLoad &LoadMI) {
 
     // If this wasn't already an extending load, we need to widen the result
     // register to avoid creating a load with a narrower result than the source.
-    if (MemStoreSizeInBits > DstTy.getSizeInBits()) {
+    if (MinMemStoreSizeInBits > DstTy.getSizeInBits()) {
       LoadTy = WideMemTy;
       LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
     }
 
     if (isa<GSExtLoad>(LoadMI)) {
       auto NewLoad = MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
-      MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
+      MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MinMemSizeInBits);
     } else if (isa<GZExtLoad>(LoadMI) || WideMemTy == LoadTy) {
       auto NewLoad = MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
       // The extra bits are guaranteed to be zero, since we stored them that
       // way.  A zext load from Wide thus automatically gives zext from MemVT.
-      MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
+      MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MinMemSizeInBits);
     } else {
       MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
     }
@@ -3394,10 +3394,10 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerLoad(GAnyLoad &LoadMI) {
 
   uint64_t LargeSplitSize, SmallSplitSize;
 
-  if (!isPowerOf2_32(MemSizeInBits)) {
+  if (!isPowerOf2_32(MinMemSizeInBits)) {
     // This load needs splitting into power of 2 sized loads.
-    LargeSplitSize = llvm::bit_floor(MemSizeInBits);
-    SmallSplitSize = MemSizeInBits - LargeSplitSize;
+    LargeSplitSize = llvm::bit_floor(MinMemSizeInBits);
+    SmallSplitSize = MinMemSizeInBits - LargeSplitSize;
   } else {
     // This is already a power of 2, but we still need to split this in half.
     //
@@ -3407,7 +3407,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerLoad(GAnyLoad &LoadMI) {
     if (TLI.allowsMemoryAccess(Ctx, MIRBuilder.getDataLayout(), MemTy, MMO))
       return UnableToLegalize;
 
-    SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
+    SmallSplitSize = LargeSplitSize = MinMemSizeInBits / 2;
   }
 
   if (MemTy.isVector()) {
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 95924f0566283b..1cbc4e408b86f4 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -3421,7 +3421,7 @@ bool MIParser::parseMachineMemoryOperand(MachineMemOperand *&Dest) {
     if (expectAndConsume(MIToken::rparen))
       return true;
 
-    Size = MemoryType.getSizeInBytes();
+    Size = MemoryType.getSizeInBytes().getKnownMinValue();
   }
 
   MachinePointerInfo Ptr = MachinePointerInfo();
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index 941ad752bfd9d4..803dae97dc10a8 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -249,7 +249,11 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
           .legalForTypesWithMemDesc({{s32, p0, s8, 8},
                                      {s32, p0, s16, 16},
                                      {s32, p0, s32, 32},
-                                     {p0, p0, sXLen, XLen}});
+                                     {p0, p0, sXLen, XLen},
+                                     {nxv1s8, p0, nxv1s8, 8}})
+          .widenScalarToNextPow2(0, /* MinSize = */ 8)
+          .lowerIfMemSizeNotByteSizePow2();
+
   auto &ExtLoadActions =
       getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
           .legalForTypesWithMemDesc({{s32, p0, s8, 8}, {s32, p0, s16, 16}});
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-load.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-load.mir
new file mode 100644
index 00000000000000..1b62f555207165
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-load.mir
@@ -0,0 +1,29 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=riscv32 -mattr=+v -run-pass=legalizer %s -o - | FileCheck %s
+# RUN: llc -mtriple=riscv64 -mattr=+v -run-pass=legalizer %s -o - | FileCheck %s
+--- |
+
+  define <vscale x 1 x i8> @vload_nx1i8(ptr %pa) {
+    %va = load <vscale x 1 x i8>, ptr %pa
+    ret <vscale x 1 x i8> %va
+  }
+
+...
+---
+name:            vload_nx1i8
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $x10
+
+    ; CHECK-LABEL: name: vload_nx1i8
+    ; CHECK: liveins: $x10
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10
+    ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 1 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 1 x s8>) from %ir.pa)
+    ; CHECK-NEXT: $v8 = COPY [[LOAD]](<vscale x 1 x s8>)
+    ; CHECK-NEXT: PseudoRET implicit $v8
+    %0:_(p0) = COPY $x10
+    %1:_(<vscale x 1 x s8>) = G_LOAD %0(p0) :: (load (<vscale x 1 x s8>) from %ir.pa)
+    $v8 = COPY %1(<vscale x 1 x s8>)
+    PseudoRET implicit $v8
+
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-store.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-store.mir
new file mode 100644
index 00000000000000..b947861f7be503
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-store.mir
@@ -0,0 +1,30 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=riscv32 -mattr=+v -run-pass=legalizer %s -o - | FileCheck %s
+# RUN: llc -mtriple=riscv64 -mattr=+v -run-pass=legalizer %s -o - | FileCheck %s
+--- |
+
+  define void @vstore_nx1i8(ptr %pa, <vscale x 1 x i8> %b) {
+    store <vscale x 1 x i8> %b, ptr %pa, align 1
+    ret void
+  }
+
+...
+---
+name:            vstore_nx1i8
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $v8, $x10
+
+    ; CHECK-LABEL: name: vstore_nx1i8
+    ; CHECK: liveins: $v8, $x10
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<vscale x 1 x s8>) = COPY $v8
+    ; CHECK-NEXT: G_STORE [[COPY1]](<vscale x 1 x s8>), [[COPY]](p0) :: (store (<vscale x 1 x s8>) into %ir.pa)
+    ; CHECK-NEXT: PseudoRET
+    %0:_(p0) = COPY $x10
+    %1:_(<vscale x 1 x s8>) = COPY $v8
+    G_STORE %1(<vscale x 1 x s8>), %0(p0) :: (store (<vscale x 1 x s8>) into %ir.pa)
+    PseudoRET
+
+...



More information about the llvm-commits mailing list