From e661185fb3e5a94177404e474d6000f386594090 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sun, 16 Oct 2022 22:49:30 -0700 Subject: [PATCH] InstCombine: Fold fdiv nnan x, 0 -> copysign(inf, x) https://alive2.llvm.org/ce/z/gLBFKB --- llvm/lib/Transforms/InstCombine/InstCombineInternal.h | 1 + llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 13 ++++++++++++- llvm/test/Transforms/InstCombine/fdiv.ll | 8 ++++---- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h index 11aed77..cc1dedf 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h +++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h @@ -370,6 +370,7 @@ private: Instruction *foldExtractOfOverflowIntrinsic(ExtractValueInst &EV); Instruction *foldIntrinsicWithOverflowCommon(IntrinsicInst *II); Instruction *foldFPSignBitOps(BinaryOperator &I); + Instruction *foldFDivConstantDivisor(BinaryOperator &I); // Optimize one of these forms: // and i1 Op, SI / select i1 Op, i1 SI, i1 false (if IsAnd = true) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index abc88e3..9627530 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -1403,7 +1403,7 @@ Instruction *InstCombinerImpl::visitSDiv(BinaryOperator &I) { } /// Remove negation and try to convert division into multiplication. -static Instruction *foldFDivConstantDivisor(BinaryOperator &I) { +Instruction *InstCombinerImpl::foldFDivConstantDivisor(BinaryOperator &I) { Constant *C; if (!match(I.getOperand(1), m_Constant(C))) return nullptr; @@ -1415,6 +1415,17 @@ static Instruction *foldFDivConstantDivisor(BinaryOperator &I) { if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL)) return BinaryOperator::CreateFDivFMF(X, NegC, &I); + // nnan X / +0.0 -> copysign(inf, X) + if (I.hasNoNaNs() && match(I.getOperand(1), m_Zero())) { + IRBuilder<> B(&I); + // TODO: nnan nsz X / -0.0 -> copysign(inf, X) + CallInst *CopySign = B.CreateIntrinsic( + Intrinsic::copysign, {C->getType()}, + {ConstantFP::getInfinity(I.getType()), I.getOperand(0)}, &I); + CopySign->takeName(&I); + return replaceInstUsesWith(I, CopySign); + } + // If the constant divisor has an exact inverse, this is always safe. If not, // then we can still create a reciprocal if fast-math-flags allow it and the // constant is a regular number (not zero, infinite, or denormal). diff --git a/llvm/test/Transforms/InstCombine/fdiv.ll b/llvm/test/Transforms/InstCombine/fdiv.ll index 38557c3..dd49f8b 100644 --- a/llvm/test/Transforms/InstCombine/fdiv.ll +++ b/llvm/test/Transforms/InstCombine/fdiv.ll @@ -950,7 +950,7 @@ define float @fdiv_zero_f32(float %x) { ; https://alive2.llvm.org/ce/z/gLBFKB define float @fdiv_nnan_zero_f32(float %x) { ; CHECK-LABEL: @fdiv_nnan_zero_f32( -; CHECK-NEXT: [[FDIV:%.*]] = fdiv nnan float [[X:%.*]], 0.000000e+00 +; CHECK-NEXT: [[FDIV:%.*]] = call nnan float @llvm.copysign.f32(float 0x7FF0000000000000, float [[X:%.*]]) ; CHECK-NEXT: ret float [[FDIV]] ; %fdiv = fdiv nnan float %x, 0.0 @@ -959,7 +959,7 @@ define float @fdiv_nnan_zero_f32(float %x) { define <2 x float> @fdiv_nnan_zero_v2f32(<2 x float> %x) { ; CHECK-LABEL: @fdiv_nnan_zero_v2f32( -; CHECK-NEXT: [[FDIV:%.*]] = fdiv nnan <2 x float> [[X:%.*]], zeroinitializer +; CHECK-NEXT: [[FDIV:%.*]] = call nnan <2 x float> @llvm.copysign.v2f32(<2 x float> , <2 x float> [[X:%.*]]) ; CHECK-NEXT: ret <2 x float> [[FDIV]] ; %fdiv = fdiv nnan <2 x float> %x, zeroinitializer @@ -968,7 +968,7 @@ define <2 x float> @fdiv_nnan_zero_v2f32(<2 x float> %x) { define float @fdiv_nnan_zero_f32_fmf(float %x) { ; CHECK-LABEL: @fdiv_nnan_zero_f32_fmf( -; CHECK-NEXT: [[FDIV:%.*]] = fdiv nnan nsz float [[X:%.*]], 0.000000e+00 +; CHECK-NEXT: [[FDIV:%.*]] = call nnan nsz float @llvm.copysign.f32(float 0x7FF0000000000000, float [[X:%.*]]) ; CHECK-NEXT: ret float [[FDIV]] ; %fdiv = fdiv nnan nsz float %x, 0.0 @@ -977,7 +977,7 @@ define float @fdiv_nnan_zero_f32_fmf(float %x) { define <2 x float> @fdiv_nnan_zero_v2f32_fmf(<2 x float> %x) { ; CHECK-LABEL: @fdiv_nnan_zero_v2f32_fmf( -; CHECK-NEXT: [[FDIV:%.*]] = fdiv nnan nsz <2 x float> [[X:%.*]], zeroinitializer +; CHECK-NEXT: [[FDIV:%.*]] = call nnan nsz <2 x float> @llvm.copysign.v2f32(<2 x float> , <2 x float> [[X:%.*]]) ; CHECK-NEXT: ret <2 x float> [[FDIV]] ; %fdiv = fdiv nnan nsz <2 x float> %x, zeroinitializer -- 2.7.4