Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit c1de3c6

Browse files
committed
[InstCombine] fold fdiv with non-splat divisor to fmul: X/C --> X * (1/C)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@325590 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent b39c3c3 commit c1de3c6

File tree

5 files changed

+49
-25
lines changed

5 files changed

+49
-25
lines changed

include/llvm/IR/Constant.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ class Constant : public User {
7979
/// scalar constant or a vector constant with all normal elements.
8080
bool isNormalFP() const;
8181

82+
/// Return true if this scalar has an exact multiplicative inverse or this
83+
/// vector has an exact multiplicative inverse for each element in the vector.
84+
bool hasExactInverseFP() const;
85+
8286
/// Return true if evaluation of this constant could trap. This is true for
8387
/// things like constant expressions that could divide by zero.
8488
bool canTrap() const;

lib/IR/Constants.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,19 @@ bool Constant::isNormalFP() const {
228228
return true;
229229
}
230230

231+
bool Constant::hasExactInverseFP() const {
232+
if (auto *CFP = dyn_cast<ConstantFP>(this))
233+
return CFP->getValueAPF().getExactInverse(nullptr);
234+
if (!getType()->isVectorTy())
235+
return false;
236+
for (unsigned i = 0, e = getType()->getVectorNumElements(); i != e; ++i) {
237+
auto *CFP = dyn_cast_or_null<ConstantFP>(this->getAggregateElement(i));
238+
if (!CFP || !CFP->getValueAPF().getExactInverse(nullptr))
239+
return false;
240+
}
241+
return true;
242+
}
243+
231244
/// Constructor to create a '0' constant of arbitrary type.
232245
Constant *Constant::getNullValue(Type *Ty) {
233246
switch (Ty->getTypeID()) {

lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,32 +1289,27 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
12891289
}
12901290

12911291
/// Try to convert X/C into X * (1/C).
1292-
static Instruction *foldFDivConstantDivisor(BinaryOperator &FDiv) {
1293-
// TODO: Handle non-splat vector constants.
1294-
const APFloat *C;
1295-
if (!match(FDiv.getOperand(1), m_APFloat(C)))
1292+
static Instruction *foldFDivConstantDivisor(BinaryOperator &I) {
1293+
Constant *C;
1294+
if (!match(I.getOperand(1), m_Constant(C)))
12961295
return nullptr;
12971296

1298-
// This returns false if the inverse would be a denormal.
1299-
APFloat Reciprocal(C->getSemantics());
1300-
bool HasRecip = C->getExactInverse(&Reciprocal);
1301-
// If the inverse is not exact, we may still be able to convert if we are
1302-
// not operating with strict math.
1303-
if (!HasRecip && FDiv.hasAllowReciprocal() && C->isFiniteNonZero()) {
1304-
Reciprocal = APFloat(C->getSemantics(), 1.0f);
1305-
Reciprocal.divide(*C, APFloat::rmNearestTiesToEven);
1306-
// Disallow denormal constants because we don't know what would happen
1307-
// on all targets.
1308-
// TODO: Function attributes can tell us that denorms are flushed?
1309-
HasRecip = !Reciprocal.isDenormal();
1310-
}
1297+
// If the constant divisor has an exact inverse, this is always safe. If not,
1298+
// then we can still create a reciprocal if fast-math-flags allow it and the
1299+
// constant is a regular number (not zero, infinite, or denormal).
1300+
if (!(C->hasExactInverseFP() || (I.hasAllowReciprocal() && C->isNormalFP())))
1301+
return nullptr;
13111302

1312-
if (!HasRecip)
1303+
// Disallow denormal constants because we don't know what would happen
1304+
// on all targets.
1305+
// TODO: Use Intrinsic::canonicalize or let function attributes tell us that
1306+
// denorms are flushed?
1307+
auto *RecipC = ConstantExpr::getFDiv(ConstantFP::get(I.getType(), 1.0), C);
1308+
if (!RecipC->isNormalFP())
13131309
return nullptr;
13141310

1315-
auto *RecipCFP = ConstantFP::get(FDiv.getType(), Reciprocal);
1316-
return BinaryOperator::CreateWithCopiedFlags(Instruction::FMul, RecipCFP,
1317-
FDiv.getOperand(0), &FDiv);
1311+
return BinaryOperator::CreateWithCopiedFlags(
1312+
Instruction::FMul, I.getOperand(0), RecipC, &I);
13181313
}
13191314

13201315
/// Try to reassociate C / X expressions where X includes another constant.

test/Transforms/InstCombine/fast-math.ll

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ define float @fmul_distribute1(float %f1) {
229229
}
230230

231231
; (X/C1 + C2) * C3 => X/(C1/C3) + C2*C3
232+
; TODO: We don't convert the fast fdiv to fmul because that would be multiplication
233+
; by a denormal, but we could do better when we know that denormals are not a problem.
234+
232235
define double @fmul_distribute2(double %f1, double %f2) {
233236
; CHECK-LABEL: @fmul_distribute2(
234237
; CHECK-NEXT: [[TMP1:%.*]] = fdiv fast double [[F1:%.*]], 0x7FE8000000000000
@@ -345,7 +348,9 @@ define float @fmul4(float %f1, float %f2) {
345348

346349
; X / C1 * C2 => X / (C2/C1) if C1/C2 is either a special value of a denormal,
347350
; and C2/C1 is a normal value.
348-
;
351+
; TODO: We don't convert the fast fdiv to fmul because that would be multiplication
352+
; by a denormal, but we could do better when we know that denormals are not a problem.
353+
349354
define float @fmul5(float %f1, float %f2) {
350355
; CHECK-LABEL: @fmul5(
351356
; CHECK-NEXT: [[TMP1:%.*]] = fdiv fast float [[F1:%.*]], 0x47E8000000000000

test/Transforms/InstCombine/fdiv.ll

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,9 @@ define <2 x float> @not_exact_but_allow_recip_splat(<2 x float> %x) {
8686
ret <2 x float> %div
8787
}
8888

89-
; FIXME: Vector neglect.
90-
9189
define <2 x float> @exact_inverse_vec(<2 x float> %x) {
9290
; CHECK-LABEL: @exact_inverse_vec(
93-
; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.000000e+00, float 8.000000e+00>
91+
; CHECK-NEXT: [[DIV:%.*]] = fmul <2 x float> [[X:%.*]], <float 2.500000e-01, float 1.250000e-01>
9492
; CHECK-NEXT: ret <2 x float> [[DIV]]
9593
;
9694
%div = fdiv <2 x float> %x, <float 4.0, float 8.0>
@@ -115,6 +113,15 @@ define <2 x float> @not_exact_inverse_vec(<2 x float> %x) {
115113
ret <2 x float> %div
116114
}
117115

116+
define <2 x float> @not_exact_inverse_vec_arcp(<2 x float> %x) {
117+
; CHECK-LABEL: @not_exact_inverse_vec_arcp(
118+
; CHECK-NEXT: [[DIV:%.*]] = fmul arcp <2 x float> [[X:%.*]], <float 2.500000e-01, float 0x3FD5555560000000>
119+
; CHECK-NEXT: ret <2 x float> [[DIV]]
120+
;
121+
%div = fdiv arcp <2 x float> %x, <float 4.0, float 3.0>
122+
ret <2 x float> %div
123+
}
124+
118125
; (X / Y) / Z --> X / (Y * Z)
119126

120127
define float @div_with_div_numerator(float %x, float %y, float %z) {

0 commit comments

Comments
 (0)