diff options
-rw-r--r-- | llvm/include/llvm/IR/PatternMatch.h | 14 | ||||
-rw-r--r-- | llvm/lib/Analysis/InstructionSimplify.cpp | 6 | ||||
-rw-r--r-- | llvm/test/Transforms/InstSimplify/fdiv.ll | 34 |
3 files changed, 54 insertions, 0 deletions
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 245d72fbd16..794e1e456c8 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -1555,6 +1555,20 @@ m_c_UMax(const LHS &L, const RHS &R) { return MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty, true>(L, R); } +/// Matches FAdd with LHS and RHS in either order. +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::FAdd, true> +m_c_FAdd(const LHS &L, const RHS &R) { + return BinaryOp_match<LHS, RHS, Instruction::FAdd, true>(L, R); +} + +/// Matches FMul with LHS and RHS in either order. +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::FMul, true> +m_c_FMul(const LHS &L, const RHS &R) { + return BinaryOp_match<LHS, RHS, Instruction::FMul, true>(L, R); +} + } // end namespace PatternMatch } // end namespace llvm diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index a258c4df898..b81ecc83c05 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -4298,9 +4298,15 @@ static Value *SimplifyFDivInst(Value *Op0, Value *Op1, FastMathFlags FMF, if (FMF.noNaNs()) { // X / X -> 1.0 is legal when NaNs are ignored. + // We can ignore infinities because INF/INF is NaN. if (Op0 == Op1) return ConstantFP::get(Op0->getType(), 1.0); + // (X * Y) / Y --> X if we can reassociate to the above form. + Value *X; + if (FMF.allowReassoc() && match(Op0, m_c_FMul(m_Value(X), m_Specific(Op1)))) + return X; + // -X / X -> -1.0 and // X / -X -> -1.0 are legal when NaNs are ignored. // We can ignore signed zeros because +-0.0/+-0.0 is NaN and ignored. diff --git a/llvm/test/Transforms/InstSimplify/fdiv.ll b/llvm/test/Transforms/InstSimplify/fdiv.ll index 6643afd8147..cc883cbbaf1 100644 --- a/llvm/test/Transforms/InstSimplify/fdiv.ll +++ b/llvm/test/Transforms/InstSimplify/fdiv.ll @@ -34,3 +34,37 @@ define double @fdiv_by_undef(double %X) { %r = fdiv double %X, undef ret double %r } + +define double @fmul_fdiv_common_operand(double %x, double %y) { +; CHECK-LABEL: @fmul_fdiv_common_operand( +; CHECK-NEXT: ret double %x +; + %m = fmul double %x, %y + %d = fdiv reassoc nnan double %m, %y + ret double %d +} + +; Negative test - the fdiv must be reassociative and not allow NaNs. + +define double @fmul_fdiv_common_operand_too_strict(double %x, double %y) { +; CHECK-LABEL: @fmul_fdiv_common_operand_too_strict( +; CHECK-NEXT: [[M:%.*]] = fmul fast double %x, %y +; CHECK-NEXT: [[D:%.*]] = fdiv reassoc double [[M]], %y +; CHECK-NEXT: ret double [[D]] +; + %m = fmul fast double %x, %y + %d = fdiv reassoc double %m, %y + ret double %d +} + +; Commute the fmul operands. Use a vector type to verify that works too. + +define <2 x float> @fmul_fdiv_common_operand_commute_vec(<2 x float> %x, <2 x float> %y) { +; CHECK-LABEL: @fmul_fdiv_common_operand_commute_vec( +; CHECK-NEXT: ret <2 x float> %x +; + %m = fmul <2 x float> %y, %x + %d = fdiv fast <2 x float> %m, %y + ret <2 x float> %d +} + |