[llvm] r325237 - [InstCombine] allow X / C -> X * (1.0/C) for vector splat FP constants

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 15 05:55:53 PST 2018


Author: spatel
Date: Thu Feb 15 05:55:52 2018
New Revision: 325237

URL: http://llvm.org/viewvc/llvm-project?rev=325237&view=rev
Log:
[InstCombine] allow X / C -> X * (1.0/C) for vector splat FP constants

Modified:
    llvm/trunk/include/llvm/IR/Constants.h
    llvm/trunk/lib/IR/Constants.cpp
    llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
    llvm/trunk/test/Transforms/InstCombine/fdiv.ll

Modified: llvm/trunk/include/llvm/IR/Constants.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Constants.h?rev=325237&r1=325236&r2=325237&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Constants.h (original)
+++ llvm/trunk/include/llvm/IR/Constants.h Thu Feb 15 05:55:52 2018
@@ -283,6 +283,11 @@ public:
   /// for simple constant values like 2.0/1.0 etc, that are known-valid both as
   /// host double and as the target format.
   static Constant *get(Type* Ty, double V);
+
+  /// If Ty is a vector type, return a Constant with a splat of the given
+  /// value. Otherwise return a ConstantFP for the given value.
+  static Constant *get(Type *Ty, const APFloat &V);
+
   static Constant *get(Type* Ty, StringRef Str);
   static ConstantFP *get(LLVMContext &Context, const APFloat &V);
   static Constant *getNaN(Type *Ty, bool Negative = false, unsigned type = 0);

Modified: llvm/trunk/lib/IR/Constants.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Constants.cpp?rev=325237&r1=325236&r2=325237&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Constants.cpp (original)
+++ llvm/trunk/lib/IR/Constants.cpp Thu Feb 15 05:55:52 2018
@@ -635,6 +635,17 @@ Constant *ConstantFP::get(Type *Ty, doub
   return C;
 }
 
+Constant *ConstantFP::get(Type *Ty, const APFloat &V) {
+  ConstantFP *C = get(Ty->getContext(), V);
+  assert(C->getType() == Ty->getScalarType() &&
+         "ConstantFP type doesn't match the type implied by its value!");
+
+  // For vectors, broadcast the value.
+  if (auto *VTy = dyn_cast<VectorType>(Ty))
+    return ConstantVector::getSplat(VTy->getNumElements(), C);
+
+  return C;
+}
 
 Constant *ConstantFP::get(Type *Ty, StringRef Str) {
   LLVMContext &Context = Ty->getContext();

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp?rev=325237&r1=325236&r2=325237&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp Thu Feb 15 05:55:52 2018
@@ -1319,21 +1319,19 @@ Instruction *InstCombiner::visitSDiv(Bin
 
 /// Try to convert X/C into X * (1/C).
 static Instruction *foldFDivConstantDivisor(BinaryOperator &FDiv) {
-  // TODO: Handle vector constants.
-  ConstantFP *CFP;
-  if (!match(FDiv.getOperand(1), m_ConstantFP(CFP)))
+  // TODO: Handle non-splat vector constants.
+  const APFloat *C;
+  if (!match(FDiv.getOperand(1), m_APFloat(C)))
     return nullptr;
 
-  const APFloat &FpVal = CFP->getValueAPF();
-  APFloat Reciprocal(FpVal.getSemantics());
-
   // This returns false if the inverse would be a denormal.
-  bool HasRecip = FpVal.getExactInverse(&Reciprocal);
+  APFloat Reciprocal(C->getSemantics());
+  bool HasRecip = C->getExactInverse(&Reciprocal);
   // If the inverse is not exact, we may still be able to convert if we are
   // not operating with strict math.
-  if (!HasRecip && FDiv.hasAllowReciprocal() && FpVal.isFiniteNonZero()) {
-    Reciprocal = APFloat(FpVal.getSemantics(), 1.0f);
-    Reciprocal.divide(FpVal, APFloat::rmNearestTiesToEven);
+  if (!HasRecip && FDiv.hasAllowReciprocal() && C->isFiniteNonZero()) {
+    Reciprocal = APFloat(C->getSemantics(), 1.0f);
+    Reciprocal.divide(*C, APFloat::rmNearestTiesToEven);
     // Disallow denormal constants because we don't know what would happen
     // on all targets.
     // TODO: Function attributes can tell us that denorms are flushed?
@@ -1343,7 +1341,7 @@ static Instruction *foldFDivConstantDivi
   if (!HasRecip)
     return nullptr;
 
-  auto *RecipCFP = ConstantFP::get(FDiv.getContext(), Reciprocal);
+  auto *RecipCFP = ConstantFP::get(FDiv.getType(), Reciprocal);
   return BinaryOperator::CreateFMul(FDiv.getOperand(0), RecipCFP);
 }
 

Modified: llvm/trunk/test/Transforms/InstCombine/fdiv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/fdiv.ll?rev=325237&r1=325236&r2=325237&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/fdiv.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/fdiv.ll Thu Feb 15 05:55:52 2018
@@ -66,17 +66,28 @@ define float @not_exact_but_allow_recip_
   ret float %div
 }
 
-; FIXME: Vector neglect.
-
 define <2 x float> @exact_inverse_splat(<2 x float> %x) {
 ; CHECK-LABEL: @exact_inverse_splat(
-; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.000000e+00, float 4.000000e+00>
+; CHECK-NEXT:    [[DIV:%.*]] = fmul <2 x float> [[X:%.*]], <float 2.500000e-01, float 2.500000e-01>
 ; CHECK-NEXT:    ret <2 x float> [[DIV]]
 ;
   %div = fdiv <2 x float> %x, <float 4.0, float 4.0>
   ret <2 x float> %div
 }
 
+; Fast math allows us to replace this fdiv.
+
+define <2 x float> @not_exact_but_allow_recip_splat(<2 x float> %x) {
+; CHECK-LABEL: @not_exact_but_allow_recip_splat(
+; CHECK-NEXT:    [[DIV:%.*]] = fmul arcp <2 x float> [[X:%.*]], <float 0x3FD5555560000000, float 0x3FD5555560000000>
+; CHECK-NEXT:    ret <2 x float> [[DIV]]
+;
+  %div = fdiv arcp <2 x float> %x, <float 3.0, float 3.0>
+  ret <2 x float> %div
+}
+
+; FIXME: Vector neglect.
+
 define <2 x float> @exact_inverse_vec(<2 x float> %x) {
 ; CHECK-LABEL: @exact_inverse_vec(
 ; CHECK-NEXT:    [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.000000e+00, float 8.000000e+00>




More information about the llvm-commits mailing list