[llvm] [RISCV][GISel] Legalize G_IS_FPCLASS for fp128 (PR #195738)
Gábor Spaits via llvm-commits
llvm-commits at lists.llvm.org
Wed May 6 00:53:19 PDT 2026
https://github.com/spaits updated https://github.com/llvm/llvm-project/pull/195738
>From fd5ce99a441f974411421c8b5bdf1137c422a674 Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Mon, 4 May 2026 22:31:28 +0200
Subject: [PATCH 1/5] [RISCV][GISel] Legalize G_IS_FPCLASS for fp128
When compiling `libc/src/stdlib/strtold.cpp` with GlobalISel there is a failure. Calls to `@llvm.is.fpclass.f128` are translated to G_IS_FPCLASS, which couldn't be laglized.
This PR tries to address that.
---
.../Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 2 +-
.../legalizer/legalize-is-fpclass-rv32.mir | 42 +++++++++++++++++++
.../legalizer/legalize-is-fpclass-rv64.mir | 32 ++++++++++++++
3 files changed, 75 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index 52fa1cf9fa3cc..0b7eedadbf4af 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -583,7 +583,7 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
.customFor(ST.hasStdExtF(), {{s1, s32}})
.customFor(ST.hasStdExtD(), {{s1, s64}})
.customFor(ST.hasStdExtZfh(), {{s1, s16}})
- .lowerFor({{s1, s32}, {s1, s64}});
+ .lowerFor({{s1, s32}, {s1, s64}, {s1, s128}});
getActionDefinitionsBuilder(G_FCONSTANT)
.legalFor(ST.hasStdExtF(), {s32})
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-is-fpclass-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-is-fpclass-rv32.mir
index fb8c5c39962a8..a01b0ab701fca 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-is-fpclass-rv32.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-is-fpclass-rv32.mir
@@ -50,3 +50,45 @@ body: |
PseudoRET implicit $x10
...
+---
+name: is_fpclass_f128
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: is_fpclass_f128
+ ; CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647
+ ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147418112
+ ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[DEF]], [[C]]
+ ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[DEF]], [[C]]
+ ; CHECK-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[DEF]], [[C]]
+ ; CHECK-NEXT: [[AND3:%[0-9]+]]:_(s32) = G_AND [[DEF]], [[C1]]
+ ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[AND]], [[C2]]
+ ; CHECK-NEXT: [[XOR1:%[0-9]+]]:_(s32) = G_XOR [[AND1]], [[C2]]
+ ; CHECK-NEXT: [[XOR2:%[0-9]+]]:_(s32) = G_XOR [[AND2]], [[C2]]
+ ; CHECK-NEXT: [[XOR3:%[0-9]+]]:_(s32) = G_XOR [[AND3]], [[C2]]
+ ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[XOR]], [[XOR1]]
+ ; CHECK-NEXT: [[OR1:%[0-9]+]]:_(s32) = G_OR [[OR]], [[XOR2]]
+ ; CHECK-NEXT: [[OR2:%[0-9]+]]:_(s32) = G_OR [[OR1]], [[XOR3]]
+ ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[OR2]](s32), [[C2]]
+ ; CHECK-NEXT: [[OR3:%[0-9]+]]:_(s32) = G_OR [[C4]], [[ICMP]]
+ ; CHECK-NEXT: [[XOR4:%[0-9]+]]:_(s32) = G_XOR [[DEF]], [[C2]]
+ ; CHECK-NEXT: [[XOR5:%[0-9]+]]:_(s32) = G_XOR [[DEF]], [[C2]]
+ ; CHECK-NEXT: [[XOR6:%[0-9]+]]:_(s32) = G_XOR [[DEF]], [[C2]]
+ ; CHECK-NEXT: [[XOR7:%[0-9]+]]:_(s32) = G_XOR [[DEF]], [[C3]]
+ ; CHECK-NEXT: [[OR4:%[0-9]+]]:_(s32) = G_OR [[XOR4]], [[XOR5]]
+ ; CHECK-NEXT: [[OR5:%[0-9]+]]:_(s32) = G_OR [[OR4]], [[XOR6]]
+ ; CHECK-NEXT: [[OR6:%[0-9]+]]:_(s32) = G_OR [[OR5]], [[XOR7]]
+ ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[OR6]](s32), [[C2]]
+ ; CHECK-NEXT: [[OR7:%[0-9]+]]:_(s32) = G_OR [[OR3]], [[ICMP1]]
+ ; CHECK-NEXT: $x10 = COPY [[OR7]](s32)
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:_(s128) = G_IMPLICIT_DEF
+ %1:_(s1) = G_IS_FPCLASS %0(s128), 608
+ %2:_(s32) = G_ANYEXT %1(s1)
+ $x10 = COPY %2(s32)
+ PseudoRET implicit $x10
+
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-is-fpclass-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-is-fpclass-rv64.mir
index 735398b873c6c..ecddc3484f697 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-is-fpclass-rv64.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-is-fpclass-rv64.mir
@@ -50,3 +50,35 @@ body: |
PseudoRET implicit $x10
...
+---
+name: is_fpclass_f128
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: is_fpclass_f128
+ ; CHECK: [[DEF:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 9223372036854775807
+ ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
+ ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 9223090561878065152
+ ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[DEF]], [[C]]
+ ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s64) = G_AND [[DEF]], [[C1]]
+ ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
+ ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s64) = G_XOR [[AND]], [[C2]]
+ ; CHECK-NEXT: [[XOR1:%[0-9]+]]:_(s64) = G_XOR [[AND1]], [[C2]]
+ ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s64) = G_OR [[XOR]], [[XOR1]]
+ ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(eq), [[OR]](s64), [[C2]]
+ ; CHECK-NEXT: [[OR1:%[0-9]+]]:_(s64) = G_OR [[C4]], [[ICMP]]
+ ; CHECK-NEXT: [[XOR2:%[0-9]+]]:_(s64) = G_XOR [[DEF]], [[C2]]
+ ; CHECK-NEXT: [[XOR3:%[0-9]+]]:_(s64) = G_XOR [[DEF]], [[C3]]
+ ; CHECK-NEXT: [[OR2:%[0-9]+]]:_(s64) = G_OR [[XOR2]], [[XOR3]]
+ ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s64) = G_ICMP intpred(eq), [[OR2]](s64), [[C2]]
+ ; CHECK-NEXT: [[OR3:%[0-9]+]]:_(s64) = G_OR [[OR1]], [[ICMP1]]
+ ; CHECK-NEXT: $x10 = COPY [[OR3]](s64)
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:_(s128) = G_IMPLICIT_DEF
+ %1:_(s1) = G_IS_FPCLASS %0(s128), 608
+ %2:_(s64) = G_ANYEXT %1(s1)
+ $x10 = COPY %2(s64)
+ PseudoRET implicit $x10
+
+...
>From f471d223053041b5aa702316c2fe44163248de0a Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Tue, 5 May 2026 09:50:23 +0200
Subject: [PATCH 2/5] Catch all lowering, end-to-end tests
---
.../Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 2 +-
.../RISCV/GlobalISel/double-intrinsics.ll | 129 ++++++++++++++++++
.../GlobalISel/legalizer-info-validation.mir | 4 +-
3 files changed, 132 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index 0b7eedadbf4af..b7efee8bf4c83 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -583,7 +583,7 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
.customFor(ST.hasStdExtF(), {{s1, s32}})
.customFor(ST.hasStdExtD(), {{s1, s64}})
.customFor(ST.hasStdExtZfh(), {{s1, s16}})
- .lowerFor({{s1, s32}, {s1, s64}, {s1, s128}});
+ .lower();
getActionDefinitionsBuilder(G_FCONSTANT)
.legalFor(ST.hasStdExtF(), {s32})
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/double-intrinsics.ll b/llvm/test/CodeGen/RISCV/GlobalISel/double-intrinsics.ll
index 906e4bc41d960..13f1dbff77e1a 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/double-intrinsics.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/double-intrinsics.ll
@@ -1014,6 +1014,135 @@ define i1 @isnan_d_fpclass(double %x) {
ret i1 %1
}
+define i1 @isnan_q_fpclass(fp128 %x) {
+; RV32IFD-LABEL: isnan_q_fpclass:
+; RV32IFD: # %bb.0:
+; RV32IFD-NEXT: lw a3, 4(a0)
+; RV32IFD-NEXT: lw a2, 12(a0)
+; RV32IFD-NEXT: lw a1, 8(a0)
+; RV32IFD-NEXT: slli a2, a2, 1
+; RV32IFD-NEXT: beqz a3, .LBB26_2
+; RV32IFD-NEXT: # %bb.1:
+; RV32IFD-NEXT: snez a0, a3
+; RV32IFD-NEXT: j .LBB26_3
+; RV32IFD-NEXT: .LBB26_2:
+; RV32IFD-NEXT: lw a0, 0(a0)
+; RV32IFD-NEXT: snez a0, a0
+; RV32IFD-NEXT: .LBB26_3:
+; RV32IFD-NEXT: lui a3, 524272
+; RV32IFD-NEXT: srli a2, a2, 1
+; RV32IFD-NEXT: bnez a1, .LBB26_6
+; RV32IFD-NEXT: # %bb.4:
+; RV32IFD-NEXT: bne a2, a3, .LBB26_7
+; RV32IFD-NEXT: .LBB26_5:
+; RV32IFD-NEXT: ret
+; RV32IFD-NEXT: .LBB26_6:
+; RV32IFD-NEXT: snez a0, a1
+; RV32IFD-NEXT: beq a2, a3, .LBB26_5
+; RV32IFD-NEXT: .LBB26_7:
+; RV32IFD-NEXT: sltu a0, a3, a2
+; RV32IFD-NEXT: ret
+;
+; RV64IFD-LABEL: isnan_q_fpclass:
+; RV64IFD: # %bb.0:
+; RV64IFD-NEXT: lui a2, 32767
+; RV64IFD-NEXT: slli a3, a1, 1
+; RV64IFD-NEXT: slli a1, a2, 36
+; RV64IFD-NEXT: srli a2, a3, 1
+; RV64IFD-NEXT: beq a2, a1, .LBB26_2
+; RV64IFD-NEXT: # %bb.1:
+; RV64IFD-NEXT: sltu a0, a1, a2
+; RV64IFD-NEXT: ret
+; RV64IFD-NEXT: .LBB26_2:
+; RV64IFD-NEXT: snez a0, a0
+; RV64IFD-NEXT: ret
+;
+; RV32I-LABEL: isnan_q_fpclass:
+; RV32I: # %bb.0:
+; RV32I-NEXT: lw a3, 4(a0)
+; RV32I-NEXT: lw a2, 12(a0)
+; RV32I-NEXT: lw a1, 8(a0)
+; RV32I-NEXT: slli a2, a2, 1
+; RV32I-NEXT: beqz a3, .LBB26_2
+; RV32I-NEXT: # %bb.1:
+; RV32I-NEXT: snez a0, a3
+; RV32I-NEXT: j .LBB26_3
+; RV32I-NEXT: .LBB26_2:
+; RV32I-NEXT: lw a0, 0(a0)
+; RV32I-NEXT: snez a0, a0
+; RV32I-NEXT: .LBB26_3:
+; RV32I-NEXT: lui a3, 524272
+; RV32I-NEXT: srli a2, a2, 1
+; RV32I-NEXT: bnez a1, .LBB26_6
+; RV32I-NEXT: # %bb.4:
+; RV32I-NEXT: bne a2, a3, .LBB26_7
+; RV32I-NEXT: .LBB26_5:
+; RV32I-NEXT: ret
+; RV32I-NEXT: .LBB26_6:
+; RV32I-NEXT: snez a0, a1
+; RV32I-NEXT: beq a2, a3, .LBB26_5
+; RV32I-NEXT: .LBB26_7:
+; RV32I-NEXT: sltu a0, a3, a2
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: isnan_q_fpclass:
+; RV64I: # %bb.0:
+; RV64I-NEXT: lui a2, 32767
+; RV64I-NEXT: slli a3, a1, 1
+; RV64I-NEXT: slli a1, a2, 36
+; RV64I-NEXT: srli a2, a3, 1
+; RV64I-NEXT: beq a2, a1, .LBB26_2
+; RV64I-NEXT: # %bb.1:
+; RV64I-NEXT: sltu a0, a1, a2
+; RV64I-NEXT: ret
+; RV64I-NEXT: .LBB26_2:
+; RV64I-NEXT: snez a0, a0
+; RV64I-NEXT: ret
+ %1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 3) ; nan
+ ret i1 %1
+}
+
+define i1 @iszero_q_fpclass(fp128 %x) {
+; RV32IFD-LABEL: iszero_q_fpclass:
+; RV32IFD: # %bb.0:
+; RV32IFD-NEXT: lw a1, 0(a0)
+; RV32IFD-NEXT: lw a2, 4(a0)
+; RV32IFD-NEXT: lw a3, 8(a0)
+; RV32IFD-NEXT: lw a0, 12(a0)
+; RV32IFD-NEXT: or a1, a1, a2
+; RV32IFD-NEXT: or a0, a3, a0
+; RV32IFD-NEXT: or a0, a1, a0
+; RV32IFD-NEXT: seqz a0, a0
+; RV32IFD-NEXT: ret
+;
+; RV64IFD-LABEL: iszero_q_fpclass:
+; RV64IFD: # %bb.0:
+; RV64IFD-NEXT: or a0, a0, a1
+; RV64IFD-NEXT: seqz a0, a0
+; RV64IFD-NEXT: ret
+;
+; RV32I-LABEL: iszero_q_fpclass:
+; RV32I: # %bb.0:
+; RV32I-NEXT: lw a1, 0(a0)
+; RV32I-NEXT: lw a2, 4(a0)
+; RV32I-NEXT: lw a3, 8(a0)
+; RV32I-NEXT: lw a0, 12(a0)
+; RV32I-NEXT: or a1, a1, a2
+; RV32I-NEXT: or a0, a3, a0
+; RV32I-NEXT: or a0, a1, a0
+; RV32I-NEXT: seqz a0, a0
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: iszero_q_fpclass:
+; RV64I: # %bb.0:
+; RV64I-NEXT: or a0, a0, a1
+; RV64I-NEXT: seqz a0, a0
+; RV64I-NEXT: ret
+ %1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 64) ; zero
+ ret i1 %1
+}
+
+
define double @tan_f64(double %a) nounwind {
; RV32IFD-LABEL: tan_f64:
; RV32IFD: # %bb.0:
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
index fc488807372e9..8edbf1a966dca 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
@@ -606,8 +606,8 @@
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: G_IS_FPCLASS (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
-# DEBUG-NEXT: .. the first uncovered type index: 2, OK
-# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
+# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: G_FCANONICALIZE (opcode {{[0-9]+}}): 1 type index, 0 imm indices
# DEBUG-NEXT: .. the first uncovered type index: 1, OK
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
>From c7956413f19d5e139d169b9ce4e0b3d3ac554d07 Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Tue, 5 May 2026 22:16:17 +0200
Subject: [PATCH 3/5] Remove unnecessary test
---
.../legalizer/legalize-is-fpclass-rv32.mir | 42 -------------------
1 file changed, 42 deletions(-)
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-is-fpclass-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-is-fpclass-rv32.mir
index a01b0ab701fca..fb8c5c39962a8 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-is-fpclass-rv32.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-is-fpclass-rv32.mir
@@ -50,45 +50,3 @@ body: |
PseudoRET implicit $x10
...
----
-name: is_fpclass_f128
-body: |
- bb.1:
- ; CHECK-LABEL: name: is_fpclass_f128
- ; CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
- ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
- ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647
- ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
- ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147418112
- ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[DEF]], [[C]]
- ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[DEF]], [[C]]
- ; CHECK-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[DEF]], [[C]]
- ; CHECK-NEXT: [[AND3:%[0-9]+]]:_(s32) = G_AND [[DEF]], [[C1]]
- ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
- ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[AND]], [[C2]]
- ; CHECK-NEXT: [[XOR1:%[0-9]+]]:_(s32) = G_XOR [[AND1]], [[C2]]
- ; CHECK-NEXT: [[XOR2:%[0-9]+]]:_(s32) = G_XOR [[AND2]], [[C2]]
- ; CHECK-NEXT: [[XOR3:%[0-9]+]]:_(s32) = G_XOR [[AND3]], [[C2]]
- ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[XOR]], [[XOR1]]
- ; CHECK-NEXT: [[OR1:%[0-9]+]]:_(s32) = G_OR [[OR]], [[XOR2]]
- ; CHECK-NEXT: [[OR2:%[0-9]+]]:_(s32) = G_OR [[OR1]], [[XOR3]]
- ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[OR2]](s32), [[C2]]
- ; CHECK-NEXT: [[OR3:%[0-9]+]]:_(s32) = G_OR [[C4]], [[ICMP]]
- ; CHECK-NEXT: [[XOR4:%[0-9]+]]:_(s32) = G_XOR [[DEF]], [[C2]]
- ; CHECK-NEXT: [[XOR5:%[0-9]+]]:_(s32) = G_XOR [[DEF]], [[C2]]
- ; CHECK-NEXT: [[XOR6:%[0-9]+]]:_(s32) = G_XOR [[DEF]], [[C2]]
- ; CHECK-NEXT: [[XOR7:%[0-9]+]]:_(s32) = G_XOR [[DEF]], [[C3]]
- ; CHECK-NEXT: [[OR4:%[0-9]+]]:_(s32) = G_OR [[XOR4]], [[XOR5]]
- ; CHECK-NEXT: [[OR5:%[0-9]+]]:_(s32) = G_OR [[OR4]], [[XOR6]]
- ; CHECK-NEXT: [[OR6:%[0-9]+]]:_(s32) = G_OR [[OR5]], [[XOR7]]
- ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[OR6]](s32), [[C2]]
- ; CHECK-NEXT: [[OR7:%[0-9]+]]:_(s32) = G_OR [[OR3]], [[ICMP1]]
- ; CHECK-NEXT: $x10 = COPY [[OR7]](s32)
- ; CHECK-NEXT: PseudoRET implicit $x10
- %0:_(s128) = G_IMPLICIT_DEF
- %1:_(s1) = G_IS_FPCLASS %0(s128), 608
- %2:_(s32) = G_ANYEXT %1(s1)
- $x10 = COPY %2(s32)
- PseudoRET implicit $x10
-
-...
>From 40be362c4c87fef5a515d2185cc43f951c83ae86 Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Tue, 5 May 2026 22:17:37 +0200
Subject: [PATCH 4/5] Remove unnecessary test
---
.../legalizer/legalize-is-fpclass-rv64.mir | 32 -------------------
1 file changed, 32 deletions(-)
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-is-fpclass-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-is-fpclass-rv64.mir
index ecddc3484f697..735398b873c6c 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-is-fpclass-rv64.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-is-fpclass-rv64.mir
@@ -50,35 +50,3 @@ body: |
PseudoRET implicit $x10
...
----
-name: is_fpclass_f128
-body: |
- bb.1:
- ; CHECK-LABEL: name: is_fpclass_f128
- ; CHECK: [[DEF:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF
- ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
- ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 9223372036854775807
- ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
- ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 9223090561878065152
- ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[DEF]], [[C]]
- ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s64) = G_AND [[DEF]], [[C1]]
- ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
- ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s64) = G_XOR [[AND]], [[C2]]
- ; CHECK-NEXT: [[XOR1:%[0-9]+]]:_(s64) = G_XOR [[AND1]], [[C2]]
- ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s64) = G_OR [[XOR]], [[XOR1]]
- ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(eq), [[OR]](s64), [[C2]]
- ; CHECK-NEXT: [[OR1:%[0-9]+]]:_(s64) = G_OR [[C4]], [[ICMP]]
- ; CHECK-NEXT: [[XOR2:%[0-9]+]]:_(s64) = G_XOR [[DEF]], [[C2]]
- ; CHECK-NEXT: [[XOR3:%[0-9]+]]:_(s64) = G_XOR [[DEF]], [[C3]]
- ; CHECK-NEXT: [[OR2:%[0-9]+]]:_(s64) = G_OR [[XOR2]], [[XOR3]]
- ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s64) = G_ICMP intpred(eq), [[OR2]](s64), [[C2]]
- ; CHECK-NEXT: [[OR3:%[0-9]+]]:_(s64) = G_OR [[OR1]], [[ICMP1]]
- ; CHECK-NEXT: $x10 = COPY [[OR3]](s64)
- ; CHECK-NEXT: PseudoRET implicit $x10
- %0:_(s128) = G_IMPLICIT_DEF
- %1:_(s1) = G_IS_FPCLASS %0(s128), 608
- %2:_(s64) = G_ANYEXT %1(s1)
- $x10 = COPY %2(s64)
- PseudoRET implicit $x10
-
-...
>From e8416ade58b6644cc9b97b477ff8ffd194004bd0 Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Wed, 6 May 2026 09:53:03 +0200
Subject: [PATCH 5/5] Add more tests
---
.../RISCV/GlobalISel/double-intrinsics.ll | 282 +++++++++++++++++-
1 file changed, 281 insertions(+), 1 deletion(-)
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/double-intrinsics.ll b/llvm/test/CodeGen/RISCV/GlobalISel/double-intrinsics.ll
index 13f1dbff77e1a..33338591d6e35 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/double-intrinsics.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/double-intrinsics.ll
@@ -1138,7 +1138,287 @@ define i1 @iszero_q_fpclass(fp128 %x) {
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: seqz a0, a0
; RV64I-NEXT: ret
- %1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 64) ; zero
+ %1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 64) ; positive zero
+ ret i1 %1
+}
+
+define i1 @isinf_q_fpclass(fp128 %x) {
+; RV32IFD-LABEL: isinf_q_fpclass:
+; RV32IFD: # %bb.0:
+; RV32IFD-NEXT: lw a1, 0(a0)
+; RV32IFD-NEXT: lw a2, 12(a0)
+; RV32IFD-NEXT: lw a4, 4(a0)
+; RV32IFD-NEXT: lw a3, 8(a0)
+; RV32IFD-NEXT: lui a5, 1048560
+; RV32IFD-NEXT: slli a6, a2, 1
+; RV32IFD-NEXT: sltiu a0, a1, 0
+; RV32IFD-NEXT: sltu a1, a4, a4
+; RV32IFD-NEXT: seqz a7, a4
+; RV32IFD-NEXT: and a7, a7, a0
+; RV32IFD-NEXT: or a1, a1, a7
+; RV32IFD-NEXT: seqz a7, a3
+; RV32IFD-NEXT: and a7, a7, a1
+; RV32IFD-NEXT: sub a1, a3, a1
+; RV32IFD-NEXT: sltu t0, a3, a3
+; RV32IFD-NEXT: srli a6, a6, 1
+; RV32IFD-NEXT: sub a4, a4, a0
+; RV32IFD-NEXT: xor a3, a2, a6
+; RV32IFD-NEXT: or a2, t0, a7
+; RV32IFD-NEXT: add a5, a6, a5
+; RV32IFD-NEXT: beqz a4, .LBB28_2
+; RV32IFD-NEXT: # %bb.1:
+; RV32IFD-NEXT: sltiu a0, a4, 0
+; RV32IFD-NEXT: .LBB28_2:
+; RV32IFD-NEXT: mv a4, a3
+; RV32IFD-NEXT: sub a2, a5, a2
+; RV32IFD-NEXT: lui a3, 524256
+; RV32IFD-NEXT: beqz a1, .LBB28_4
+; RV32IFD-NEXT: # %bb.3:
+; RV32IFD-NEXT: sltiu a0, a1, 0
+; RV32IFD-NEXT: .LBB28_4:
+; RV32IFD-NEXT: snez a1, a4
+; RV32IFD-NEXT: beq a2, a3, .LBB28_6
+; RV32IFD-NEXT: # %bb.5:
+; RV32IFD-NEXT: sltu a0, a2, a3
+; RV32IFD-NEXT: .LBB28_6:
+; RV32IFD-NEXT: xori a1, a1, 1
+; RV32IFD-NEXT: and a0, a0, a1
+; RV32IFD-NEXT: ret
+;
+; RV64IFD-LABEL: isinf_q_fpclass:
+; RV64IFD: # %bb.0:
+; RV64IFD-NEXT: slli a2, a1, 1
+; RV64IFD-NEXT: li a3, 1
+; RV64IFD-NEXT: sltiu a0, a0, 0
+; RV64IFD-NEXT: srli a2, a2, 1
+; RV64IFD-NEXT: slli a3, a3, 48
+; RV64IFD-NEXT: xor a1, a1, a2
+; RV64IFD-NEXT: sub a2, a2, a3
+; RV64IFD-NEXT: lui a3, 16383
+; RV64IFD-NEXT: mv a1, a1
+; RV64IFD-NEXT: sub a2, a2, a0
+; RV64IFD-NEXT: slli a3, a3, 37
+; RV64IFD-NEXT: snez a1, a1
+; RV64IFD-NEXT: beq a2, a3, .LBB28_2
+; RV64IFD-NEXT: # %bb.1:
+; RV64IFD-NEXT: sltu a0, a2, a3
+; RV64IFD-NEXT: .LBB28_2:
+; RV64IFD-NEXT: xori a1, a1, 1
+; RV64IFD-NEXT: and a0, a0, a1
+; RV64IFD-NEXT: ret
+;
+; RV32I-LABEL: isinf_q_fpclass:
+; RV32I: # %bb.0:
+; RV32I-NEXT: lw a1, 0(a0)
+; RV32I-NEXT: lw a2, 12(a0)
+; RV32I-NEXT: lw a4, 4(a0)
+; RV32I-NEXT: lw a3, 8(a0)
+; RV32I-NEXT: lui a5, 1048560
+; RV32I-NEXT: slli a6, a2, 1
+; RV32I-NEXT: sltiu a0, a1, 0
+; RV32I-NEXT: sltu a1, a4, a4
+; RV32I-NEXT: seqz a7, a4
+; RV32I-NEXT: and a7, a7, a0
+; RV32I-NEXT: or a1, a1, a7
+; RV32I-NEXT: seqz a7, a3
+; RV32I-NEXT: and a7, a7, a1
+; RV32I-NEXT: sub a1, a3, a1
+; RV32I-NEXT: sltu t0, a3, a3
+; RV32I-NEXT: srli a6, a6, 1
+; RV32I-NEXT: sub a4, a4, a0
+; RV32I-NEXT: xor a3, a2, a6
+; RV32I-NEXT: or a2, t0, a7
+; RV32I-NEXT: add a5, a6, a5
+; RV32I-NEXT: beqz a4, .LBB28_2
+; RV32I-NEXT: # %bb.1:
+; RV32I-NEXT: sltiu a0, a4, 0
+; RV32I-NEXT: .LBB28_2:
+; RV32I-NEXT: mv a4, a3
+; RV32I-NEXT: sub a2, a5, a2
+; RV32I-NEXT: lui a3, 524256
+; RV32I-NEXT: beqz a1, .LBB28_4
+; RV32I-NEXT: # %bb.3:
+; RV32I-NEXT: sltiu a0, a1, 0
+; RV32I-NEXT: .LBB28_4:
+; RV32I-NEXT: snez a1, a4
+; RV32I-NEXT: beq a2, a3, .LBB28_6
+; RV32I-NEXT: # %bb.5:
+; RV32I-NEXT: sltu a0, a2, a3
+; RV32I-NEXT: .LBB28_6:
+; RV32I-NEXT: xori a1, a1, 1
+; RV32I-NEXT: and a0, a0, a1
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: isinf_q_fpclass:
+; RV64I: # %bb.0:
+; RV64I-NEXT: slli a2, a1, 1
+; RV64I-NEXT: li a3, 1
+; RV64I-NEXT: sltiu a0, a0, 0
+; RV64I-NEXT: srli a2, a2, 1
+; RV64I-NEXT: slli a3, a3, 48
+; RV64I-NEXT: xor a1, a1, a2
+; RV64I-NEXT: sub a2, a2, a3
+; RV64I-NEXT: lui a3, 16383
+; RV64I-NEXT: mv a1, a1
+; RV64I-NEXT: sub a2, a2, a0
+; RV64I-NEXT: slli a3, a3, 37
+; RV64I-NEXT: snez a1, a1
+; RV64I-NEXT: beq a2, a3, .LBB28_2
+; RV64I-NEXT: # %bb.1:
+; RV64I-NEXT: sltu a0, a2, a3
+; RV64I-NEXT: .LBB28_2:
+; RV64I-NEXT: xori a1, a1, 1
+; RV64I-NEXT: and a0, a0, a1
+; RV64I-NEXT: ret
+ %1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 256) ; positive infinity
+ ret i1 %1
+}
+
+define i1 @isinf_or_zero_q_fpclass(fp128 %x) {
+; RV32IFD-LABEL: isinf_or_zero_q_fpclass:
+; RV32IFD: # %bb.0:
+; RV32IFD-NEXT: lw a3, 0(a0)
+; RV32IFD-NEXT: lw a4, 12(a0)
+; RV32IFD-NEXT: lw a5, 4(a0)
+; RV32IFD-NEXT: lw a6, 8(a0)
+; RV32IFD-NEXT: lui a7, 1048560
+; RV32IFD-NEXT: slli t0, a4, 1
+; RV32IFD-NEXT: or a1, a3, a5
+; RV32IFD-NEXT: or a2, a6, a4
+; RV32IFD-NEXT: sltiu a0, a3, 0
+; RV32IFD-NEXT: sltu a3, a5, a5
+; RV32IFD-NEXT: seqz t1, a5
+; RV32IFD-NEXT: and t1, t1, a0
+; RV32IFD-NEXT: or a3, a3, t1
+; RV32IFD-NEXT: seqz t1, a6
+; RV32IFD-NEXT: and t1, t1, a3
+; RV32IFD-NEXT: sub a3, a6, a3
+; RV32IFD-NEXT: sltu t2, a6, a6
+; RV32IFD-NEXT: srli t0, t0, 1
+; RV32IFD-NEXT: sub a5, a5, a0
+; RV32IFD-NEXT: xor a6, a4, t0
+; RV32IFD-NEXT: or a4, t2, t1
+; RV32IFD-NEXT: add a7, t0, a7
+; RV32IFD-NEXT: beqz a5, .LBB29_2
+; RV32IFD-NEXT: # %bb.1:
+; RV32IFD-NEXT: sltiu a0, a5, 0
+; RV32IFD-NEXT: .LBB29_2:
+; RV32IFD-NEXT: mv a6, a6
+; RV32IFD-NEXT: or a5, a1, a2
+; RV32IFD-NEXT: sub a1, a7, a4
+; RV32IFD-NEXT: lui a2, 524256
+; RV32IFD-NEXT: beqz a3, .LBB29_4
+; RV32IFD-NEXT: # %bb.3:
+; RV32IFD-NEXT: sltiu a0, a3, 0
+; RV32IFD-NEXT: .LBB29_4:
+; RV32IFD-NEXT: snez a4, a6
+; RV32IFD-NEXT: seqz a3, a5
+; RV32IFD-NEXT: beq a1, a2, .LBB29_6
+; RV32IFD-NEXT: # %bb.5:
+; RV32IFD-NEXT: sltu a0, a1, a2
+; RV32IFD-NEXT: .LBB29_6:
+; RV32IFD-NEXT: xori a1, a4, 1
+; RV32IFD-NEXT: and a0, a0, a1
+; RV32IFD-NEXT: or a0, a3, a0
+; RV32IFD-NEXT: ret
+;
+; RV64IFD-LABEL: isinf_or_zero_q_fpclass:
+; RV64IFD: # %bb.0:
+; RV64IFD-NEXT: slli a2, a1, 1
+; RV64IFD-NEXT: or a5, a0, a1
+; RV64IFD-NEXT: li a3, 1
+; RV64IFD-NEXT: sltiu a0, a0, 0
+; RV64IFD-NEXT: srli a2, a2, 1
+; RV64IFD-NEXT: slli a3, a3, 48
+; RV64IFD-NEXT: xor a1, a1, a2
+; RV64IFD-NEXT: sub a2, a2, a3
+; RV64IFD-NEXT: lui a3, 16383
+; RV64IFD-NEXT: slli a3, a3, 37
+; RV64IFD-NEXT: mv a1, a1
+; RV64IFD-NEXT: sub a4, a2, a0
+; RV64IFD-NEXT: snez a2, a1
+; RV64IFD-NEXT: seqz a1, a5
+; RV64IFD-NEXT: beq a4, a3, .LBB29_2
+; RV64IFD-NEXT: # %bb.1:
+; RV64IFD-NEXT: sltu a0, a4, a3
+; RV64IFD-NEXT: .LBB29_2:
+; RV64IFD-NEXT: xori a2, a2, 1
+; RV64IFD-NEXT: and a0, a0, a2
+; RV64IFD-NEXT: or a0, a1, a0
+; RV64IFD-NEXT: ret
+;
+; RV32I-LABEL: isinf_or_zero_q_fpclass:
+; RV32I: # %bb.0:
+; RV32I-NEXT: lw a3, 0(a0)
+; RV32I-NEXT: lw a4, 12(a0)
+; RV32I-NEXT: lw a5, 4(a0)
+; RV32I-NEXT: lw a6, 8(a0)
+; RV32I-NEXT: lui a7, 1048560
+; RV32I-NEXT: slli t0, a4, 1
+; RV32I-NEXT: or a1, a3, a5
+; RV32I-NEXT: or a2, a6, a4
+; RV32I-NEXT: sltiu a0, a3, 0
+; RV32I-NEXT: sltu a3, a5, a5
+; RV32I-NEXT: seqz t1, a5
+; RV32I-NEXT: and t1, t1, a0
+; RV32I-NEXT: or a3, a3, t1
+; RV32I-NEXT: seqz t1, a6
+; RV32I-NEXT: and t1, t1, a3
+; RV32I-NEXT: sub a3, a6, a3
+; RV32I-NEXT: sltu t2, a6, a6
+; RV32I-NEXT: srli t0, t0, 1
+; RV32I-NEXT: sub a5, a5, a0
+; RV32I-NEXT: xor a6, a4, t0
+; RV32I-NEXT: or a4, t2, t1
+; RV32I-NEXT: add a7, t0, a7
+; RV32I-NEXT: beqz a5, .LBB29_2
+; RV32I-NEXT: # %bb.1:
+; RV32I-NEXT: sltiu a0, a5, 0
+; RV32I-NEXT: .LBB29_2:
+; RV32I-NEXT: mv a6, a6
+; RV32I-NEXT: or a5, a1, a2
+; RV32I-NEXT: sub a1, a7, a4
+; RV32I-NEXT: lui a2, 524256
+; RV32I-NEXT: beqz a3, .LBB29_4
+; RV32I-NEXT: # %bb.3:
+; RV32I-NEXT: sltiu a0, a3, 0
+; RV32I-NEXT: .LBB29_4:
+; RV32I-NEXT: snez a4, a6
+; RV32I-NEXT: seqz a3, a5
+; RV32I-NEXT: beq a1, a2, .LBB29_6
+; RV32I-NEXT: # %bb.5:
+; RV32I-NEXT: sltu a0, a1, a2
+; RV32I-NEXT: .LBB29_6:
+; RV32I-NEXT: xori a1, a4, 1
+; RV32I-NEXT: and a0, a0, a1
+; RV32I-NEXT: or a0, a3, a0
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: isinf_or_zero_q_fpclass:
+; RV64I: # %bb.0:
+; RV64I-NEXT: slli a2, a1, 1
+; RV64I-NEXT: or a5, a0, a1
+; RV64I-NEXT: li a3, 1
+; RV64I-NEXT: sltiu a0, a0, 0
+; RV64I-NEXT: srli a2, a2, 1
+; RV64I-NEXT: slli a3, a3, 48
+; RV64I-NEXT: xor a1, a1, a2
+; RV64I-NEXT: sub a2, a2, a3
+; RV64I-NEXT: lui a3, 16383
+; RV64I-NEXT: slli a3, a3, 37
+; RV64I-NEXT: mv a1, a1
+; RV64I-NEXT: sub a4, a2, a0
+; RV64I-NEXT: snez a2, a1
+; RV64I-NEXT: seqz a1, a5
+; RV64I-NEXT: beq a4, a3, .LBB29_2
+; RV64I-NEXT: # %bb.1:
+; RV64I-NEXT: sltu a0, a4, a3
+; RV64I-NEXT: .LBB29_2:
+; RV64I-NEXT: xori a2, a2, 1
+; RV64I-NEXT: and a0, a0, a2
+; RV64I-NEXT: or a0, a1, a0
+; RV64I-NEXT: ret
+ %1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 320) ; positive zero or inf.
ret i1 %1
}
More information about the llvm-commits
mailing list