forked from OSchip/llvm-project
[InstCombine] allow X / C -> X * (1.0/C) for vector splat FP constants
llvm-svn: 325237
This commit is contained in:
parent
b5f8ca47e7
commit
6a0f667077
|
@ -283,6 +283,11 @@ public:
|
||||||
/// for simple constant values like 2.0/1.0 etc, that are known-valid both as
|
/// for simple constant values like 2.0/1.0 etc, that are known-valid both as
|
||||||
/// host double and as the target format.
|
/// host double and as the target format.
|
||||||
static Constant *get(Type* Ty, double V);
|
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 Constant *get(Type* Ty, StringRef Str);
|
||||||
static ConstantFP *get(LLVMContext &Context, const APFloat &V);
|
static ConstantFP *get(LLVMContext &Context, const APFloat &V);
|
||||||
static Constant *getNaN(Type *Ty, bool Negative = false, unsigned type = 0);
|
static Constant *getNaN(Type *Ty, bool Negative = false, unsigned type = 0);
|
||||||
|
|
|
@ -635,6 +635,17 @@ Constant *ConstantFP::get(Type *Ty, double V) {
|
||||||
return C;
|
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) {
|
Constant *ConstantFP::get(Type *Ty, StringRef Str) {
|
||||||
LLVMContext &Context = Ty->getContext();
|
LLVMContext &Context = Ty->getContext();
|
||||||
|
|
|
@ -1319,21 +1319,19 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
|
||||||
|
|
||||||
/// Try to convert X/C into X * (1/C).
|
/// Try to convert X/C into X * (1/C).
|
||||||
static Instruction *foldFDivConstantDivisor(BinaryOperator &FDiv) {
|
static Instruction *foldFDivConstantDivisor(BinaryOperator &FDiv) {
|
||||||
// TODO: Handle vector constants.
|
// TODO: Handle non-splat vector constants.
|
||||||
ConstantFP *CFP;
|
const APFloat *C;
|
||||||
if (!match(FDiv.getOperand(1), m_ConstantFP(CFP)))
|
if (!match(FDiv.getOperand(1), m_APFloat(C)))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
const APFloat &FpVal = CFP->getValueAPF();
|
|
||||||
APFloat Reciprocal(FpVal.getSemantics());
|
|
||||||
|
|
||||||
// This returns false if the inverse would be a denormal.
|
// 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
|
// If the inverse is not exact, we may still be able to convert if we are
|
||||||
// not operating with strict math.
|
// not operating with strict math.
|
||||||
if (!HasRecip && FDiv.hasAllowReciprocal() && FpVal.isFiniteNonZero()) {
|
if (!HasRecip && FDiv.hasAllowReciprocal() && C->isFiniteNonZero()) {
|
||||||
Reciprocal = APFloat(FpVal.getSemantics(), 1.0f);
|
Reciprocal = APFloat(C->getSemantics(), 1.0f);
|
||||||
Reciprocal.divide(FpVal, APFloat::rmNearestTiesToEven);
|
Reciprocal.divide(*C, APFloat::rmNearestTiesToEven);
|
||||||
// Disallow denormal constants because we don't know what would happen
|
// Disallow denormal constants because we don't know what would happen
|
||||||
// on all targets.
|
// on all targets.
|
||||||
// TODO: Function attributes can tell us that denorms are flushed?
|
// TODO: Function attributes can tell us that denorms are flushed?
|
||||||
|
@ -1343,7 +1341,7 @@ static Instruction *foldFDivConstantDivisor(BinaryOperator &FDiv) {
|
||||||
if (!HasRecip)
|
if (!HasRecip)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto *RecipCFP = ConstantFP::get(FDiv.getContext(), Reciprocal);
|
auto *RecipCFP = ConstantFP::get(FDiv.getType(), Reciprocal);
|
||||||
return BinaryOperator::CreateFMul(FDiv.getOperand(0), RecipCFP);
|
return BinaryOperator::CreateFMul(FDiv.getOperand(0), RecipCFP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,17 +66,28 @@ define float @not_exact_but_allow_recip_but_denorm(float %x) {
|
||||||
ret float %div
|
ret float %div
|
||||||
}
|
}
|
||||||
|
|
||||||
; FIXME: Vector neglect.
|
|
||||||
|
|
||||||
define <2 x float> @exact_inverse_splat(<2 x float> %x) {
|
define <2 x float> @exact_inverse_splat(<2 x float> %x) {
|
||||||
; CHECK-LABEL: @exact_inverse_splat(
|
; 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]]
|
; CHECK-NEXT: ret <2 x float> [[DIV]]
|
||||||
;
|
;
|
||||||
%div = fdiv <2 x float> %x, <float 4.0, float 4.0>
|
%div = fdiv <2 x float> %x, <float 4.0, float 4.0>
|
||||||
ret <2 x float> %div
|
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) {
|
define <2 x float> @exact_inverse_vec(<2 x float> %x) {
|
||||||
; CHECK-LABEL: @exact_inverse_vec(
|
; CHECK-LABEL: @exact_inverse_vec(
|
||||||
; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.000000e+00, float 8.000000e+00>
|
; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.000000e+00, float 8.000000e+00>
|
||||||
|
|
Loading…
Reference in New Issue