diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp index d934638c15e75..4962fae61c471 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -2002,6 +2002,16 @@ Instruction *InstCombinerImpl::visitFAdd(BinaryOperator &I) { if (Instruction *FoldedFAdd = foldBinOpIntoSelectOrPhi(I)) return FoldedFAdd; + // B = fadd A, 0.0 + // Z = Op B + // can be transformed into + // Z = Op A + // Where Op is such that we can ignore sign of 0 in fadd + Value *A; + if (match(&I, m_OneUse(m_FAdd(m_Value(A), m_AnyZeroFP()))) && + canIgnoreSignBitOfZero(*I.use_begin())) + return replaceInstUsesWith(I, A); + // (-X) + Y --> Y - X Value *X, *Y; if (match(&I, m_c_FAdd(m_FNeg(m_Value(X)), m_Value(Y)))) @@ -3115,6 +3125,16 @@ Instruction *InstCombinerImpl::visitFSub(BinaryOperator &I) { Value *X, *Y; Constant *C; + // B = fsub A, 0.0 + // Z = Op B + // can be transformed into + // Z = Op A + // Where Op is such that we can ignore sign of 0 in fsub + Value *A; + if (match(&I, m_OneUse(m_FSub(m_Value(A), m_AnyZeroFP()))) && + canIgnoreSignBitOfZero(*I.use_begin())) + return replaceInstUsesWith(I, A); + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); // If Op0 is not -0.0 or we can ignore -0.0: Z - (X - Y) --> Z + (Y - X) // Canonicalize to fadd to make analysis easier. diff --git a/llvm/test/Transforms/InstCombine/fold-fadd-with-zero-gh154238.ll b/llvm/test/Transforms/InstCombine/fold-fadd-with-zero-gh154238.ll new file mode 100644 index 0000000000000..b9d951dc2945a --- /dev/null +++ b/llvm/test/Transforms/InstCombine/fold-fadd-with-zero-gh154238.ll @@ -0,0 +1,37 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt < %s -passes=instcombine -S | FileCheck %s +define float @src(float %arg1) { +; CHECK-LABEL: define float @src( +; CHECK-SAME: float [[ARG1:%.*]]) { +; CHECK-NEXT: [[V3:%.*]] = call float @llvm.fabs.f32(float [[ARG1]]) +; CHECK-NEXT: ret float [[V3]] +; + %v2 = fadd float %arg1, 0.000000e+00 + %v3 = call float @llvm.fabs.f32(float %v2) + ret float %v3 +} + +define float @src2(float %arg1) { +; CHECK-LABEL: define float @src2( +; CHECK-SAME: float [[ARG1:%.*]]) { +; CHECK-NEXT: [[V2:%.*]] = fadd float [[ARG1]], 0.000000e+00 +; CHECK-NEXT: [[V3:%.*]] = call float @llvm.fabs.f32(float [[V2]]) +; CHECK-NEXT: [[V4:%.*]] = fsub float [[V2]], [[V3]] +; CHECK-NEXT: ret float [[V4]] +; + %v2 = fadd float %arg1, 0.000000e+00 + %v3 = call float @llvm.fabs.f32(float %v2) + %v4 = fsub float %v2, %v3 + ret float %v4 +} + +define float @src_sub(float %arg1) { +; CHECK-LABEL: define float @src_sub( +; CHECK-SAME: float [[ARG1:%.*]]) { +; CHECK-NEXT: [[V3:%.*]] = call float @llvm.fabs.f32(float [[ARG1]]) +; CHECK-NEXT: ret float [[V3]] +; + %v2 = fsub float %arg1, 0.000000e+00 + %v3 = call float @llvm.fabs.f32(float %v2) + ret float %v3 +}