[llvm] r323716 - [InstSimplify] (X * Y) / Y --> X for relaxed floating-point ops

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 29 16:18:37 PST 2018


Author: spatel
Date: Mon Jan 29 16:18:37 2018
New Revision: 323716

URL: http://llvm.org/viewvc/llvm-project?rev=323716&view=rev
Log:
[InstSimplify] (X * Y) / Y --> X for relaxed floating-point ops

This is the FP counterpart that was mentioned in PR35709:
https://bugs.llvm.org/show_bug.cgi?id=35709

Differential Revision: https://reviews.llvm.org/D42385

Modified:
    llvm/trunk/include/llvm/IR/PatternMatch.h
    llvm/trunk/lib/Analysis/InstructionSimplify.cpp
    llvm/trunk/test/Transforms/InstSimplify/fdiv.ll

Modified: llvm/trunk/include/llvm/IR/PatternMatch.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/PatternMatch.h?rev=323716&r1=323715&r2=323716&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/PatternMatch.h (original)
+++ llvm/trunk/include/llvm/IR/PatternMatch.h Mon Jan 29 16:18:37 2018
@@ -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
 

Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=323716&r1=323715&r2=323716&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
+++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Mon Jan 29 16:18:37 2018
@@ -4298,9 +4298,15 @@ static Value *SimplifyFDivInst(Value *Op
 
   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.

Modified: llvm/trunk/test/Transforms/InstSimplify/fdiv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/fdiv.ll?rev=323716&r1=323715&r2=323716&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/fdiv.ll (original)
+++ llvm/trunk/test/Transforms/InstSimplify/fdiv.ll Mon Jan 29 16:18:37 2018
@@ -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
+}
+




More information about the llvm-commits mailing list