From 4928effc2ef653e0bdc54bb79f8015c696e21436 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 13 Nov 2024 21:00:27 -0800 Subject: [PATCH 1/4] [RISCV] Add an implementation of findRepresentativeClass to assign i32 to GPRRegClass for RV64. This is an alternative fix for #81192. This allows the SelectionDAG scheduler to be able to find a register class for i32 on RV64. The default implementation of findRepresentativeClass only works for legal types which i32 is not for RV64. I wanted to remove i32 from the GPR register class to fix the issue, but we need to be able to write some i32 patterns for GISel. And now it looks like I need to add i16 to GPR. I had tried to use manual instruction selection for some cases in GISel in #116111, but I got some feedback recommending the use of patterns. I did some investigation of why tablegen uses i32 in output patterns on RV64. It appears it comes down to ForceArbitraryInstResultType that just picks a type for the output pattern when the isel pattern isn't specific enough. I believe it picks the smallest type(lowested numbered) to resolve the conflict. --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 18 ++++++++++++++++++ llvm/lib/Target/RISCV/RISCVISelLowering.h | 3 +++ 2 files changed, 21 insertions(+) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 3df8eca8cae7f..f191b4e9cb251 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -21996,6 +21996,24 @@ SDValue RISCVTargetLowering::expandIndirectJTBranch(const SDLoc &dl, return TargetLowering::expandIndirectJTBranch(dl, Value, Addr, JTI, DAG); } +// Some types are listed in the GPR register class to support isel patterns for +// GISel, but are not legal in SelectionDAG. This prevents the default +// implementation from finding a register clss for them. +std::pair +RISCVTargetLowering::findRepresentativeClass(const TargetRegisterInfo *TRI, + MVT VT) const { + const TargetRegisterClass *RRC = nullptr; + uint8_t Cost = 1; + switch (VT.SimpleTy) { + default: + return TargetLowering::findRepresentativeClass(TRI, VT); + case MVT::i8: case MVT::i16: case MVT::i32: + RRC = &RISCV::GPRRegClass; + break; + } + return std::make_pair(RRC, Cost); +} + namespace llvm::RISCVVIntrinsicsTable { #define GET_RISCVVIntrinsicsTable_IMPL diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h index 9ae70d257fa44..aa73d558c048b 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -1051,6 +1051,9 @@ class RISCVTargetLowering : public TargetLowering { SDValue emitFlushICache(SelectionDAG &DAG, SDValue InChain, SDValue Start, SDValue End, SDValue Flags, SDLoc DL) const; + + std::pair + findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const override; }; namespace RISCVVIntrinsicsTable { From 10b08c448f93d31b855ddb430c8463b32b6d1dfa Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 13 Nov 2024 22:02:21 -0800 Subject: [PATCH 2/4] fixup! clang-format --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index f191b4e9cb251..2e157c7ce1c7c 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -22007,7 +22007,9 @@ RISCVTargetLowering::findRepresentativeClass(const TargetRegisterInfo *TRI, switch (VT.SimpleTy) { default: return TargetLowering::findRepresentativeClass(TRI, VT); - case MVT::i8: case MVT::i16: case MVT::i32: + case MVT::i8: + case MVT::i16: + case MVT::i32: RRC = &RISCV::GPRRegClass; break; } From 7fe0a33554a7a7a0b53ad47b52e690aa9058ddc6 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 15 Nov 2024 16:02:35 -0800 Subject: [PATCH 3/4] fixup! Add f16/bf16 by calling base class with f32. Handle int by calling base class with XLenVT. --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 28 +++++++++++++-------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 2e157c7ce1c7c..7aafb2478c660 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -21996,24 +21996,32 @@ SDValue RISCVTargetLowering::expandIndirectJTBranch(const SDLoc &dl, return TargetLowering::expandIndirectJTBranch(dl, Value, Addr, JTI, DAG); } -// Some types are listed in the GPR register class to support isel patterns for -// GISel, but are not legal in SelectionDAG. This prevents the default -// implementation from finding a register clss for them. +// If an output pattern produces multiple instructions tablegen may pick an +// arbitrary type from an instructions destination register class to use for the +// VT of that MachineSDNode. This VT may be used to look up the representative +// register class. If the type isn't legal, the default implementation will +// not find a register class. +// +// Some integer types smaller than XLen are listed in the GPR register class to +// support isel patterns for GISel, but are not legal in SelectionDAG. The +// arbitrary type tablegen picks may be one of these smaller types. +// +// f16 and bf16 are both valid for the FPR16 or GPRF16 register class. It's +// possible for tablegen to pick bf16 as the arbitrary type for an f16 pattern. std::pair RISCVTargetLowering::findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const { - const TargetRegisterClass *RRC = nullptr; - uint8_t Cost = 1; switch (VT.SimpleTy) { - default: - return TargetLowering::findRepresentativeClass(TRI, VT); case MVT::i8: case MVT::i16: case MVT::i32: - RRC = &RISCV::GPRRegClass; - break; + return TargetLowering::findRepresentativeClass(TRI, Subtarget.getXLenVT()); + case MVT::bf16: + case MVT::f16: + return TargetLowering::findRepresentativeClass(TRI, MVT::f32); } - return std::make_pair(RRC, Cost); + + return TargetLowering::findRepresentativeClass(TRI, VT); } namespace llvm::RISCVVIntrinsicsTable { From 076504d8970d34934fe0d5b59e14d9d9fa6fa02a Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 15 Nov 2024 16:22:17 -0800 Subject: [PATCH 4/4] fixup! fix -Wswitch warning --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 7aafb2478c660..eb81efb107713 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -22012,6 +22012,8 @@ std::pair RISCVTargetLowering::findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const { switch (VT.SimpleTy) { + default: + break; case MVT::i8: case MVT::i16: case MVT::i32: