DAG: Fix broken lowering of is.fplcass fcZero with DAZ
authorMatt Arsenault <Matthew.Arsenault@amd.com>
Tue, 31 Jan 2023 18:23:56 +0000 (14:23 -0400)
committerMatt Arsenault <arsenm2@gmail.com>
Sun, 5 Feb 2023 13:14:16 +0000 (09:14 -0400)
is.fpclass x, fcZero is not equivalent to fcmp with 0 if
denormals are treated as 0. It would be equivalent to fcZero|fcSubnormal
which can be done separately; this is the minimal correctness fix.

The same optimization was not ported to the GlobalISel version.

llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
llvm/test/CodeGen/X86/is_fpclass.ll

index 429184d..db26fd2 100644 (file)
@@ -8042,10 +8042,19 @@ SDValue TargetLowering::expandIS_FPCLASS(EVT ResultVT, SDValue Op,
   // exceptions are ignored.
   if (Flags.hasNoFPExcept() &&
       isOperationLegalOrCustom(ISD::SETCC, OperandVT.getScalarType())) {
-    if (Test == fcZero)
-      return DAG.getSetCC(DL, ResultVT, Op,
-                          DAG.getConstantFP(0.0, DL, OperandVT),
-                          IsInverted ? ISD::SETUNE : ISD::SETOEQ);
+    if (Test == fcZero) {
+      DenormalMode Mode = DAG.getMachineFunction().getDenormalMode(Semantics);
+      if (Mode.Input == DenormalMode::IEEE) {
+        // If denormals could be implicitly treated as 0, this is not equivalent
+        // to a compare with 0 since it will also be true for denormals.
+        //
+        // TODO: With DAZ, check == fcZero | fcSubnormal
+        return DAG.getSetCC(DL, ResultVT, Op,
+                            DAG.getConstantFP(0.0, DL, OperandVT),
+                            IsInverted ? ISD::SETUNE : ISD::SETOEQ);
+      }
+    }
+
     if (Test == fcNan)
       return DAG.getSetCC(DL, ResultVT, Op, Op,
                           IsInverted ? ISD::SETO : ISD::SETUO);
index 10183fb..edeadd0 100644 (file)
@@ -416,24 +416,15 @@ entry:
 define i1 @iszero_f_daz(float %x) #0 {
 ; CHECK-32-LABEL: iszero_f_daz:
 ; CHECK-32:       # %bb.0: # %entry
-; CHECK-32-NEXT:    flds {{[0-9]+}}(%esp)
-; CHECK-32-NEXT:    fldz
-; CHECK-32-NEXT:    fucompp
-; CHECK-32-NEXT:    fnstsw %ax
-; CHECK-32-NEXT:    # kill: def $ah killed $ah killed $ax
-; CHECK-32-NEXT:    sahf
-; CHECK-32-NEXT:    setnp %cl
+; CHECK-32-NEXT:    testl $2147483647, {{[0-9]+}}(%esp) # imm = 0x7FFFFFFF
 ; CHECK-32-NEXT:    sete %al
-; CHECK-32-NEXT:    andb %cl, %al
 ; CHECK-32-NEXT:    retl
 ;
 ; CHECK-64-LABEL: iszero_f_daz:
 ; CHECK-64:       # %bb.0: # %entry
-; CHECK-64-NEXT:    xorps %xmm1, %xmm1
-; CHECK-64-NEXT:    cmpeqss %xmm0, %xmm1
-; CHECK-64-NEXT:    movd %xmm1, %eax
-; CHECK-64-NEXT:    andl $1, %eax
-; CHECK-64-NEXT:    # kill: def $al killed $al killed $eax
+; CHECK-64-NEXT:    movd %xmm0, %eax
+; CHECK-64-NEXT:    testl $2147483647, %eax # imm = 0x7FFFFFFF
+; CHECK-64-NEXT:    sete %al
 ; CHECK-64-NEXT:    retq
 entry:
   %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 96)  ; 0x60 = "zero"
@@ -443,24 +434,15 @@ entry:
 define i1 @iszero_f_maybe_daz(float %x) #1 {
 ; CHECK-32-LABEL: iszero_f_maybe_daz:
 ; CHECK-32:       # %bb.0: # %entry
-; CHECK-32-NEXT:    flds {{[0-9]+}}(%esp)
-; CHECK-32-NEXT:    fldz
-; CHECK-32-NEXT:    fucompp
-; CHECK-32-NEXT:    fnstsw %ax
-; CHECK-32-NEXT:    # kill: def $ah killed $ah killed $ax
-; CHECK-32-NEXT:    sahf
-; CHECK-32-NEXT:    setnp %cl
+; CHECK-32-NEXT:    testl $2147483647, {{[0-9]+}}(%esp) # imm = 0x7FFFFFFF
 ; CHECK-32-NEXT:    sete %al
-; CHECK-32-NEXT:    andb %cl, %al
 ; CHECK-32-NEXT:    retl
 ;
 ; CHECK-64-LABEL: iszero_f_maybe_daz:
 ; CHECK-64:       # %bb.0: # %entry
-; CHECK-64-NEXT:    xorps %xmm1, %xmm1
-; CHECK-64-NEXT:    cmpeqss %xmm0, %xmm1
-; CHECK-64-NEXT:    movd %xmm1, %eax
-; CHECK-64-NEXT:    andl $1, %eax
-; CHECK-64-NEXT:    # kill: def $al killed $al killed $eax
+; CHECK-64-NEXT:    movd %xmm0, %eax
+; CHECK-64-NEXT:    testl $2147483647, %eax # imm = 0x7FFFFFFF
+; CHECK-64-NEXT:    sete %al
 ; CHECK-64-NEXT:    retq
 entry:
   %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 96)  ; 0x60 = "zero"