summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/IR/Constants.h5
-rw-r--r--llvm/lib/IR/Constants.cpp11
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp20
-rw-r--r--llvm/test/Transforms/InstCombine/fdiv.ll17
4 files changed, 39 insertions, 14 deletions
diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h
index 0094fd54992..0ec082c23eb 100644
--- a/llvm/include/llvm/IR/Constants.h
+++ b/llvm/include/llvm/IR/Constants.h
@@ -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);
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index dccba779deb..a601f54a359 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -635,6 +635,17 @@ Constant *ConstantFP::get(Type *Ty, double V) {
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();
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 5457f19d7f4..57a30558a98 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1319,21 +1319,19 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
/// 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 *foldFDivConstantDivisor(BinaryOperator &FDiv) {
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);
}
diff --git a/llvm/test/Transforms/InstCombine/fdiv.ll b/llvm/test/Transforms/InstCombine/fdiv.ll
index ac9733b11c4..03e0a36b0f8 100644
--- a/llvm/test/Transforms/InstCombine/fdiv.ll
+++ b/llvm/test/Transforms/InstCombine/fdiv.ll
@@ -66,17 +66,28 @@ define float @not_exact_but_allow_recip_but_denorm(float %x) {
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>
OpenPOWER on IntegriCloud