Skip to content

Commit 7c3c8a1

Browse files
authored
[RISCV][GISel] Add support for G_IS_FPCLASS in F and D extensions (#72000)
Add legalizer, regbankselect, and isel supports for floating point version of G_IS_FPCLASS.
1 parent e096732 commit 7c3c8a1

File tree

13 files changed

+348
-5
lines changed

13 files changed

+348
-5
lines changed

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2483,6 +2483,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
24832483

24842484
case TargetOpcode::G_FPTOSI:
24852485
case TargetOpcode::G_FPTOUI:
2486+
case TargetOpcode::G_IS_FPCLASS:
24862487
Observer.changingInstr(MI);
24872488

24882489
if (TypeIdx == 0)

llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
394394
preISelLower(MI, MIB, MRI);
395395
const unsigned Opc = MI.getOpcode();
396396

397-
if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
397+
if (!MI.isPreISelOpcode() || Opc == TargetOpcode::G_PHI) {
398398
if (Opc == TargetOpcode::PHI || Opc == TargetOpcode::G_PHI) {
399399
const Register DefReg = MI.getOperand(0).getReg();
400400
const LLT DefTy = MRI.getType(DefReg);

llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ static LegalityPredicate typeIsScalarFPArith(unsigned TypeIdx,
3434
};
3535
}
3636

37-
RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
38-
const unsigned XLen = ST.getXLen();
39-
const LLT sXLen = LLT::scalar(XLen);
37+
RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
38+
: STI(ST), XLen(STI.getXLen()), sXLen(LLT::scalar(XLen)) {
4039
const LLT sDoubleXLen = LLT::scalar(2 * XLen);
4140
const LLT p0 = LLT::pointer(0, XLen);
41+
const LLT s1 = LLT::scalar(1);
4242
const LLT s8 = LLT::scalar(8);
4343
const LLT s16 = LLT::scalar(16);
4444
const LLT s32 = LLT::scalar(32);
@@ -244,6 +244,10 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
244244
.legalIf(all(typeIs(0, sXLen), typeIsScalarFPArith(1, ST)))
245245
.clampScalar(0, sXLen, sXLen);
246246

247+
// TODO: Support vector version of G_IS_FPCLASS.
248+
getActionDefinitionsBuilder(G_IS_FPCLASS)
249+
.customIf(all(typeIs(0, s1), typeIsScalarFPArith(1, ST)));
250+
247251
getActionDefinitionsBuilder(G_FCONSTANT).legalIf(typeIsScalarFPArith(0, ST));
248252

249253
getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})
@@ -309,6 +313,25 @@ bool RISCVLegalizerInfo::legalizeCustom(LegalizerHelper &Helper,
309313
return Helper.lower(MI, 0, /* Unused hint type */ LLT()) ==
310314
LegalizerHelper::Legalized;
311315
}
316+
case TargetOpcode::G_IS_FPCLASS: {
317+
Register GISFPCLASS = MI.getOperand(0).getReg();
318+
Register Src = MI.getOperand(1).getReg();
319+
const MachineOperand &ImmOp = MI.getOperand(2);
320+
MachineIRBuilder MIB(MI);
321+
322+
// Turn LLVM IR's floating point classes to that in RISC-V,
323+
// by simply rotating the 10-bit immediate right by two bits.
324+
APInt GFpClassImm(10, static_cast<uint64_t>(ImmOp.getImm()));
325+
auto FClassMask = MIB.buildConstant(sXLen, GFpClassImm.rotr(2).zext(XLen));
326+
auto ConstZero = MIB.buildConstant(sXLen, 0);
327+
328+
auto GFClass = MIB.buildInstr(RISCV::G_FCLASS, {sXLen}, {Src});
329+
auto And = MIB.buildAnd(sXLen, GFClass, FClassMask);
330+
MIB.buildICmp(CmpInst::ICMP_NE, GISFPCLASS, And, ConstZero);
331+
332+
MI.eraseFromParent();
333+
return true;
334+
}
312335
}
313336

314337
llvm_unreachable("expected switch to return");

llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ class RISCVSubtarget;
2323

2424
/// This class provides the information for the target register banks.
2525
class RISCVLegalizerInfo : public LegalizerInfo {
26+
const RISCVSubtarget &STI;
27+
const unsigned XLen;
28+
const LLT sXLen;
29+
2630
public:
2731
RISCVLegalizerInfo(const RISCVSubtarget &ST);
2832

llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,8 @@ RISCVRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
330330
OpdsMapping[3] = GPRValueMapping;
331331
break;
332332
case TargetOpcode::G_FPTOSI:
333-
case TargetOpcode::G_FPTOUI: {
333+
case TargetOpcode::G_FPTOUI:
334+
case RISCV::G_FCLASS: {
334335
LLT Ty = MRI.getType(MI.getOperand(1).getReg());
335336
OpdsMapping[0] = GPRValueMapping;
336337
OpdsMapping[1] = getFPValueMapping(Ty.getSizeInBits());
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===-- RISCVInstrGISel.td - RISC-V GISel target pseudos ----*- tablegen -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
/// \file
10+
// RISC-V GlobalISel target pseudo instruction definitions. This is kept
11+
// separately from the other tablegen files for organizational purposes, but
12+
// share the same infrastructure.
13+
//
14+
//===----------------------------------------------------------------------===//
15+
16+
class RISCVGenericInstruction : GenericInstruction {
17+
let Namespace = "RISCV";
18+
}
19+
20+
// Pseudo equivalent to a RISCVISD::FCLASS.
21+
def G_FCLASS : RISCVGenericInstruction {
22+
let OutOperandList = (outs type0:$dst);
23+
let InOperandList = (ins type1:$src);
24+
let hasSideEffects = false;
25+
}
26+
def : GINodeEquiv<G_FCLASS, riscv_fclass>;

llvm/lib/Target/RISCV/RISCVInstrInfo.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2127,3 +2127,9 @@ include "RISCVInstrInfoXVentana.td"
21272127
include "RISCVInstrInfoXTHead.td"
21282128
include "RISCVInstrInfoXSf.td"
21292129
include "RISCVInstrInfoXCV.td"
2130+
2131+
//===----------------------------------------------------------------------===//
2132+
// Global ISel
2133+
//===----------------------------------------------------------------------===//
2134+
2135+
include "RISCVInstrGISel.td"
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
2+
# RUN: llc -mtriple=riscv32 -mattr=+d -run-pass=instruction-select -verify-machineinstrs %s -o - | \
3+
# RUN: FileCheck %s
4+
5+
---
6+
name: is_fpclass_f32
7+
legalized: true
8+
regBankSelected: true
9+
body: |
10+
bb.0:
11+
liveins: $f10_f
12+
13+
; CHECK-LABEL: name: is_fpclass_f32
14+
; CHECK: liveins: $f10_f
15+
; CHECK-NEXT: {{ $}}
16+
; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr32 = COPY $f10_f
17+
; CHECK-NEXT: [[FCLASS_S:%[0-9]+]]:gpr = FCLASS_S [[COPY]]
18+
; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[FCLASS_S]], 152
19+
; CHECK-NEXT: [[SLTU:%[0-9]+]]:gpr = SLTU $x0, [[ANDI]]
20+
; CHECK-NEXT: $x10 = COPY [[SLTU]]
21+
; CHECK-NEXT: PseudoRET implicit $x10
22+
%0:fprb(s32) = COPY $f10_f
23+
%3:gprb(s32) = G_CONSTANT i32 152
24+
%4:gprb(s32) = G_CONSTANT i32 0
25+
%5:gprb(s32) = G_FCLASS %0(s32)
26+
%6:gprb(s32) = G_AND %5, %3
27+
%7:gprb(s32) = G_ICMP intpred(ne), %6(s32), %4
28+
$x10 = COPY %7(s32)
29+
PseudoRET implicit $x10
30+
...
31+
---
32+
name: is_fpclass_f32_onehot
33+
legalized: true
34+
regBankSelected: true
35+
body: |
36+
bb.0:
37+
liveins: $f10_f
38+
39+
; CHECK-LABEL: name: is_fpclass_f32_onehot
40+
; CHECK: liveins: $f10_f
41+
; CHECK-NEXT: {{ $}}
42+
; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr32 = COPY $f10_f
43+
; CHECK-NEXT: [[FCLASS_S:%[0-9]+]]:gpr = FCLASS_S [[COPY]]
44+
; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[FCLASS_S]], 256
45+
; CHECK-NEXT: [[SLTU:%[0-9]+]]:gpr = SLTU $x0, [[ANDI]]
46+
; CHECK-NEXT: $x10 = COPY [[SLTU]]
47+
; CHECK-NEXT: PseudoRET implicit $x10
48+
%0:fprb(s32) = COPY $f10_f
49+
%3:gprb(s32) = G_CONSTANT i32 256
50+
%4:gprb(s32) = G_CONSTANT i32 0
51+
%5:gprb(s32) = G_FCLASS %0(s32)
52+
%6:gprb(s32) = G_AND %5, %3
53+
%7:gprb(s32) = G_ICMP intpred(ne), %6(s32), %4
54+
$x10 = COPY %7(s32)
55+
PseudoRET implicit $x10
56+
...
57+
---
58+
name: is_fpclass_f32_one
59+
legalized: true
60+
regBankSelected: true
61+
body: |
62+
bb.0:
63+
liveins: $f10_f
64+
65+
; CHECK-LABEL: name: is_fpclass_f32_one
66+
; CHECK: liveins: $f10_f
67+
; CHECK-NEXT: {{ $}}
68+
; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr32 = COPY $f10_f
69+
; CHECK-NEXT: [[FCLASS_S:%[0-9]+]]:gpr = FCLASS_S [[COPY]]
70+
; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[FCLASS_S]], 1
71+
; CHECK-NEXT: [[SLTU:%[0-9]+]]:gpr = SLTU $x0, [[ANDI]]
72+
; CHECK-NEXT: $x10 = COPY [[SLTU]]
73+
; CHECK-NEXT: PseudoRET implicit $x10
74+
%0:fprb(s32) = COPY $f10_f
75+
%3:gprb(s32) = G_CONSTANT i32 1
76+
%4:gprb(s32) = G_CONSTANT i32 0
77+
%5:gprb(s32) = G_FCLASS %0(s32)
78+
%6:gprb(s32) = G_AND %5, %3
79+
%7:gprb(s32) = G_ICMP intpred(ne), %6(s32), %4
80+
$x10 = COPY %7(s32)
81+
PseudoRET implicit $x10
82+
...
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
2+
# RUN: llc -mtriple=riscv64 -mattr=+d -run-pass=instruction-select -verify-machineinstrs %s -o - | \
3+
# RUN: FileCheck %s
4+
5+
---
6+
name: is_fpclass_f64
7+
legalized: true
8+
regBankSelected: true
9+
body: |
10+
bb.0:
11+
liveins: $f10_d
12+
13+
; CHECK-LABEL: name: is_fpclass_f64
14+
; CHECK: liveins: $f10_d
15+
; CHECK-NEXT: {{ $}}
16+
; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $f10_d
17+
; CHECK-NEXT: [[FCLASS_D:%[0-9]+]]:gpr = FCLASS_D [[COPY]]
18+
; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[FCLASS_D]], 152
19+
; CHECK-NEXT: [[SLTU:%[0-9]+]]:gpr = SLTU $x0, [[ANDI]]
20+
; CHECK-NEXT: $x10 = COPY [[SLTU]]
21+
; CHECK-NEXT: PseudoRET implicit $x10
22+
%0:fprb(s64) = COPY $f10_d
23+
%3:gprb(s64) = G_CONSTANT i64 152
24+
%4:gprb(s64) = G_CONSTANT i64 0
25+
%5:gprb(s64) = G_FCLASS %0(s64)
26+
%6:gprb(s64) = G_AND %5, %3
27+
%7:gprb(s64) = G_ICMP intpred(ne), %6(s64), %4
28+
$x10 = COPY %7(s64)
29+
PseudoRET implicit $x10
30+
...
31+
---
32+
name: is_fpclass_f64_onehot
33+
legalized: true
34+
regBankSelected: true
35+
body: |
36+
bb.0:
37+
liveins: $f10_d
38+
39+
; CHECK-LABEL: name: is_fpclass_f64_onehot
40+
; CHECK: liveins: $f10_d
41+
; CHECK-NEXT: {{ $}}
42+
; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $f10_d
43+
; CHECK-NEXT: [[FCLASS_D:%[0-9]+]]:gpr = FCLASS_D [[COPY]]
44+
; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[FCLASS_D]], 256
45+
; CHECK-NEXT: [[SLTU:%[0-9]+]]:gpr = SLTU $x0, [[ANDI]]
46+
; CHECK-NEXT: $x10 = COPY [[SLTU]]
47+
; CHECK-NEXT: PseudoRET implicit $x10
48+
%0:fprb(s64) = COPY $f10_d
49+
%3:gprb(s64) = G_CONSTANT i64 256
50+
%4:gprb(s64) = G_CONSTANT i64 0
51+
%5:gprb(s64) = G_FCLASS %0(s64)
52+
%6:gprb(s64) = G_AND %5, %3
53+
%7:gprb(s64) = G_ICMP intpred(ne), %6(s64), %4
54+
$x10 = COPY %7(s64)
55+
PseudoRET implicit $x10
56+
...
57+
---
58+
name: is_fpclass_f64_one
59+
legalized: true
60+
regBankSelected: true
61+
body: |
62+
bb.0:
63+
liveins: $f10_d
64+
65+
; CHECK-LABEL: name: is_fpclass_f64_one
66+
; CHECK: liveins: $f10_d
67+
; CHECK-NEXT: {{ $}}
68+
; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $f10_d
69+
; CHECK-NEXT: [[FCLASS_D:%[0-9]+]]:gpr = FCLASS_D [[COPY]]
70+
; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[FCLASS_D]], 1
71+
; CHECK-NEXT: [[SLTU:%[0-9]+]]:gpr = SLTU $x0, [[ANDI]]
72+
; CHECK-NEXT: $x10 = COPY [[SLTU]]
73+
; CHECK-NEXT: PseudoRET implicit $x10
74+
%0:fprb(s64) = COPY $f10_d
75+
%3:gprb(s64) = G_CONSTANT i64 1
76+
%4:gprb(s64) = G_CONSTANT i64 0
77+
%5:gprb(s64) = G_FCLASS %0(s64)
78+
%6:gprb(s64) = G_AND %5, %3
79+
%7:gprb(s64) = G_ICMP intpred(ne), %6(s64), %4
80+
$x10 = COPY %7(s64)
81+
PseudoRET implicit $x10
82+
...
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
2+
# RUN: llc -mtriple=riscv32 -mattr=+d -run-pass=legalizer %s -o - \
3+
# RUN: | FileCheck %s
4+
5+
---
6+
name: is_fpclass_f32
7+
body: |
8+
bb.1:
9+
liveins: $f10_f
10+
11+
; CHECK-LABEL: name: is_fpclass_f32
12+
; CHECK: liveins: $f10_f
13+
; CHECK-NEXT: {{ $}}
14+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $f10_f
15+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 152
16+
; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
17+
; CHECK-NEXT: [[FCLASS:%[0-9]+]]:_(s32) = G_FCLASS [[COPY]](s32)
18+
; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[FCLASS]], [[C]]
19+
; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[AND]](s32), [[C1]]
20+
; CHECK-NEXT: $x10 = COPY [[ICMP]](s32)
21+
; CHECK-NEXT: PseudoRET implicit $x10
22+
%0:_(s32) = COPY $f10_f
23+
%1:_(s1) = G_IS_FPCLASS %0(s32), 608
24+
%2:_(s32) = G_ANYEXT %1(s1)
25+
$x10 = COPY %2(s32)
26+
PseudoRET implicit $x10
27+
28+
...
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
2+
# RUN: llc -mtriple=riscv64 -mattr=+d -run-pass=legalizer %s -o - \
3+
# RUN: | FileCheck %s
4+
5+
---
6+
name: is_fpclass_f64
7+
body: |
8+
bb.1:
9+
liveins: $f10_d
10+
11+
; CHECK-LABEL: name: is_fpclass_f64
12+
; CHECK: liveins: $f10_d
13+
; CHECK-NEXT: {{ $}}
14+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $f10_d
15+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 152
16+
; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
17+
; CHECK-NEXT: [[FCLASS:%[0-9]+]]:_(s64) = G_FCLASS [[COPY]](s64)
18+
; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[FCLASS]], [[C]]
19+
; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(ne), [[AND]](s64), [[C1]]
20+
; CHECK-NEXT: $x10 = COPY [[ICMP]](s64)
21+
; CHECK-NEXT: PseudoRET implicit $x10
22+
%0:_(s64) = COPY $f10_d
23+
%1:_(s1) = G_IS_FPCLASS %0(s64), 608
24+
%2:_(s64) = G_ANYEXT %1(s1)
25+
$x10 = COPY %2(s64)
26+
PseudoRET implicit $x10
27+
28+
...
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
2+
# RUN: llc -mtriple=riscv32 -mattr=+d -run-pass=regbankselect -verify-machineinstrs %s -o - \
3+
# RUN: | FileCheck %s
4+
5+
---
6+
name: is_fpclass_f32
7+
legalized: true
8+
body: |
9+
bb.0:
10+
liveins: $f10_f
11+
12+
; CHECK-LABEL: name: is_fpclass_f32
13+
; CHECK: liveins: $f10_f
14+
; CHECK-NEXT: {{ $}}
15+
; CHECK-NEXT: [[COPY:%[0-9]+]]:fprb(s32) = COPY $f10_f
16+
; CHECK-NEXT: [[C:%[0-9]+]]:gprb(s32) = G_CONSTANT i32 152
17+
; CHECK-NEXT: [[C1:%[0-9]+]]:gprb(s32) = G_CONSTANT i32 0
18+
; CHECK-NEXT: [[FCLASS:%[0-9]+]]:gprb(s32) = G_FCLASS [[COPY]](s32)
19+
; CHECK-NEXT: [[AND:%[0-9]+]]:gprb(s32) = G_AND [[FCLASS]], [[C]]
20+
; CHECK-NEXT: [[ICMP:%[0-9]+]]:gprb(s32) = G_ICMP intpred(ne), [[AND]](s32), [[C1]]
21+
; CHECK-NEXT: $x10 = COPY [[ICMP]](s32)
22+
; CHECK-NEXT: PseudoRET implicit $x10
23+
%0:_(s32) = COPY $f10_f
24+
%3:_(s32) = G_CONSTANT i32 152
25+
%4:_(s32) = G_CONSTANT i32 0
26+
%5:_(s32) = G_FCLASS %0(s32)
27+
%6:_(s32) = G_AND %5, %3
28+
%7:_(s32) = G_ICMP intpred(ne), %6(s32), %4
29+
$x10 = COPY %7(s32)
30+
PseudoRET implicit $x10
31+
...

0 commit comments

Comments
 (0)