[llvm] b27f231 - Revert "Reland [PowerPC] improve performance on the isNan and !isNan function in case of -ffp-model=strict" (#214751)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 7 09:02:52 PDT 2026
Author: zhijian lin
Date: 2026-08-07T12:02:47-04:00
New Revision: b27f2310cf1a23b9afc84795dadde7755bf5a30c
URL: https://github.com/llvm/llvm-project/commit/b27f2310cf1a23b9afc84795dadde7755bf5a30c
DIFF: https://github.com/llvm/llvm-project/commit/b27f2310cf1a23b9afc84795dadde7755bf5a30c.diff
LOG: Revert "Reland [PowerPC] improve performance on the isNan and !isNan function in case of -ffp-model=strict" (#214751)
the commit 7e1aba74a4f702dbd0b5c2ebc87f88dffb851b6e
cause following problem:
Commit
https://github.com/llvm/llvm-project/commit/7e1aba74a4f702dbd0b5c2ebc87f88dffb851b6e
moved setOperationAction(IS_FPCLASS, MVT::f32/f64, Custom) to an
unconditional block, causing all PPC targets — including
powerpc64-ibm-aix -m32 — to mark IS_FPCLASS as Custom. This exposed two
crashes when compiling compiler-rt/builtins for 32-bit AIX (-m32
-mcpu=pwr7):
Crash 1 — masks fcFinite/fcInf/fcInf|fcNan at -O2 (divdc3.c, muldc3.c)
At -O2, IS_FPCLASS nodes carry the nofpexcept flag. For mask 504
(fcFinite, from __builtin_isfinite under -ffp-model=strict) and mask 519
(fcInf|fcNan, injected post-legalize when SimplifySetCC transforms
SETUEQ(fabs(x), +inf) into a new IS_FPCLASS node), LowerIS_FPCLASS
returned SDValue(). This caused ExpandNode to call expandIS_FPCLASS
post-legalize, which fell to the integer-bitcast path computing IntVT =
i64. Since i64 is not a legal type on PPC32, this crashed with:
fatal error: error in backend: Cannot select: t9: i1 = is_fpclass
nofpexcept t8, TargetConstant:i32<519>
Crash 2 — masks fcNan/~fcNan at -O0 (divdc3.c)
At -O0, IS_FPCLASS nodes lack nofpexcept, so expandIS_FPCLASS's
float-comparison path is skipped entirely for all masks. For masks
504/516/519 this triggers the same integer-bitcast crash as above. For
masks 3 (fcNan) and 1020 (~fcNan), LowerIS_FPCLASS reached the
fcmpu/xscmpudp path added by
https://github.com/llvm/llvm-project/commit/7e1aba74a4f702dbd0b5c2ebc87f88dffb851b6e,
but that path emitted getNOT(..., MVT::i1) — an XOR on MVT::i1. Since
useCRBits=false on pwr7 and earlier targets, MVT::i1 is not a legal
type, triggering::
Assertion failed: "Unexpected illegal type!" in LegalizeDAG.cpp
This crash was hidden at -O2 because nofpexcept caused those nodes to be
handled by expandIS_FPCLASS before reaching LowerIS_FPCLASS.
This reverts commit 7e1aba74a4f702dbd0b5c2ebc87f88dffb851b6e.
Added:
Modified:
llvm/lib/Target/PowerPC/PPCISelLowering.cpp
Removed:
llvm/test/CodeGen/PowerPC/fp-classify-nan.ll
################################################################################
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index e338a083386573..e3d74eb389d155 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -817,9 +817,6 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
setOperationAction(ISD::FCANONICALIZE, MVT::f32, Legal);
}
- setOperationAction(ISD::IS_FPCLASS, MVT::f32, Custom);
- setOperationAction(ISD::IS_FPCLASS, MVT::f64, Custom);
-
if (Subtarget.hasAltivec()) {
for (MVT VT : { MVT::v16i8, MVT::v8i16, MVT::v4i32 }) {
setOperationAction(ISD::AVGCEILS, VT, Legal);
@@ -1261,8 +1258,11 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
if (Subtarget.hasP9Vector()) {
setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v4i32, Custom);
setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v4f32, Custom);
+
// Test data class instructions store results in CR bits.
if (Subtarget.useCRBits()) {
+ setOperationAction(ISD::IS_FPCLASS, MVT::f32, Custom);
+ setOperationAction(ISD::IS_FPCLASS, MVT::f64, Custom);
setOperationAction(ISD::IS_FPCLASS, MVT::f128, Custom);
setOperationAction(ISD::IS_FPCLASS, MVT::ppcf128, Custom);
}
@@ -11964,78 +11964,18 @@ static SDValue getDataClassTest(SDValue Op, FPClassTest Mask, const SDLoc &Dl,
SDValue PPCTargetLowering::LowerIS_FPCLASS(SDValue Op,
SelectionDAG &DAG) const {
+ assert(Subtarget.hasP9Vector() && "Test data class requires Power9");
SDValue LHS = Op.getOperand(0);
uint64_t RHSC = Op.getConstantOperandVal(1);
SDLoc Dl(Op);
FPClassTest Category = static_cast<FPClassTest>(RHSC);
- EVT VT = LHS.getValueType();
-
- assert((VT == MVT::f32 || VT == MVT::f64 ||
- ((VT == MVT::f128 || VT == MVT::ppcf128) && Subtarget.hasVSX() &&
- Subtarget.useCRBits())) &&
- "invalid customize type for IS_FPCLASS.");
- // Handle ppcf128 by extracting the higher part
- if (VT == MVT::ppcf128) {
+ if (LHS.getValueType() == MVT::ppcf128) {
// The higher part determines the value class.
LHS = DAG.getNode(ISD::EXTRACT_ELEMENT, Dl, MVT::f64, LHS,
DAG.getConstant(1, Dl, MVT::i32));
- VT = MVT::f64;
- }
-
- // If we have P9Vector and useCRBits, use the data class test instructions
- if (Subtarget.hasP9Vector() && Subtarget.useCRBits()) {
- return getDataClassTest(LHS, Category, Dl, DAG, Subtarget);
- }
-
- // For non-P9Vector targets, we can only check for NaN using fcmpu/xscmpudp
- // These instructions set CR bits based on comparison with itself:
- // - If value is NaN, the comparison is unordered (FU bit set)
- // - If value is not NaN, the comparison is equal (EQ bit set)
-
- if ((Category != fcNan) && (Category != ~fcNan)) {
- // If not checking for NaN or non-NaN, we can't handle this without P9Vector
- return SDValue();
}
- // Determine which comparison instruction to use based on vector support
- unsigned CmpOp;
-
- if (Subtarget.hasVSX()) {
- // Use xscmpudp for VSX targets (both f32 and f64)
- // For f32, extend to f64 first
- if (VT == MVT::f32) {
- LHS = DAG.getNode(ISD::FP_EXTEND, Dl, MVT::f64, LHS);
- } else if (VT != MVT::f64) {
- return SDValue();
- }
- CmpOp = PPC::XSCMPUDP;
- } else {
- // Use fcmpu for non-VSX targets
- // FCMPUS and FCMPUD both map to the same fcmpu instruction,
- // just with
diff erent register classes (f4rc vs f8rc)
- if (VT == MVT::f64) {
- CmpOp = PPC::FCMPUD;
- } else if (VT == MVT::f32) {
- CmpOp = PPC::FCMPUS;
- } else {
- return SDValue();
- }
- }
-
- // Create the comparison: fcmpu/xscmpudp CR, LHS, LHS
- // The CR field output will be allocated by the register allocator
- SDValue Cmp = SDValue(DAG.getMachineNode(CmpOp, Dl, MVT::i32, LHS, LHS), 0);
-
- // Extract the unordered bit (FU) from the CR field
- // For NaN detection: FU bit is set if operands are unordered (i.e., NaN)
- SDValue NanCheck = SDValue(
- DAG.getMachineNode(
- TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1, Cmp,
- DAG.getTargetConstant(Category == ~fcNan ? PPC::sub_un : PPC::sub_eq,
- Dl, MVT::i32)),
- 0);
-
- return DAG.getNOT(Dl, NanCheck, MVT::i1);
+ return getDataClassTest(LHS, Category, Dl, DAG, Subtarget);
}
// Adjust the length value for a load/store with length to account for the
diff --git a/llvm/test/CodeGen/PowerPC/fp-classify-nan.ll b/llvm/test/CodeGen/PowerPC/fp-classify-nan.ll
deleted file mode 100644
index 3a866984f2ba76..00000000000000
--- a/llvm/test/CodeGen/PowerPC/fp-classify-nan.ll
+++ /dev/null
@@ -1,126 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr8 < %s \
-; RUN: -verify-machineinstrs -ppc-asm-full-reg-names | FileCheck %s --check-prefix=P8
-; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr9 < %s \
-; RUN: -verify-machineinstrs -ppc-asm-full-reg-names | FileCheck %s --check-prefix=P9
-; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr8 -mattr=-vsx < %s \
-; RUN: -verify-machineinstrs -ppc-asm-full-reg-names | FileCheck %s --check-prefix=P8-NO-VSX
-
-; RUN: llc -mtriple=powerpc-ibm-aix7.2.0.0 -mcpu=pwr8 < %s \
-; RUN: -verify-machineinstrs -ppc-asm-full-reg-names | FileCheck %s --check-prefix=P8
-; RUN: llc -mtriple=powerpc-ibm-aix7.2.0.0 -mcpu=pwr9 < %s \
-; RUN: -verify-machineinstrs -ppc-asm-full-reg-names | FileCheck %s --check-prefix=P9
-; RUN: llc -mtriple=powerpc-ibm-aix7.2.0.0 -mcpu=pwr8 -mattr=-vsx < %s \
-; RUN: -verify-machineinstrs -ppc-asm-full-reg-names | FileCheck %s --check-prefix=P8-NO-VSX
-;
-define zeroext i1 @test_is_nan_f64(double %x) #0 {
-; P8-LABEL: test_is_nan_f64:
-; P8: # %bb.0:
-; P8-NEXT: xscmpudp cr0, f1, f1
-; P8-NEXT: li r3, 1
-; P8-NEXT: iseleq r3, 0, r3
-; P8-NEXT: blr
-;
-; P9-LABEL: test_is_nan_f64:
-; P9: # %bb.0:
-; P9-NEXT: xststdcdp cr0, f1, 64
-; P9-NEXT: li r3, 0
-; P9-NEXT: li r4, 1
-; P9-NEXT: iseleq r3, r4, r3
-; P9-NEXT: blr
-;
-; P8-NO-VSX-LABEL: test_is_nan_f64:
-; P8-NO-VSX: # %bb.0:
-; P8-NO-VSX-NEXT: fcmpu cr0, f1, f1
-; P8-NO-VSX-NEXT: li r3, 1
-; P8-NO-VSX-NEXT: iseleq r3, 0, r3
-; P8-NO-VSX-NEXT: blr
- %result = call i1 @llvm.is.fpclass.f64(double %x, i32 3)
- ret i1 %result
-}
-
-define zeroext i1 @test_is_not_nan_f64(double %x) #0 {
-; P8-LABEL: test_is_not_nan_f64:
-; P8: # %bb.0:
-; P8-NEXT: xscmpudp cr0, f1, f1
-; P8-NEXT: li r3, 1
-; P8-NEXT: isel r3, 0, r3, un
-; P8-NEXT: blr
-;
-; P9-LABEL: test_is_not_nan_f64:
-; P9: # %bb.0:
-; P9-NEXT: xststdcdp cr0, f1, 64
-; P9-NEXT: li r3, 1
-; P9-NEXT: iseleq r3, 0, r3
-; P9-NEXT: blr
-;
-; P8-NO-VSX-LABEL: test_is_not_nan_f64:
-; P8-NO-VSX: # %bb.0:
-; P8-NO-VSX-NEXT: fcmpu cr0, f1, f1
-; P8-NO-VSX-NEXT: li r3, 1
-; P8-NO-VSX-NEXT: isel r3, 0, r3, un
-; P8-NO-VSX-NEXT: blr
- %result = call i1 @llvm.is.fpclass.f64(double %x, i32 1020)
- ret i1 %result
-}
-
-define zeroext i1 @test_is_nan_f32(float %x) #0 {
-; P8-LABEL: test_is_nan_f32:
-; P8: # %bb.0:
-; P8-NEXT: xscmpudp cr0, f1, f1
-; P8-NEXT: li r3, 1
-; P8-NEXT: iseleq r3, 0, r3
-; P8-NEXT: blr
-;
-; P9-LABEL: test_is_nan_f32:
-; P9: # %bb.0:
-; P9-NEXT: xststdcsp cr0, f1, 64
-; P9-NEXT: li r3, 0
-; P9-NEXT: li r4, 1
-; P9-NEXT: iseleq r3, r4, r3
-; P9-NEXT: blr
-;
-; P8-NO-VSX-LABEL: test_is_nan_f32:
-; P8-NO-VSX: # %bb.0:
-; P8-NO-VSX-NEXT: fcmpu cr0, f1, f1
-; P8-NO-VSX-NEXT: li r3, 1
-; P8-NO-VSX-NEXT: iseleq r3, 0, r3
-; P8-NO-VSX-NEXT: blr
- %result = call i1 @llvm.is.fpclass.f32(float %x, i32 3)
- ret i1 %result
-}
-
-define zeroext i1 @test_is_not_nan_f32(float %x) #0 {
-; P8-LABEL: test_is_not_nan_f32:
-; P8: # %bb.0:
-; P8-NEXT: xscmpudp cr0, f1, f1
-; P8-NEXT: li r3, 1
-; P8-NEXT: isel r3, 0, r3, un
-; P8-NEXT: blr
-;
-; P9-LABEL: test_is_not_nan_f32:
-; P9: # %bb.0:
-; P9-NEXT: xststdcsp cr0, f1, 64
-; P9-NEXT: li r3, 1
-; P9-NEXT: iseleq r3, 0, r3
-; P9-NEXT: blr
-;
-; P8-NO-VSX-LABEL: test_is_not_nan_f32:
-; P8-NO-VSX: # %bb.0:
-; P8-NO-VSX-NEXT: fcmpu cr0, f1, f1
-; P8-NO-VSX-NEXT: li r3, 1
-; P8-NO-VSX-NEXT: isel r3, 0, r3, un
-; P8-NO-VSX-NEXT: blr
- %result = call i1 @llvm.is.fpclass.f32(float %x, i32 1020)
- ret i1 %result
-}
-
-declare i1 @llvm.is.fpclass.f64(double, i32)
-declare i1 @llvm.is.fpclass.f32(float, i32)
-declare float @llvm.fabs.f32(float)
-declare double @llvm.fabs.f64(double)
-declare fp128 @llvm.fabs.f128(fp128)
-declare <4 x float> @llvm.fabs.v4f32(<4 x float>)
-declare <2 x double> @llvm.fabs.v2f64(<2 x double>)
-
-attributes #0 = {strictfp}
More information about the llvm-commits
mailing list