diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 0e8e4c9618bb2..2c810c2b885d3 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -18235,6 +18235,16 @@ SDValue DAGCombiner::combineRepeatedFPDivisors(SDNode *N) { if (N0CFP && (N0CFP->isExactlyValue(1.0) || N0CFP->isExactlyValue(-1.0))) return SDValue(); + // Skip if we have subnormals, multiplying with the reciprocal will introduce + // infinities. + ConstantFPSDNode *N1CFP = isConstOrConstSplatFP(N1, /* AllowUndefs */ true); + if (N1CFP) { + FPClassTest FPClass = N1CFP->getValueAPF().classify(); + if (FPClass == fcPosSubnormal || FPClass == fcNegSubnormal) { + return SDValue(); + } + } + // Exit early if the target does not want this transform or if there can't // possibly be enough uses of the divisor to make the transform worthwhile. unsigned MinUses = TLI.combineRepeatedFPDivisors(); diff --git a/llvm/test/CodeGen/X86/repeated-fp-divisors-denorm.ll b/llvm/test/CodeGen/X86/repeated-fp-divisors-denorm.ll new file mode 100644 index 0000000000000..a6987de790e41 --- /dev/null +++ b/llvm/test/CodeGen/X86/repeated-fp-divisors-denorm.ll @@ -0,0 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=x86_64 < %s | FileCheck %s + +; Negative test: repeated FP divisor transform should bail out when the rewrite +; would introduce infinities because of subnormal constant divisors. +define void @two_denorm_fdivs(float %a0, float %a1, float %a2, ptr %res) { +; CHECK-LABEL: two_denorm_fdivs: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: movss {{.*#+}} xmm0 = [1.95915678E-39,0.0E+0,0.0E+0,0.0E+0] +; CHECK-NEXT: divss %xmm0, %xmm1 +; CHECK-NEXT: movss %xmm1, (%rdi) +; CHECK-NEXT: divss %xmm0, %xmm2 +; CHECK-NEXT: movss %xmm2, 4(%rdi) +; CHECK-NEXT: retq +entry: + %div0 = fdiv arcp float %a1, 0x37E5555500000000 + store float %div0, ptr %res + %ptr1 = getelementptr inbounds float, ptr %res, i64 1 + %div1 = fdiv arcp float %a2, 0x37E5555500000000 + store float %div1, ptr %ptr1 + ret void +}