[llvm] [RISCV][GISel] Add support for G_IS_FPCLASS in F and D extensions (PR #72000)
Min-Yih Hsu via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 22 14:51:06 PST 2023
https://github.com/mshockwave updated https://github.com/llvm/llvm-project/pull/72000
>From 51c9a13c4909cd04bc475f50c3de96f556ff267f Mon Sep 17 00:00:00 2001
From: Min-Yih Hsu <min.hsu at sifive.com>
Date: Fri, 10 Nov 2023 10:51:21 -0800
Subject: [PATCH 1/8] [RISCG][GISel] Add support for G_IS_FPCLASS in F and D
extensions
Add legalizer, regbankselect, and isel supports for floating point
version of G_IS_FPCLASS.
---
.../CodeGen/GlobalISel/LegalizerHelper.cpp | 1 +
.../RISCV/GISel/RISCVInstructionSelector.cpp | 28 +++++++++++++++++
.../Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 30 +++++++++++++++----
.../RISCV/GISel/RISCVRegisterBankInfo.cpp | 6 ++++
.../instruction-select/is-fpclass-rv32.mir | 25 ++++++++++++++++
.../instruction-select/is-fpclass-rv64.mir | 25 ++++++++++++++++
.../legalizer/rv32/legalize-is-fpclass.mir | 24 +++++++++++++++
.../legalizer/rv64/legalize-is-fpclass.mir | 24 +++++++++++++++
.../regbankselect/is-fpclass-rv32.mir | 23 ++++++++++++++
.../regbankselect/is-fpclass-rv64.mir | 23 ++++++++++++++
10 files changed, 204 insertions(+), 5 deletions(-)
create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir
create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir
create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-is-fpclass.mir
create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-is-fpclass.mir
create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv32.mir
create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv64.mir
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index cde5bc7d9a981f1..f0f34a62b431a0c 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -2483,6 +2483,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
case TargetOpcode::G_FPTOSI:
case TargetOpcode::G_FPTOUI:
+ case TargetOpcode::G_IS_FPCLASS:
Observer.changingInstr(MI);
if (TypeIdx == 0)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index b8acd98939b9fc7..9f2d10bca23f025 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -69,6 +69,8 @@ class RISCVInstructionSelector : public InstructionSelector {
MachineRegisterInfo &MRI) const;
bool selectFPCompare(MachineInstr &MI, MachineIRBuilder &MIB,
MachineRegisterInfo &MRI) const;
+ bool selectIsFPClass(MachineInstr &MI, MachineIRBuilder &MIB,
+ MachineRegisterInfo &MRI) const;
ComplexRendererFns selectShiftMask(MachineOperand &Root) const;
ComplexRendererFns selectAddrRegImm(MachineOperand &Root) const;
@@ -419,6 +421,8 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
return selectSelect(MI, MIB, MRI);
case TargetOpcode::G_FCMP:
return selectFPCompare(MI, MIB, MRI);
+ case TargetOpcode::G_IS_FPCLASS:
+ return selectIsFPClass(MI, MIB, MRI);
default:
return false;
}
@@ -948,6 +952,30 @@ bool RISCVInstructionSelector::selectFPCompare(MachineInstr &MI,
return true;
}
+bool RISCVInstructionSelector::selectIsFPClass(MachineInstr &MI,
+ MachineIRBuilder &MIB,
+ MachineRegisterInfo &MRI) const {
+ Register CheckResult = MI.getOperand(0).getReg();
+ Register Src = MI.getOperand(1).getReg();
+ int64_t MaskImm = MI.getOperand(2).getImm();
+ unsigned NewOpc = MRI.getType(Src).getSizeInBits() == 32 ? RISCV::FCLASS_S
+ : RISCV::FCLASS_D;
+
+ Register FClassResult = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ // Insert FCLASS_S/D.
+ auto FClass = MIB.buildInstr(NewOpc, {FClassResult}, {Src});
+ if (!FClass.constrainAllUses(TII, TRI, RBI))
+ return false;
+ // Insert AND to check Src aginst the mask.
+ auto And = MIB.buildInstr(RISCV::ANDI, {CheckResult}, {FClassResult})
+ .addImm(MaskImm);
+ if (!And.constrainAllUses(TII, TRI, RBI))
+ return false;
+
+ MI.eraseFromParent();
+ return true;
+}
+
namespace llvm {
InstructionSelector *
createRISCVInstructionSelector(const RISCVTargetMachine &TM,
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index 1aba6b78d8a9d9b..44f469a5aea138c 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -215,12 +215,21 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
typeIs(1, s32)(Query));
});
+ // Predicates shared by G_FCMP and G_IS_FPCLASS.
+ auto isScalarAndFP = [=, &ST](const LegalityQuery &Query) -> bool {
+ return typeIs(0, sXLen)(Query) &&
+ ((ST.hasStdExtF() && typeIs(1, s32)(Query)) ||
+ (ST.hasStdExtD() && typeIs(1, s64)(Query)));
+ };
getActionDefinitionsBuilder(G_FCMP)
- .legalIf([=, &ST](const LegalityQuery &Query) -> bool {
- return typeIs(0, sXLen)(Query) &&
- ((ST.hasStdExtF() && typeIs(1, s32)(Query)) ||
- (ST.hasStdExtD() && typeIs(1, s64)(Query)));
- })
+ .legalIf(isScalarAndFP)
+ .clampScalar(0, sXLen, sXLen);
+
+ // TODO: Support vector version of G_IS_FPCLASS.
+ getActionDefinitionsBuilder(G_IS_FPCLASS)
+ // This line basically equals to `legalIf(isScalarAndFP)` + post
+ // processing depicted in legalizeCustom.
+ .customIf(isScalarAndFP)
.clampScalar(0, sXLen, sXLen);
getActionDefinitionsBuilder(G_FCONSTANT)
@@ -270,6 +279,17 @@ bool RISCVLegalizerInfo::legalizeCustom(LegalizerHelper &Helper,
return Helper.lower(MI, 0, /* Unused hint type */ LLT()) ==
LegalizerHelper::Legalized;
}
+ case TargetOpcode::G_IS_FPCLASS: {
+ // Turn LLVM IR's floating point classes to that in RISCV,
+ // which is simply rotating the 10-bit immediate right by two bits.
+ MachineOperand &ImmOp = MI.getOperand(2);
+ APInt ClassImm(10, static_cast<uint64_t>(ImmOp.getImm()));
+ ImmOp.setImm(ClassImm.rotr(2).getLimitedValue());
+ // Note that we do NOT want to notify Observer as it will
+ // send this instruction back to the legalizer chain and eventually
+ // falls into an infinite loop.
+ return true;
+ }
}
llvm_unreachable("expected switch to return");
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
index 60b6de0a760dcbb..af3529e170d6a21 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
@@ -246,6 +246,12 @@ RISCVRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
{GPRValueMapping, nullptr, FPRValueMapping, FPRValueMapping});
break;
}
+ case TargetOpcode::G_IS_FPCLASS: {
+ LLT FPTy = MRI.getType(MI.getOperand(1).getReg());
+ OperandsMapping = getOperandsMapping(
+ {GPRValueMapping, getFPValueMapping(FPTy.getSizeInBits()), nullptr});
+ break;
+ }
default:
return getInvalidInstructionMapping();
}
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir
new file mode 100644
index 000000000000000..9590b1afe1d32fe
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir
@@ -0,0 +1,25 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
+# RUN: llc -mtriple=riscv32 -mattr=+d -run-pass=instruction-select -verify-machineinstrs %s -o - | \
+# RUN: FileCheck %s
+
+---
+name: is_fpclass_f32
+legalized: true
+regBankSelected: true
+body: |
+ bb.0:
+ liveins: $f10_f
+
+ ; CHECK-LABEL: name: is_fpclass_f32
+ ; CHECK: liveins: $f10_f
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr32 = COPY $f10_f
+ ; CHECK-NEXT: [[FCLASS_S:%[0-9]+]]:gpr = FCLASS_S [[COPY]]
+ ; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[FCLASS_S]], 152
+ ; CHECK-NEXT: $x10 = COPY [[ANDI]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:fprb(s32) = COPY $f10_f
+ %1:gprb(s32) = G_IS_FPCLASS %0(s32), 152
+ $x10 = COPY %1(s32)
+ PseudoRET implicit $x10
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir
new file mode 100644
index 000000000000000..98f748ed98481a8
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir
@@ -0,0 +1,25 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
+# RUN: llc -mtriple=riscv64 -mattr=+d -run-pass=instruction-select -verify-machineinstrs %s -o - | \
+# RUN: FileCheck %s
+
+---
+name: is_fpclass_f64
+legalized: true
+regBankSelected: true
+body: |
+ bb.0:
+ liveins: $f10_d
+
+ ; CHECK-LABEL: name: is_fpclass_f64
+ ; CHECK: liveins: $f10_d
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $f10_d
+ ; CHECK-NEXT: [[FCLASS_D:%[0-9]+]]:gpr = FCLASS_D [[COPY]]
+ ; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[FCLASS_D]], 152
+ ; CHECK-NEXT: $x10 = COPY [[ANDI]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:fprb(s64) = COPY $f10_d
+ %1:gprb(s64) = G_IS_FPCLASS %0(s64), 152
+ $x10 = COPY %1(s64)
+ PseudoRET implicit $x10
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-is-fpclass.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-is-fpclass.mir
new file mode 100644
index 000000000000000..3f8b77aa59264f0
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-is-fpclass.mir
@@ -0,0 +1,24 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
+# RUN: llc -mtriple=riscv32 -mattr=+d -run-pass=legalizer %s -o - \
+# RUN: | FileCheck %s
+
+---
+name: is_fpclass_f32
+body: |
+ bb.1:
+ liveins: $f10_f
+
+ ; CHECK-LABEL: name: is_fpclass_f32
+ ; CHECK: liveins: $f10_f
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $f10_f
+ ; CHECK-NEXT: [[IS_FPCLASS:%[0-9]+]]:_(s32) = G_IS_FPCLASS [[COPY]](s32), 152
+ ; CHECK-NEXT: $x10 = COPY [[IS_FPCLASS]](s32)
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:_(s32) = COPY $f10_f
+ %1:_(s1) = G_IS_FPCLASS %0(s32), 608
+ %2:_(s32) = G_ANYEXT %1(s1)
+ $x10 = COPY %2(s32)
+ PseudoRET implicit $x10
+
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-is-fpclass.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-is-fpclass.mir
new file mode 100644
index 000000000000000..96bf5270a91107a
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-is-fpclass.mir
@@ -0,0 +1,24 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
+# RUN: llc -mtriple=riscv64 -mattr=+d -run-pass=legalizer %s -o - \
+# RUN: | FileCheck %s
+
+---
+name: is_fpclass_f64
+body: |
+ bb.1:
+ liveins: $f10_d
+
+ ; CHECK-LABEL: name: is_fpclass_f64
+ ; CHECK: liveins: $f10_d
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $f10_d
+ ; CHECK-NEXT: [[IS_FPCLASS:%[0-9]+]]:_(s64) = G_IS_FPCLASS [[COPY]](s64), 152
+ ; CHECK-NEXT: $x10 = COPY [[IS_FPCLASS]](s64)
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:_(s64) = COPY $f10_d
+ %1:_(s1) = G_IS_FPCLASS %0(s64), 608
+ %2:_(s64) = G_ANYEXT %1(s1)
+ $x10 = COPY %2(s64)
+ PseudoRET implicit $x10
+
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv32.mir
new file mode 100644
index 000000000000000..6c8241f14b73135
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv32.mir
@@ -0,0 +1,23 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
+# RUN: llc -mtriple=riscv32 -mattr=+d -run-pass=regbankselect -verify-machineinstrs %s -o - \
+# RUN: | FileCheck %s
+
+---
+name: is_fpclass_f32
+legalized: true
+body: |
+ bb.0:
+ liveins: $f10_f
+
+ ; CHECK-LABEL: name: is_fpclass_f32
+ ; CHECK: liveins: $f10_f
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:fprb(s32) = COPY $f10_f
+ ; CHECK-NEXT: [[IS_FPCLASS:%[0-9]+]]:gprb(s32) = G_IS_FPCLASS [[COPY]](s32), 152
+ ; CHECK-NEXT: $x10 = COPY [[IS_FPCLASS]](s32)
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:_(s32) = COPY $f10_f
+ %3:_(s32) = G_IS_FPCLASS %0(s32), 152
+ $x10 = COPY %3(s32)
+ PseudoRET implicit $x10
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv64.mir
new file mode 100644
index 000000000000000..ad6fcd0dd379e38
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv64.mir
@@ -0,0 +1,23 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
+# RUN: llc -mtriple=riscv64 -mattr=+d -run-pass=regbankselect -verify-machineinstrs %s -o - \
+# RUN: | FileCheck %s
+
+---
+name: is_fpclass_f64
+legalized: true
+body: |
+ bb.0:
+ liveins: $f10_d
+
+ ; CHECK-LABEL: name: is_fpclass_f64
+ ; CHECK: liveins: $f10_d
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:fprb(s64) = COPY $f10_d
+ ; CHECK-NEXT: [[IS_FPCLASS:%[0-9]+]]:gprb(s64) = G_IS_FPCLASS [[COPY]](s64), 152
+ ; CHECK-NEXT: $x10 = COPY [[IS_FPCLASS]](s64)
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:_(s64) = COPY $f10_d
+ %3:_(s64) = G_IS_FPCLASS %0(s64), 152
+ $x10 = COPY %3(s64)
+ PseudoRET implicit $x10
+...
>From e63340d2adab7f9ae8397f568480646da969b0e4 Mon Sep 17 00:00:00 2001
From: Min-Yih Hsu <min.hsu at sifive.com>
Date: Mon, 13 Nov 2023 08:55:24 -0800
Subject: [PATCH 2/8] Move transformation of FPClass mask from legalizer to
isel
And addressed some comments.
---
.../RISCV/GISel/RISCVInstructionSelector.cpp | 13 +++++---
.../Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 31 ++++---------------
.../instruction-select/is-fpclass-rv64.mir | 2 +-
.../legalizer/rv64/legalize-is-fpclass.mir | 2 +-
4 files changed, 17 insertions(+), 31 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 9f2d10bca23f025..a87577dd786f2f2 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -955,20 +955,25 @@ bool RISCVInstructionSelector::selectFPCompare(MachineInstr &MI,
bool RISCVInstructionSelector::selectIsFPClass(MachineInstr &MI,
MachineIRBuilder &MIB,
MachineRegisterInfo &MRI) const {
- Register CheckResult = MI.getOperand(0).getReg();
+ Register GISFPCLASS = MI.getOperand(0).getReg();
Register Src = MI.getOperand(1).getReg();
- int64_t MaskImm = MI.getOperand(2).getImm();
+ const MachineOperand &ImmOp = MI.getOperand(2);
unsigned NewOpc = MRI.getType(Src).getSizeInBits() == 32 ? RISCV::FCLASS_S
: RISCV::FCLASS_D;
+ // Turn LLVM IR's floating point classes to that in RISCV,
+ // by simply rotating the 10-bit immediate right by two bits.
+ APInt GFpClassImm(10, static_cast<uint64_t>(ImmOp.getImm()));
+ APInt FClassMask = GFpClassImm.rotr(2);
+
Register FClassResult = MRI.createVirtualRegister(&RISCV::GPRRegClass);
// Insert FCLASS_S/D.
auto FClass = MIB.buildInstr(NewOpc, {FClassResult}, {Src});
if (!FClass.constrainAllUses(TII, TRI, RBI))
return false;
// Insert AND to check Src aginst the mask.
- auto And = MIB.buildInstr(RISCV::ANDI, {CheckResult}, {FClassResult})
- .addImm(MaskImm);
+ auto And = MIB.buildInstr(RISCV::ANDI, {GISFPCLASS}, {FClassResult})
+ .addImm(FClassMask.getLimitedValue());
if (!And.constrainAllUses(TII, TRI, RBI))
return false;
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index 44f469a5aea138c..46de35e24948a63 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -215,21 +215,13 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
typeIs(1, s32)(Query));
});
- // Predicates shared by G_FCMP and G_IS_FPCLASS.
- auto isScalarAndFP = [=, &ST](const LegalityQuery &Query) -> bool {
- return typeIs(0, sXLen)(Query) &&
- ((ST.hasStdExtF() && typeIs(1, s32)(Query)) ||
- (ST.hasStdExtD() && typeIs(1, s64)(Query)));
- };
- getActionDefinitionsBuilder(G_FCMP)
- .legalIf(isScalarAndFP)
- .clampScalar(0, sXLen, sXLen);
-
// TODO: Support vector version of G_IS_FPCLASS.
- getActionDefinitionsBuilder(G_IS_FPCLASS)
- // This line basically equals to `legalIf(isScalarAndFP)` + post
- // processing depicted in legalizeCustom.
- .customIf(isScalarAndFP)
+ getActionDefinitionsBuilder({G_FCMP, G_IS_FPCLASS})
+ .legalIf([=, &ST](const LegalityQuery &Query) -> bool {
+ return typeIs(0, sXLen)(Query) &&
+ ((ST.hasStdExtF() && typeIs(1, s32)(Query)) ||
+ (ST.hasStdExtD() && typeIs(1, s64)(Query)));
+ })
.clampScalar(0, sXLen, sXLen);
getActionDefinitionsBuilder(G_FCONSTANT)
@@ -279,17 +271,6 @@ bool RISCVLegalizerInfo::legalizeCustom(LegalizerHelper &Helper,
return Helper.lower(MI, 0, /* Unused hint type */ LLT()) ==
LegalizerHelper::Legalized;
}
- case TargetOpcode::G_IS_FPCLASS: {
- // Turn LLVM IR's floating point classes to that in RISCV,
- // which is simply rotating the 10-bit immediate right by two bits.
- MachineOperand &ImmOp = MI.getOperand(2);
- APInt ClassImm(10, static_cast<uint64_t>(ImmOp.getImm()));
- ImmOp.setImm(ClassImm.rotr(2).getLimitedValue());
- // Note that we do NOT want to notify Observer as it will
- // send this instruction back to the legalizer chain and eventually
- // falls into an infinite loop.
- return true;
- }
}
llvm_unreachable("expected switch to return");
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir
index 98f748ed98481a8..38c47ef1ec59277 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir
@@ -19,7 +19,7 @@ body: |
; CHECK-NEXT: $x10 = COPY [[ANDI]]
; CHECK-NEXT: PseudoRET implicit $x10
%0:fprb(s64) = COPY $f10_d
- %1:gprb(s64) = G_IS_FPCLASS %0(s64), 152
+ %1:gprb(s64) = G_IS_FPCLASS %0(s64), 608
$x10 = COPY %1(s64)
PseudoRET implicit $x10
...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-is-fpclass.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-is-fpclass.mir
index 96bf5270a91107a..7c4ef4828021881 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-is-fpclass.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-is-fpclass.mir
@@ -12,7 +12,7 @@ body: |
; CHECK: liveins: $f10_d
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $f10_d
- ; CHECK-NEXT: [[IS_FPCLASS:%[0-9]+]]:_(s64) = G_IS_FPCLASS [[COPY]](s64), 152
+ ; CHECK-NEXT: [[IS_FPCLASS:%[0-9]+]]:_(s64) = G_IS_FPCLASS [[COPY]](s64), 608
; CHECK-NEXT: $x10 = COPY [[IS_FPCLASS]](s64)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s64) = COPY $f10_d
>From 28ac70dc7b756c30cc2feea4643bbcf158f1ce23 Mon Sep 17 00:00:00 2001
From: Min-Yih Hsu <min.hsu at sifive.com>
Date: Mon, 13 Nov 2023 09:00:15 -0800
Subject: [PATCH 3/8] fixup! Move transformation of FPClass mask from legalizer
to isel
---
.../RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir | 2 +-
.../RISCV/GlobalISel/legalizer/rv32/legalize-is-fpclass.mir | 2 +-
.../RISCV/GlobalISel/regbankselect/is-fpclass-rv32.mir | 4 ++--
.../RISCV/GlobalISel/regbankselect/is-fpclass-rv64.mir | 4 ++--
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir
index 9590b1afe1d32fe..1a57288a6b3038a 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir
@@ -19,7 +19,7 @@ body: |
; CHECK-NEXT: $x10 = COPY [[ANDI]]
; CHECK-NEXT: PseudoRET implicit $x10
%0:fprb(s32) = COPY $f10_f
- %1:gprb(s32) = G_IS_FPCLASS %0(s32), 152
+ %1:gprb(s32) = G_IS_FPCLASS %0(s32), 608
$x10 = COPY %1(s32)
PseudoRET implicit $x10
...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-is-fpclass.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-is-fpclass.mir
index 3f8b77aa59264f0..c588d3cdfbb61a3 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-is-fpclass.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-is-fpclass.mir
@@ -12,7 +12,7 @@ body: |
; CHECK: liveins: $f10_f
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $f10_f
- ; CHECK-NEXT: [[IS_FPCLASS:%[0-9]+]]:_(s32) = G_IS_FPCLASS [[COPY]](s32), 152
+ ; CHECK-NEXT: [[IS_FPCLASS:%[0-9]+]]:_(s32) = G_IS_FPCLASS [[COPY]](s32), 608
; CHECK-NEXT: $x10 = COPY [[IS_FPCLASS]](s32)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s32) = COPY $f10_f
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv32.mir
index 6c8241f14b73135..6804d75111340d2 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv32.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv32.mir
@@ -13,11 +13,11 @@ body: |
; CHECK: liveins: $f10_f
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:fprb(s32) = COPY $f10_f
- ; CHECK-NEXT: [[IS_FPCLASS:%[0-9]+]]:gprb(s32) = G_IS_FPCLASS [[COPY]](s32), 152
+ ; CHECK-NEXT: [[IS_FPCLASS:%[0-9]+]]:gprb(s32) = G_IS_FPCLASS [[COPY]](s32), 608
; CHECK-NEXT: $x10 = COPY [[IS_FPCLASS]](s32)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s32) = COPY $f10_f
- %3:_(s32) = G_IS_FPCLASS %0(s32), 152
+ %3:_(s32) = G_IS_FPCLASS %0(s32), 608
$x10 = COPY %3(s32)
PseudoRET implicit $x10
...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv64.mir
index ad6fcd0dd379e38..708b1f12fe1f4bf 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv64.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv64.mir
@@ -13,11 +13,11 @@ body: |
; CHECK: liveins: $f10_d
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:fprb(s64) = COPY $f10_d
- ; CHECK-NEXT: [[IS_FPCLASS:%[0-9]+]]:gprb(s64) = G_IS_FPCLASS [[COPY]](s64), 152
+ ; CHECK-NEXT: [[IS_FPCLASS:%[0-9]+]]:gprb(s64) = G_IS_FPCLASS [[COPY]](s64), 608
; CHECK-NEXT: $x10 = COPY [[IS_FPCLASS]](s64)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s64) = COPY $f10_d
- %3:_(s64) = G_IS_FPCLASS %0(s64), 152
+ %3:_(s64) = G_IS_FPCLASS %0(s64), 608
$x10 = COPY %3(s64)
PseudoRET implicit $x10
...
>From 56395b9b625c9b98ee1fad7e045f0f77ba226bcf Mon Sep 17 00:00:00 2001
From: Min-Yih Hsu <min.hsu at sifive.com>
Date: Mon, 13 Nov 2023 10:34:32 -0800
Subject: [PATCH 4/8] Make sure the result only set/clear the LSB
---
.../RISCV/GISel/RISCVInstructionSelector.cpp | 33 +++++++++++++++----
.../instruction-select/is-fpclass-rv32.mir | 25 +++++++++++++-
.../instruction-select/is-fpclass-rv64.mir | 25 +++++++++++++-
3 files changed, 75 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index a87577dd786f2f2..4f83b1626929a4b 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -958,24 +958,45 @@ bool RISCVInstructionSelector::selectIsFPClass(MachineInstr &MI,
Register GISFPCLASS = MI.getOperand(0).getReg();
Register Src = MI.getOperand(1).getReg();
const MachineOperand &ImmOp = MI.getOperand(2);
+ const unsigned XLen = STI.getXLen();
unsigned NewOpc = MRI.getType(Src).getSizeInBits() == 32 ? RISCV::FCLASS_S
: RISCV::FCLASS_D;
// Turn LLVM IR's floating point classes to that in RISCV,
// by simply rotating the 10-bit immediate right by two bits.
APInt GFpClassImm(10, static_cast<uint64_t>(ImmOp.getImm()));
- APInt FClassMask = GFpClassImm.rotr(2);
+ APInt FClassMask = GFpClassImm.rotr(2).zext(XLen);
Register FClassResult = MRI.createVirtualRegister(&RISCV::GPRRegClass);
// Insert FCLASS_S/D.
auto FClass = MIB.buildInstr(NewOpc, {FClassResult}, {Src});
if (!FClass.constrainAllUses(TII, TRI, RBI))
return false;
- // Insert AND to check Src aginst the mask.
- auto And = MIB.buildInstr(RISCV::ANDI, {GISFPCLASS}, {FClassResult})
- .addImm(FClassMask.getLimitedValue());
- if (!And.constrainAllUses(TII, TRI, RBI))
- return false;
+
+ // If there is only a single bit set in the mask, lower to SLLI + SRLI.
+ if (FClassMask.popcount() == 1) {
+ Register SLResult = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ auto SLLI = MIB.buildInstr(RISCV::SLLI, {SLResult}, {FClassResult})
+ .addImm(FClassMask.countl_zero());
+ if (!SLLI.constrainAllUses(TII, TRI, RBI))
+ return false;
+ auto SRLI =
+ MIB.buildInstr(RISCV::SRLI, {GISFPCLASS}, {SLResult}).addImm(XLen - 1);
+ if (!SRLI.constrainAllUses(TII, TRI, RBI))
+ return false;
+ } else {
+ // Otherwise, lower to AND + SNEZ.
+ Register AndResult = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ auto And = MIB.buildInstr(RISCV::ANDI, {AndResult}, {FClassResult})
+ .addImm(FClassMask.getLimitedValue());
+ if (!And.constrainAllUses(TII, TRI, RBI))
+ return false;
+
+ Register Zero = RISCV::X0;
+ auto SNEZ = MIB.buildInstr(RISCV::SLTU, {GISFPCLASS}, {Zero, AndResult});
+ if (!SNEZ.constrainAllUses(TII, TRI, RBI))
+ return false;
+ }
MI.eraseFromParent();
return true;
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir
index 1a57288a6b3038a..c379c5ab950f580 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir
@@ -16,10 +16,33 @@ body: |
; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr32 = COPY $f10_f
; CHECK-NEXT: [[FCLASS_S:%[0-9]+]]:gpr = FCLASS_S [[COPY]]
; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[FCLASS_S]], 152
- ; CHECK-NEXT: $x10 = COPY [[ANDI]]
+ ; CHECK-NEXT: [[SLTU:%[0-9]+]]:gpr = SLTU $x0, [[ANDI]]
+ ; CHECK-NEXT: $x10 = COPY [[SLTU]]
; CHECK-NEXT: PseudoRET implicit $x10
%0:fprb(s32) = COPY $f10_f
%1:gprb(s32) = G_IS_FPCLASS %0(s32), 608
$x10 = COPY %1(s32)
PseudoRET implicit $x10
...
+---
+name: is_fpclass_f32_onehot
+legalized: true
+regBankSelected: true
+body: |
+ bb.0:
+ liveins: $f10_f
+
+ ; CHECK-LABEL: name: is_fpclass_f32_onehot
+ ; CHECK: liveins: $f10_f
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr32 = COPY $f10_f
+ ; CHECK-NEXT: [[FCLASS_S:%[0-9]+]]:gpr = FCLASS_S [[COPY]]
+ ; CHECK-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[FCLASS_S]], 23
+ ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[SLLI]], 31
+ ; CHECK-NEXT: $x10 = COPY [[SRLI]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:fprb(s32) = COPY $f10_f
+ %1:gprb(s32) = G_IS_FPCLASS %0(s32), 1
+ $x10 = COPY %1(s32)
+ PseudoRET implicit $x10
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir
index 38c47ef1ec59277..ed4390dbbd83f41 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir
@@ -16,10 +16,33 @@ body: |
; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $f10_d
; CHECK-NEXT: [[FCLASS_D:%[0-9]+]]:gpr = FCLASS_D [[COPY]]
; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[FCLASS_D]], 152
- ; CHECK-NEXT: $x10 = COPY [[ANDI]]
+ ; CHECK-NEXT: [[SLTU:%[0-9]+]]:gpr = SLTU $x0, [[ANDI]]
+ ; CHECK-NEXT: $x10 = COPY [[SLTU]]
; CHECK-NEXT: PseudoRET implicit $x10
%0:fprb(s64) = COPY $f10_d
%1:gprb(s64) = G_IS_FPCLASS %0(s64), 608
$x10 = COPY %1(s64)
PseudoRET implicit $x10
...
+---
+name: is_fpclass_f64_onehot
+legalized: true
+regBankSelected: true
+body: |
+ bb.0:
+ liveins: $f10_d
+
+ ; CHECK-LABEL: name: is_fpclass_f64_onehot
+ ; CHECK: liveins: $f10_d
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $f10_d
+ ; CHECK-NEXT: [[FCLASS_D:%[0-9]+]]:gpr = FCLASS_D [[COPY]]
+ ; CHECK-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[FCLASS_D]], 55
+ ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[SLLI]], 63
+ ; CHECK-NEXT: $x10 = COPY [[SRLI]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:fprb(s64) = COPY $f10_d
+ %1:gprb(s64) = G_IS_FPCLASS %0(s64), 1
+ $x10 = COPY %1(s64)
+ PseudoRET implicit $x10
+...
>From 9f9347875206d37c0f7153d3a7f3a7fa673ddcec Mon Sep 17 00:00:00 2001
From: Min-Yih Hsu <min.hsu at sifive.com>
Date: Mon, 13 Nov 2023 12:15:07 -0800
Subject: [PATCH 5/8] Address review comments
And add another special case where FCLASS mask is one.
---
.../RISCV/GISel/RISCVInstructionSelector.cpp | 29 +++++++++++--------
.../instruction-select/is-fpclass-rv32.mir | 20 +++++++++++++
.../instruction-select/is-fpclass-rv64.mir | 20 +++++++++++++
3 files changed, 57 insertions(+), 12 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 4f83b1626929a4b..b079a2d8fa2e3d0 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -962,7 +962,7 @@ bool RISCVInstructionSelector::selectIsFPClass(MachineInstr &MI,
unsigned NewOpc = MRI.getType(Src).getSizeInBits() == 32 ? RISCV::FCLASS_S
: RISCV::FCLASS_D;
- // Turn LLVM IR's floating point classes to that in RISCV,
+ // Turn LLVM IR's floating point classes to that in RISC-V,
// by simply rotating the 10-bit immediate right by two bits.
APInt GFpClassImm(10, static_cast<uint64_t>(ImmOp.getImm()));
APInt FClassMask = GFpClassImm.rotr(2).zext(XLen);
@@ -973,27 +973,32 @@ bool RISCVInstructionSelector::selectIsFPClass(MachineInstr &MI,
if (!FClass.constrainAllUses(TII, TRI, RBI))
return false;
- // If there is only a single bit set in the mask, lower to SLLI + SRLI.
- if (FClassMask.popcount() == 1) {
- Register SLResult = MRI.createVirtualRegister(&RISCV::GPRRegClass);
- auto SLLI = MIB.buildInstr(RISCV::SLLI, {SLResult}, {FClassResult})
- .addImm(FClassMask.countl_zero());
+ if (FClassMask == 1) {
+ // We don't need to generate additional instructions if Mask is 1, as the
+ // `ANDI rs, 1` that follows will suffice.
+ MRI.replaceRegWith(GISFPCLASS, FClassResult);
+ } else if (FClassMask.popcount() == 1) {
+ // If there is only a single bit set in the mask, lower to SLLI + SRLI.
+ auto SLLI =
+ MIB.buildInstr(RISCV::SLLI, {&RISCV::GPRRegClass}, {FClassResult})
+ .addImm(FClassMask.countl_zero());
if (!SLLI.constrainAllUses(TII, TRI, RBI))
return false;
- auto SRLI =
- MIB.buildInstr(RISCV::SRLI, {GISFPCLASS}, {SLResult}).addImm(XLen - 1);
+ auto SRLI = MIB.buildInstr(RISCV::SRLI, {GISFPCLASS}, {SLLI.getReg(0)})
+ .addImm(XLen - 1);
if (!SRLI.constrainAllUses(TII, TRI, RBI))
return false;
} else {
// Otherwise, lower to AND + SNEZ.
- Register AndResult = MRI.createVirtualRegister(&RISCV::GPRRegClass);
- auto And = MIB.buildInstr(RISCV::ANDI, {AndResult}, {FClassResult})
- .addImm(FClassMask.getLimitedValue());
+ auto And =
+ MIB.buildInstr(RISCV::ANDI, {&RISCV::GPRRegClass}, {FClassResult})
+ .addImm(FClassMask.getLimitedValue());
if (!And.constrainAllUses(TII, TRI, RBI))
return false;
Register Zero = RISCV::X0;
- auto SNEZ = MIB.buildInstr(RISCV::SLTU, {GISFPCLASS}, {Zero, AndResult});
+ auto SNEZ =
+ MIB.buildInstr(RISCV::SLTU, {GISFPCLASS}, {Zero, And.getReg(0)});
if (!SNEZ.constrainAllUses(TII, TRI, RBI))
return false;
}
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir
index c379c5ab950f580..fafc24c1ad4c019 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir
@@ -46,3 +46,23 @@ body: |
$x10 = COPY %1(s32)
PseudoRET implicit $x10
...
+---
+name: is_fpclass_f32_one
+legalized: true
+regBankSelected: true
+body: |
+ bb.0:
+ liveins: $f10_f
+
+ ; CHECK-LABEL: name: is_fpclass_f32_one
+ ; CHECK: liveins: $f10_f
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr32 = COPY $f10_f
+ ; CHECK-NEXT: [[FCLASS_S:%[0-9]+]]:gpr = FCLASS_S [[COPY]]
+ ; CHECK-NEXT: $x10 = COPY [[FCLASS_S]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:fprb(s32) = COPY $f10_f
+ %1:gprb(s32) = G_IS_FPCLASS %0(s32), 4
+ $x10 = COPY %1(s32)
+ PseudoRET implicit $x10
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir
index ed4390dbbd83f41..b7bd7151d96711b 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir
@@ -46,3 +46,23 @@ body: |
$x10 = COPY %1(s64)
PseudoRET implicit $x10
...
+---
+name: is_fpclass_f64_one
+legalized: true
+regBankSelected: true
+body: |
+ bb.0:
+ liveins: $f10_d
+
+ ; CHECK-LABEL: name: is_fpclass_f64_one
+ ; CHECK: liveins: $f10_d
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $f10_d
+ ; CHECK-NEXT: [[FCLASS_D:%[0-9]+]]:gpr = FCLASS_D [[COPY]]
+ ; CHECK-NEXT: $x10 = COPY [[FCLASS_D]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:fprb(s64) = COPY $f10_d
+ %1:gprb(s64) = G_IS_FPCLASS %0(s64), 4
+ $x10 = COPY %1(s64)
+ PseudoRET implicit $x10
+...
>From 1639478eabef1fb20f0011a1a97b8b4e894e7072 Mon Sep 17 00:00:00 2001
From: Min-Yih Hsu <min.hsu at sifive.com>
Date: Mon, 13 Nov 2023 18:59:11 -0800
Subject: [PATCH 6/8] fixup! Address review comments
---
.../Target/RISCV/GISel/RISCVInstructionSelector.cpp | 12 ++++++++----
.../instruction-select/is-fpclass-rv32.mir | 3 ++-
.../instruction-select/is-fpclass-rv64.mir | 3 ++-
3 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index b079a2d8fa2e3d0..985f7afd86c431b 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -974,9 +974,13 @@ bool RISCVInstructionSelector::selectIsFPClass(MachineInstr &MI,
return false;
if (FClassMask == 1) {
- // We don't need to generate additional instructions if Mask is 1, as the
- // `ANDI rs, 1` that follows will suffice.
- MRI.replaceRegWith(GISFPCLASS, FClassResult);
+ // If Mask is 1, we don't need to generate additional instructions
+ // other than `ANDI rs, 1`, which will likely be folded into an identical
+ // one commonly generated for G_IS_FPCLASS's users.
+ auto And =
+ MIB.buildInstr(RISCV::ANDI, {GISFPCLASS}, {FClassResult}).addImm(1U);
+ if (!And.constrainAllUses(TII, TRI, RBI))
+ return false;
} else if (FClassMask.popcount() == 1) {
// If there is only a single bit set in the mask, lower to SLLI + SRLI.
auto SLLI =
@@ -989,7 +993,7 @@ bool RISCVInstructionSelector::selectIsFPClass(MachineInstr &MI,
if (!SRLI.constrainAllUses(TII, TRI, RBI))
return false;
} else {
- // Otherwise, lower to AND + SNEZ.
+ // Otherwise, lower to ANDI + SNEZ.
auto And =
MIB.buildInstr(RISCV::ANDI, {&RISCV::GPRRegClass}, {FClassResult})
.addImm(FClassMask.getLimitedValue());
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir
index fafc24c1ad4c019..6c9ad537d971566 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir
@@ -59,7 +59,8 @@ body: |
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr32 = COPY $f10_f
; CHECK-NEXT: [[FCLASS_S:%[0-9]+]]:gpr = FCLASS_S [[COPY]]
- ; CHECK-NEXT: $x10 = COPY [[FCLASS_S]]
+ ; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[FCLASS_S]], 1
+ ; CHECK-NEXT: $x10 = COPY [[ANDI]]
; CHECK-NEXT: PseudoRET implicit $x10
%0:fprb(s32) = COPY $f10_f
%1:gprb(s32) = G_IS_FPCLASS %0(s32), 4
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir
index b7bd7151d96711b..6b63124cdbac26c 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir
@@ -59,7 +59,8 @@ body: |
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $f10_d
; CHECK-NEXT: [[FCLASS_D:%[0-9]+]]:gpr = FCLASS_D [[COPY]]
- ; CHECK-NEXT: $x10 = COPY [[FCLASS_D]]
+ ; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[FCLASS_D]], 1
+ ; CHECK-NEXT: $x10 = COPY [[ANDI]]
; CHECK-NEXT: PseudoRET implicit $x10
%0:fprb(s64) = COPY $f10_d
%1:gprb(s64) = G_IS_FPCLASS %0(s64), 4
>From 0409ebf8ceda2345891be1d6ee803cbef20e91b5 Mon Sep 17 00:00:00 2001
From: Min Hsu <min.hsu at sifive.com>
Date: Wed, 22 Nov 2023 14:41:23 -0800
Subject: [PATCH 7/8] Create a generic instruction for G_IS_FPCLASS
Creating a generic instruction, RISCV::G_FCLASS, so that we can reuse
the SelectionDAG patterns during ISel.
---
.../RISCV/GISel/RISCVInstructionSelector.cpp | 65 +------------------
.../Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 31 +++++++--
.../Target/RISCV/GISel/RISCVLegalizerInfo.h | 4 ++
.../RISCV/GISel/RISCVRegisterBankInfo.cpp | 9 +--
llvm/lib/Target/RISCV/RISCVInstrGISel.td | 25 +++++++
llvm/lib/Target/RISCV/RISCVInstrInfo.td | 6 ++
.../instruction-select/is-fpclass-rv32.mir | 33 +++++++---
.../instruction-select/is-fpclass-rv64.mir | 33 +++++++---
.../legalizer/rv32/legalize-is-fpclass.mir | 8 ++-
.../legalizer/rv64/legalize-is-fpclass.mir | 8 ++-
.../regbankselect/is-fpclass-rv32.mir | 16 +++--
.../regbankselect/is-fpclass-rv64.mir | 16 +++--
12 files changed, 147 insertions(+), 107 deletions(-)
create mode 100644 llvm/lib/Target/RISCV/RISCVInstrGISel.td
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 985f7afd86c431b..fe9fec6bbb23305 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -69,8 +69,6 @@ class RISCVInstructionSelector : public InstructionSelector {
MachineRegisterInfo &MRI) const;
bool selectFPCompare(MachineInstr &MI, MachineIRBuilder &MIB,
MachineRegisterInfo &MRI) const;
- bool selectIsFPClass(MachineInstr &MI, MachineIRBuilder &MIB,
- MachineRegisterInfo &MRI) const;
ComplexRendererFns selectShiftMask(MachineOperand &Root) const;
ComplexRendererFns selectAddrRegImm(MachineOperand &Root) const;
@@ -307,7 +305,7 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
preISelLower(MI, MIB, MRI);
const unsigned Opc = MI.getOpcode();
- if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
+ if (!MI.isPreISelOpcode() || Opc == TargetOpcode::G_PHI) {
if (Opc == TargetOpcode::PHI || Opc == TargetOpcode::G_PHI) {
const Register DefReg = MI.getOperand(0).getReg();
const LLT DefTy = MRI.getType(DefReg);
@@ -421,8 +419,6 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
return selectSelect(MI, MIB, MRI);
case TargetOpcode::G_FCMP:
return selectFPCompare(MI, MIB, MRI);
- case TargetOpcode::G_IS_FPCLASS:
- return selectIsFPClass(MI, MIB, MRI);
default:
return false;
}
@@ -952,65 +948,6 @@ bool RISCVInstructionSelector::selectFPCompare(MachineInstr &MI,
return true;
}
-bool RISCVInstructionSelector::selectIsFPClass(MachineInstr &MI,
- MachineIRBuilder &MIB,
- MachineRegisterInfo &MRI) const {
- Register GISFPCLASS = MI.getOperand(0).getReg();
- Register Src = MI.getOperand(1).getReg();
- const MachineOperand &ImmOp = MI.getOperand(2);
- const unsigned XLen = STI.getXLen();
- unsigned NewOpc = MRI.getType(Src).getSizeInBits() == 32 ? RISCV::FCLASS_S
- : RISCV::FCLASS_D;
-
- // Turn LLVM IR's floating point classes to that in RISC-V,
- // by simply rotating the 10-bit immediate right by two bits.
- APInt GFpClassImm(10, static_cast<uint64_t>(ImmOp.getImm()));
- APInt FClassMask = GFpClassImm.rotr(2).zext(XLen);
-
- Register FClassResult = MRI.createVirtualRegister(&RISCV::GPRRegClass);
- // Insert FCLASS_S/D.
- auto FClass = MIB.buildInstr(NewOpc, {FClassResult}, {Src});
- if (!FClass.constrainAllUses(TII, TRI, RBI))
- return false;
-
- if (FClassMask == 1) {
- // If Mask is 1, we don't need to generate additional instructions
- // other than `ANDI rs, 1`, which will likely be folded into an identical
- // one commonly generated for G_IS_FPCLASS's users.
- auto And =
- MIB.buildInstr(RISCV::ANDI, {GISFPCLASS}, {FClassResult}).addImm(1U);
- if (!And.constrainAllUses(TII, TRI, RBI))
- return false;
- } else if (FClassMask.popcount() == 1) {
- // If there is only a single bit set in the mask, lower to SLLI + SRLI.
- auto SLLI =
- MIB.buildInstr(RISCV::SLLI, {&RISCV::GPRRegClass}, {FClassResult})
- .addImm(FClassMask.countl_zero());
- if (!SLLI.constrainAllUses(TII, TRI, RBI))
- return false;
- auto SRLI = MIB.buildInstr(RISCV::SRLI, {GISFPCLASS}, {SLLI.getReg(0)})
- .addImm(XLen - 1);
- if (!SRLI.constrainAllUses(TII, TRI, RBI))
- return false;
- } else {
- // Otherwise, lower to ANDI + SNEZ.
- auto And =
- MIB.buildInstr(RISCV::ANDI, {&RISCV::GPRRegClass}, {FClassResult})
- .addImm(FClassMask.getLimitedValue());
- if (!And.constrainAllUses(TII, TRI, RBI))
- return false;
-
- Register Zero = RISCV::X0;
- auto SNEZ =
- MIB.buildInstr(RISCV::SLTU, {GISFPCLASS}, {Zero, And.getReg(0)});
- if (!SNEZ.constrainAllUses(TII, TRI, RBI))
- return false;
- }
-
- MI.eraseFromParent();
- return true;
-}
-
namespace llvm {
InstructionSelector *
createRISCVInstructionSelector(const RISCVTargetMachine &TM,
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index 46de35e24948a63..0e0c4a3336f8b41 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -13,6 +13,7 @@
#include "RISCVLegalizerInfo.h"
#include "RISCVSubtarget.h"
#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/IR/DerivedTypes.h"
@@ -21,9 +22,8 @@
using namespace llvm;
using namespace LegalityPredicates;
-RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
- const unsigned XLen = ST.getXLen();
- const LLT sXLen = LLT::scalar(XLen);
+RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
+ : STI(ST), XLen(STI.getXLen()), sXLen(LLT::scalar(XLen)) {
const LLT sDoubleXLen = LLT::scalar(2 * XLen);
const LLT p0 = LLT::pointer(0, XLen);
const LLT s8 = LLT::scalar(8);
@@ -216,7 +216,7 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
});
// TODO: Support vector version of G_IS_FPCLASS.
- getActionDefinitionsBuilder({G_FCMP, G_IS_FPCLASS})
+ getActionDefinitionsBuilder(G_FCMP)
.legalIf([=, &ST](const LegalityQuery &Query) -> bool {
return typeIs(0, sXLen)(Query) &&
((ST.hasStdExtF() && typeIs(1, s32)(Query)) ||
@@ -224,6 +224,8 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
})
.clampScalar(0, sXLen, sXLen);
+ getActionDefinitionsBuilder(G_IS_FPCLASS).custom();
+
getActionDefinitionsBuilder(G_FCONSTANT)
.legalIf([=, &ST](const LegalityQuery &Query) -> bool {
return (ST.hasStdExtF() && typeIs(0, s32)(Query)) ||
@@ -271,6 +273,27 @@ bool RISCVLegalizerInfo::legalizeCustom(LegalizerHelper &Helper,
return Helper.lower(MI, 0, /* Unused hint type */ LLT()) ==
LegalizerHelper::Legalized;
}
+ case TargetOpcode::G_IS_FPCLASS: {
+ Register GISFPCLASS = MI.getOperand(0).getReg();
+ Register Src = MI.getOperand(1).getReg();
+ const MachineOperand &ImmOp = MI.getOperand(2);
+ const unsigned XLen = STI.getXLen();
+ const LLT sXLen = LLT::scalar(XLen);
+ MachineIRBuilder MIB(MI);
+
+ // Turn LLVM IR's floating point classes to that in RISC-V,
+ // by simply rotating the 10-bit immediate right by two bits.
+ APInt GFpClassImm(10, static_cast<uint64_t>(ImmOp.getImm()));
+ auto FClassMask = MIB.buildConstant(sXLen, GFpClassImm.rotr(2).zext(XLen));
+ auto ConstZero = MIB.buildConstant(sXLen, 0);
+
+ auto GFClass = MIB.buildInstr(RISCV::G_FCLASS, {sXLen}, {Src});
+ auto And = MIB.buildAnd(sXLen, GFClass, FClassMask);
+ MIB.buildICmp(CmpInst::ICMP_NE, GISFPCLASS, And, ConstZero);
+
+ MI.eraseFromParent();
+ return true;
+ }
}
llvm_unreachable("expected switch to return");
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.h b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.h
index 4061c553b6496ae..cbe0c7da857b77f 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.h
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.h
@@ -21,6 +21,10 @@ class RISCVSubtarget;
/// This class provides the information for the target register banks.
class RISCVLegalizerInfo : public LegalizerInfo {
+ const RISCVSubtarget &STI;
+ const unsigned XLen;
+ const LLT sXLen;
+
public:
RISCVLegalizerInfo(const RISCVSubtarget &ST);
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
index af3529e170d6a21..08bf9ecebda9e22 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
@@ -215,7 +215,8 @@ RISCVRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
break;
}
case TargetOpcode::G_FPTOSI:
- case TargetOpcode::G_FPTOUI: {
+ case TargetOpcode::G_FPTOUI:
+ case RISCV::G_FCLASS: {
LLT Ty = MRI.getType(MI.getOperand(1).getReg());
OperandsMapping =
getOperandsMapping({GPRValueMapping,
@@ -246,12 +247,6 @@ RISCVRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
{GPRValueMapping, nullptr, FPRValueMapping, FPRValueMapping});
break;
}
- case TargetOpcode::G_IS_FPCLASS: {
- LLT FPTy = MRI.getType(MI.getOperand(1).getReg());
- OperandsMapping = getOperandsMapping(
- {GPRValueMapping, getFPValueMapping(FPTy.getSizeInBits()), nullptr});
- break;
- }
default:
return getInvalidInstructionMapping();
}
diff --git a/llvm/lib/Target/RISCV/RISCVInstrGISel.td b/llvm/lib/Target/RISCV/RISCVInstrGISel.td
new file mode 100644
index 000000000000000..f7958705a5965b8
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVInstrGISel.td
@@ -0,0 +1,25 @@
+//===-- RISCVGIsel.td - RISC-V GlobalISel Patterns ---------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// This file contains patterns that are relevant to GlobalISel, including
+/// GIComplexOperandMatcher definitions for equivalent SelectionDAG
+/// ComplexPatterns.
+//
+//===----------------------------------------------------------------------===//
+
+class RISCVGenericInstruction : GenericInstruction {
+ let Namespace = "RISCV";
+}
+
+def G_FCLASS : RISCVGenericInstruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins type1:$src);
+ let hasSideEffects = false;
+}
+def : GINodeEquiv<G_FCLASS, riscv_fpclass>;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 53f820d43a925df..b22797634f623ed 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -2093,3 +2093,9 @@ include "RISCVInstrInfoXVentana.td"
include "RISCVInstrInfoXTHead.td"
include "RISCVInstrInfoXSf.td"
include "RISCVInstrInfoXCV.td"
+
+//===----------------------------------------------------------------------===//
+// Global ISel
+//===----------------------------------------------------------------------===//
+
+include "RISCVInstrGISel.td"
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir
index 6c9ad537d971566..705c70757e80b6e 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv32.mir
@@ -20,8 +20,12 @@ body: |
; CHECK-NEXT: $x10 = COPY [[SLTU]]
; CHECK-NEXT: PseudoRET implicit $x10
%0:fprb(s32) = COPY $f10_f
- %1:gprb(s32) = G_IS_FPCLASS %0(s32), 608
- $x10 = COPY %1(s32)
+ %3:gprb(s32) = G_CONSTANT i32 152
+ %4:gprb(s32) = G_CONSTANT i32 0
+ %5:gprb(s32) = G_FCLASS %0(s32)
+ %6:gprb(s32) = G_AND %5, %3
+ %7:gprb(s32) = G_ICMP intpred(ne), %6(s32), %4
+ $x10 = COPY %7(s32)
PseudoRET implicit $x10
...
---
@@ -37,13 +41,17 @@ body: |
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr32 = COPY $f10_f
; CHECK-NEXT: [[FCLASS_S:%[0-9]+]]:gpr = FCLASS_S [[COPY]]
- ; CHECK-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[FCLASS_S]], 23
- ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[SLLI]], 31
- ; CHECK-NEXT: $x10 = COPY [[SRLI]]
+ ; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[FCLASS_S]], 256
+ ; CHECK-NEXT: [[SLTU:%[0-9]+]]:gpr = SLTU $x0, [[ANDI]]
+ ; CHECK-NEXT: $x10 = COPY [[SLTU]]
; CHECK-NEXT: PseudoRET implicit $x10
%0:fprb(s32) = COPY $f10_f
- %1:gprb(s32) = G_IS_FPCLASS %0(s32), 1
- $x10 = COPY %1(s32)
+ %3:gprb(s32) = G_CONSTANT i32 256
+ %4:gprb(s32) = G_CONSTANT i32 0
+ %5:gprb(s32) = G_FCLASS %0(s32)
+ %6:gprb(s32) = G_AND %5, %3
+ %7:gprb(s32) = G_ICMP intpred(ne), %6(s32), %4
+ $x10 = COPY %7(s32)
PseudoRET implicit $x10
...
---
@@ -60,10 +68,15 @@ body: |
; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr32 = COPY $f10_f
; CHECK-NEXT: [[FCLASS_S:%[0-9]+]]:gpr = FCLASS_S [[COPY]]
; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[FCLASS_S]], 1
- ; CHECK-NEXT: $x10 = COPY [[ANDI]]
+ ; CHECK-NEXT: [[SLTU:%[0-9]+]]:gpr = SLTU $x0, [[ANDI]]
+ ; CHECK-NEXT: $x10 = COPY [[SLTU]]
; CHECK-NEXT: PseudoRET implicit $x10
%0:fprb(s32) = COPY $f10_f
- %1:gprb(s32) = G_IS_FPCLASS %0(s32), 4
- $x10 = COPY %1(s32)
+ %3:gprb(s32) = G_CONSTANT i32 1
+ %4:gprb(s32) = G_CONSTANT i32 0
+ %5:gprb(s32) = G_FCLASS %0(s32)
+ %6:gprb(s32) = G_AND %5, %3
+ %7:gprb(s32) = G_ICMP intpred(ne), %6(s32), %4
+ $x10 = COPY %7(s32)
PseudoRET implicit $x10
...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir
index 6b63124cdbac26c..e970bc23a8c1a27 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/is-fpclass-rv64.mir
@@ -20,8 +20,12 @@ body: |
; CHECK-NEXT: $x10 = COPY [[SLTU]]
; CHECK-NEXT: PseudoRET implicit $x10
%0:fprb(s64) = COPY $f10_d
- %1:gprb(s64) = G_IS_FPCLASS %0(s64), 608
- $x10 = COPY %1(s64)
+ %3:gprb(s64) = G_CONSTANT i64 152
+ %4:gprb(s64) = G_CONSTANT i64 0
+ %5:gprb(s64) = G_FCLASS %0(s64)
+ %6:gprb(s64) = G_AND %5, %3
+ %7:gprb(s64) = G_ICMP intpred(ne), %6(s64), %4
+ $x10 = COPY %7(s64)
PseudoRET implicit $x10
...
---
@@ -37,13 +41,17 @@ body: |
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $f10_d
; CHECK-NEXT: [[FCLASS_D:%[0-9]+]]:gpr = FCLASS_D [[COPY]]
- ; CHECK-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[FCLASS_D]], 55
- ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[SLLI]], 63
- ; CHECK-NEXT: $x10 = COPY [[SRLI]]
+ ; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[FCLASS_D]], 256
+ ; CHECK-NEXT: [[SLTU:%[0-9]+]]:gpr = SLTU $x0, [[ANDI]]
+ ; CHECK-NEXT: $x10 = COPY [[SLTU]]
; CHECK-NEXT: PseudoRET implicit $x10
%0:fprb(s64) = COPY $f10_d
- %1:gprb(s64) = G_IS_FPCLASS %0(s64), 1
- $x10 = COPY %1(s64)
+ %3:gprb(s64) = G_CONSTANT i64 256
+ %4:gprb(s64) = G_CONSTANT i64 0
+ %5:gprb(s64) = G_FCLASS %0(s64)
+ %6:gprb(s64) = G_AND %5, %3
+ %7:gprb(s64) = G_ICMP intpred(ne), %6(s64), %4
+ $x10 = COPY %7(s64)
PseudoRET implicit $x10
...
---
@@ -60,10 +68,15 @@ body: |
; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $f10_d
; CHECK-NEXT: [[FCLASS_D:%[0-9]+]]:gpr = FCLASS_D [[COPY]]
; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[FCLASS_D]], 1
- ; CHECK-NEXT: $x10 = COPY [[ANDI]]
+ ; CHECK-NEXT: [[SLTU:%[0-9]+]]:gpr = SLTU $x0, [[ANDI]]
+ ; CHECK-NEXT: $x10 = COPY [[SLTU]]
; CHECK-NEXT: PseudoRET implicit $x10
%0:fprb(s64) = COPY $f10_d
- %1:gprb(s64) = G_IS_FPCLASS %0(s64), 4
- $x10 = COPY %1(s64)
+ %3:gprb(s64) = G_CONSTANT i64 1
+ %4:gprb(s64) = G_CONSTANT i64 0
+ %5:gprb(s64) = G_FCLASS %0(s64)
+ %6:gprb(s64) = G_AND %5, %3
+ %7:gprb(s64) = G_ICMP intpred(ne), %6(s64), %4
+ $x10 = COPY %7(s64)
PseudoRET implicit $x10
...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-is-fpclass.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-is-fpclass.mir
index c588d3cdfbb61a3..b35a68b20ad151e 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-is-fpclass.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-is-fpclass.mir
@@ -12,8 +12,12 @@ body: |
; CHECK: liveins: $f10_f
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $f10_f
- ; CHECK-NEXT: [[IS_FPCLASS:%[0-9]+]]:_(s32) = G_IS_FPCLASS [[COPY]](s32), 608
- ; CHECK-NEXT: $x10 = COPY [[IS_FPCLASS]](s32)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 152
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: [[FCLASS:%[0-9]+]]:_(s32) = G_FCLASS [[COPY]](s32)
+ ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[FCLASS]], [[C]]
+ ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[AND]](s32), [[C1]]
+ ; CHECK-NEXT: $x10 = COPY [[ICMP]](s32)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s32) = COPY $f10_f
%1:_(s1) = G_IS_FPCLASS %0(s32), 608
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-is-fpclass.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-is-fpclass.mir
index 7c4ef4828021881..8b27e2875c537ac 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-is-fpclass.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-is-fpclass.mir
@@ -12,8 +12,12 @@ body: |
; CHECK: liveins: $f10_d
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $f10_d
- ; CHECK-NEXT: [[IS_FPCLASS:%[0-9]+]]:_(s64) = G_IS_FPCLASS [[COPY]](s64), 608
- ; CHECK-NEXT: $x10 = COPY [[IS_FPCLASS]](s64)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 152
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
+ ; CHECK-NEXT: [[FCLASS:%[0-9]+]]:_(s64) = G_FCLASS [[COPY]](s64)
+ ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[FCLASS]], [[C]]
+ ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(ne), [[AND]](s64), [[C1]]
+ ; CHECK-NEXT: $x10 = COPY [[ICMP]](s64)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s64) = COPY $f10_d
%1:_(s1) = G_IS_FPCLASS %0(s64), 608
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv32.mir
index 6804d75111340d2..e48c1cbaba303f2 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv32.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv32.mir
@@ -13,11 +13,19 @@ body: |
; CHECK: liveins: $f10_f
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:fprb(s32) = COPY $f10_f
- ; CHECK-NEXT: [[IS_FPCLASS:%[0-9]+]]:gprb(s32) = G_IS_FPCLASS [[COPY]](s32), 608
- ; CHECK-NEXT: $x10 = COPY [[IS_FPCLASS]](s32)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:gprb(s32) = G_CONSTANT i32 152
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:gprb(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: [[FCLASS:%[0-9]+]]:gprb(s32) = G_FCLASS [[COPY]](s32)
+ ; CHECK-NEXT: [[AND:%[0-9]+]]:gprb(s32) = G_AND [[FCLASS]], [[C]]
+ ; CHECK-NEXT: [[ICMP:%[0-9]+]]:gprb(s32) = G_ICMP intpred(ne), [[AND]](s32), [[C1]]
+ ; CHECK-NEXT: $x10 = COPY [[ICMP]](s32)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s32) = COPY $f10_f
- %3:_(s32) = G_IS_FPCLASS %0(s32), 608
- $x10 = COPY %3(s32)
+ %3:_(s32) = G_CONSTANT i32 152
+ %4:_(s32) = G_CONSTANT i32 0
+ %5:_(s32) = G_FCLASS %0(s32)
+ %6:_(s32) = G_AND %5, %3
+ %7:_(s32) = G_ICMP intpred(ne), %6(s32), %4
+ $x10 = COPY %7(s32)
PseudoRET implicit $x10
...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv64.mir
index 708b1f12fe1f4bf..afe999ea42be43d 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv64.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/is-fpclass-rv64.mir
@@ -13,11 +13,19 @@ body: |
; CHECK: liveins: $f10_d
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:fprb(s64) = COPY $f10_d
- ; CHECK-NEXT: [[IS_FPCLASS:%[0-9]+]]:gprb(s64) = G_IS_FPCLASS [[COPY]](s64), 608
- ; CHECK-NEXT: $x10 = COPY [[IS_FPCLASS]](s64)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:gprb(s64) = G_CONSTANT i64 152
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:gprb(s64) = G_CONSTANT i64 0
+ ; CHECK-NEXT: [[FCLASS:%[0-9]+]]:gprb(s64) = G_FCLASS [[COPY]](s64)
+ ; CHECK-NEXT: [[AND:%[0-9]+]]:gprb(s64) = G_AND [[FCLASS]], [[C]]
+ ; CHECK-NEXT: [[ICMP:%[0-9]+]]:gprb(s64) = G_ICMP intpred(ne), [[AND]](s64), [[C1]]
+ ; CHECK-NEXT: $x10 = COPY [[ICMP]](s64)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s64) = COPY $f10_d
- %3:_(s64) = G_IS_FPCLASS %0(s64), 608
- $x10 = COPY %3(s64)
+ %3:_(s64) = G_CONSTANT i64 152
+ %4:_(s64) = G_CONSTANT i64 0
+ %5:_(s64) = G_FCLASS %0(s64)
+ %6:_(s64) = G_AND %5, %3
+ %7:_(s64) = G_ICMP intpred(ne), %6(s64), %4
+ $x10 = COPY %7(s64)
PseudoRET implicit $x10
...
>From e36def3e15f69470e74ede8403b235153e831f9a Mon Sep 17 00:00:00 2001
From: Min Hsu <min.hsu at sifive.com>
Date: Wed, 22 Nov 2023 14:50:21 -0800
Subject: [PATCH 8/8] fixup! Create a generic instruction for G_IS_FPCLASS
---
llvm/lib/Target/RISCV/RISCVInstrGISel.td | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVInstrGISel.td b/llvm/lib/Target/RISCV/RISCVInstrGISel.td
index f7958705a5965b8..588297ecb928c0d 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrGISel.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrGISel.td
@@ -1,4 +1,4 @@
-//===-- RISCVGIsel.td - RISC-V GlobalISel Patterns ---------*- tablegen -*-===//
+//===-- RISCVInstrGISel.td - RISC-V GISel target pseudos ----*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -7,9 +7,9 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// This file contains patterns that are relevant to GlobalISel, including
-/// GIComplexOperandMatcher definitions for equivalent SelectionDAG
-/// ComplexPatterns.
+// RISC-V GlobalISel target pseudo instruction definitions. This is kept
+// separately from the other tablegen files for organizational purposes, but
+// share the same infrastructure.
//
//===----------------------------------------------------------------------===//
@@ -17,6 +17,7 @@ class RISCVGenericInstruction : GenericInstruction {
let Namespace = "RISCV";
}
+// Pseudo equivalent to a RISCVISD::FPCLASS.
def G_FCLASS : RISCVGenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type1:$src);
More information about the llvm-commits
mailing list