[llvm] [RISCV][GISel] Add manual isel for s16 load/store for the GPR bank. (PR #116111)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 13 13:56:42 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-globalisel
Author: Craig Topper (topperc)
<details>
<summary>Changes</summary>
In order to support f16 load/store we need to make load/stores with s16 register type legal. If regbank selection doesn't pick the FPR bank, we'll be left with a GPR load or store which we don't have isel patterns for. We can't add the isel patterns because i16 isn't a legal type for the GPR register class.
Code was adapted from AArch64's manual selection code.
---
Full diff: https://github.com/llvm/llvm-project/pull/116111.diff
5 Files Affected:
- (modified) llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp (+65)
- (modified) llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/load-rv32.mir (+24-1)
- (modified) llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/load-rv64.mir (+24-1)
- (modified) llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/store-rv32.mir (+24-1)
- (modified) llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/store-rv64.mir (+24-1)
``````````diff
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 3c95f01b86361c..c10c32e65a7fa1 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -580,6 +580,23 @@ static void getOperandsForBranch(Register CondReg, RISCVCC::CondCode &CC,
CC = getRISCVCCFromICmp(Pred);
}
+/// Select the RISC-V opcode for the G_LOAD or G_STORE operation \p GenericOpc,
+/// appropriate for the (value) register bank \p RegBankID and of memory access
+/// size \p OpSize.
+/// \returns \p GenericOpc if the combination is unsupported.
+static unsigned selectLoadStoreOp(unsigned GenericOpc, unsigned RegBankID,
+ unsigned OpSize) {
+ const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
+ if (RegBankID == RISCV::GPRBRegBankID) {
+ switch (OpSize) {
+ case 16:
+ return IsStore ? RISCV::SH : RISCV::LH;
+ }
+ }
+
+ return GenericOpc;
+}
+
bool RISCVInstructionSelector::select(MachineInstr &MI) {
MachineBasicBlock &MBB = *MI.getParent();
MachineFunction &MF = *MBB.getParent();
@@ -786,6 +803,54 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
return selectMergeValues(MI, MIB);
case TargetOpcode::G_UNMERGE_VALUES:
return selectUnmergeValues(MI, MIB);
+ case TargetOpcode::G_LOAD:
+ case TargetOpcode::G_STORE: {
+ GLoadStore &LdSt = cast<GLoadStore>(MI);
+ LLT PtrTy = MRI->getType(LdSt.getPointerReg());
+
+ if (PtrTy != LLT::pointer(0, STI.getXLen())) {
+ LLVM_DEBUG(dbgs() << "Load/Store pointer has type: " << PtrTy
+ << ", expected: " << LLT::pointer(0, STI.getXLen())
+ << '\n');
+ return false;
+ }
+
+#ifndef NDEBUG
+ const RegisterBank &PtrRB =
+ *RBI.getRegBank(LdSt.getPointerReg(), *MRI, TRI);
+ // Check that the pointer register is valid.
+ assert(PtrRB.getID() == RISCV::GPRBRegBankID &&
+ "Load/Store pointer operand isn't a GPR");
+#endif
+
+ unsigned MemSizeInBits = LdSt.getMemSizeInBits().getValue();
+
+ const Register ValReg = LdSt.getReg(0);
+ const RegisterBank &RB = *RBI.getRegBank(ValReg, *MRI, TRI);
+
+ const unsigned NewOpc =
+ selectLoadStoreOp(MI.getOpcode(), RB.getID(), MemSizeInBits);
+ if (NewOpc == MI.getOpcode())
+ return false;
+
+ // Check if we can fold anything into the addressing mode.
+ auto AddrModeFns = selectAddrRegImm(MI.getOperand(1));
+ if (!AddrModeFns)
+ return false;
+
+ // Folded something. Create a new instruction and return it.
+ auto NewInst = MIB.buildInstr(NewOpc, {}, {}, MI.getFlags());
+ if (isa<GStore>(MI))
+ NewInst.addUse(ValReg);
+ else
+ NewInst.addDef(ValReg);
+ NewInst.cloneMemRefs(MI);
+ for (auto &Fn : *AddrModeFns)
+ Fn(NewInst);
+ MI.eraseFromParent();
+
+ return constrainSelectedInstRegOperands(*NewInst, TII, TRI, RBI);
+ }
default:
return false;
}
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/load-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/load-rv32.mir
index 36c604d4f5c529..3964fd1a918aa4 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/load-rv32.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/load-rv32.mir
@@ -1,6 +1,6 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple=riscv32 -run-pass=instruction-select %s -o - \
-# RUN: | FileCheck %s
+# RUN: -disable-gisel-legality-check | FileCheck %s
---
name: load_i8
@@ -45,6 +45,29 @@ body: |
$x10 = COPY %1(s32)
PseudoRET implicit $x10
+...
+---
+name: load_i16_i16
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x10
+
+ ; CHECK-LABEL: name: load_i16_i16
+ ; CHECK: liveins: $x10
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[LH:%[0-9]+]]:gpr = LH [[COPY]], 0 :: (load (s16))
+ ; CHECK-NEXT: $x10 = COPY [[LH]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:gprb(p0) = COPY $x10
+ %1:gprb(s16) = G_LOAD %0(p0) :: (load (s16))
+ %2:gprb(s32) = G_ANYEXT %1
+ $x10 = COPY %2(s32)
+ PseudoRET implicit $x10
+
...
---
name: load_i32
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/load-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/load-rv64.mir
index 647e1e5287a80b..70dd2bfee28ba1 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/load-rv64.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/load-rv64.mir
@@ -1,6 +1,6 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple=riscv64 -run-pass=instruction-select %s -o - \
-# RUN: | FileCheck %s
+# RUN: -disable-gisel-legality-check | FileCheck %s
---
name: load_i8_i64
@@ -45,6 +45,29 @@ body: |
$x10 = COPY %1(s64)
PseudoRET implicit $x10
+...
+---
+name: load_i16_i16
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x10
+
+ ; CHECK-LABEL: name: load_i16_i16
+ ; CHECK: liveins: $x10
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[LH:%[0-9]+]]:gpr = LH [[COPY]], 0 :: (load (s16))
+ ; CHECK-NEXT: $x10 = COPY [[LH]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:gprb(p0) = COPY $x10
+ %1:gprb(s16) = G_LOAD %0(p0) :: (load (s16))
+ %2:gprb(s64) = G_ANYEXT %1
+ $x10 = COPY %2(s64)
+ PseudoRET implicit $x10
+
...
---
name: load_i32_i64
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/store-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/store-rv32.mir
index e4111417ece672..f1cc69517cf8f7 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/store-rv32.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/store-rv32.mir
@@ -1,6 +1,6 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple=riscv32 -run-pass=instruction-select %s -o - \
-# RUN: | FileCheck %s
+# RUN: -disable-gisel-legality-check | FileCheck %s
#
---
name: store_i8
@@ -45,6 +45,29 @@ body: |
G_STORE %0(s32), %1(p0) :: (store (s16))
PseudoRET
+...
+---
+name: store_i16_i16
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x10, $x11
+
+ ; CHECK-LABEL: name: store_i16_i16
+ ; CHECK: liveins: $x10, $x11
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
+ ; CHECK-NEXT: SH [[COPY]], [[COPY1]], 0 :: (store (s16))
+ ; CHECK-NEXT: PseudoRET
+ %0:gprb(s32) = COPY $x10
+ %1:gprb(p0) = COPY $x11
+ %2:gprb(s16) = G_TRUNC %0
+ G_STORE %2(s16), %1(p0) :: (store (s16))
+ PseudoRET
+
...
---
name: store_i32
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/store-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/store-rv64.mir
index 385a330a97a175..69f590c1df5970 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/store-rv64.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/store-rv64.mir
@@ -1,6 +1,6 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple=riscv64 -run-pass=instruction-select %s -o - \
-# RUN: | FileCheck %s
+# RUN: -disable-gisel-legality-check | FileCheck %s
---
name: store_i8_i64
@@ -45,6 +45,29 @@ body: |
G_STORE %0(s64), %1(p0) :: (store (s16))
PseudoRET
+...
+---
+name: store_i16_i16
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x10, $x11
+
+ ; CHECK-LABEL: name: store_i16_i16
+ ; CHECK: liveins: $x10, $x11
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
+ ; CHECK-NEXT: SH [[COPY]], [[COPY1]], 0 :: (store (s16))
+ ; CHECK-NEXT: PseudoRET
+ %0:gprb(s64) = COPY $x10
+ %1:gprb(p0) = COPY $x11
+ %2:gprb(s16) = G_TRUNC %0
+ G_STORE %2(s16), %1(p0) :: (store (s16))
+ PseudoRET
+
...
---
name: store_i32_i64
``````````
</details>
https://github.com/llvm/llvm-project/pull/116111
More information about the llvm-commits
mailing list