mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[InstCombine] Without infinites, fold (C / X) < 0.0 --> (X < 0)
When C is not zero and infinites are not allowed (C / X) > 0 is a sign test. Depending on the sign of C, the predicate must be swapped. E.g.: foo(double X) { if ((-2.0 / X) <= 0) ... } => foo(double X) { if (X >= 0) ... } Patch by: @marels (Martin Elshuber) Differential Revision: https://reviews.llvm.org/D51942 llvm-svn: 343228
This commit is contained in:
parent
ccbe566797
commit
f1c984ec4b
@ -5229,6 +5229,57 @@ Instruction *InstCombiner::foldFCmpIntToFPConst(FCmpInst &I, Instruction *LHSI,
|
||||
return new ICmpInst(Pred, LHSI->getOperand(0), RHSInt);
|
||||
}
|
||||
|
||||
/// Fold (C / X) < 0.0 --> X < 0.0 if possible. Swap predicate if necessary.
|
||||
static Instruction *foldFCmpReciprocalAndZero(FCmpInst &I, Instruction *LHSI,
|
||||
Constant *RHSC) {
|
||||
// When C is not 0.0 and infinities are not allowed:
|
||||
// (C / X) < 0.0 is a sign-bit test of X
|
||||
// (C / X) < 0.0 --> X < 0.0 (if C is positive)
|
||||
// (C / X) < 0.0 --> X > 0.0 (if C is negative, swap the predicate)
|
||||
//
|
||||
// Proof:
|
||||
// Multiply (C / X) < 0.0 by X * X / C.
|
||||
// - X is non zero, if it is the flag 'ninf' is violated.
|
||||
// - C defines the sign of X * X * C. Thus it also defines whether to swap
|
||||
// the predicate. C is also non zero by definition.
|
||||
//
|
||||
// Thus X * X / C is non zero and the transformation is valid. [qed]
|
||||
|
||||
FCmpInst::Predicate Pred = I.getPredicate();
|
||||
|
||||
// Check that predicates are valid.
|
||||
if ((Pred != FCmpInst::FCMP_OGT) && (Pred != FCmpInst::FCMP_OLT) &&
|
||||
(Pred != FCmpInst::FCMP_OGE) && (Pred != FCmpInst::FCMP_OLE))
|
||||
return nullptr;
|
||||
|
||||
// Check that RHS operand is zero.
|
||||
if (!match(RHSC, m_AnyZeroFP()))
|
||||
return nullptr;
|
||||
|
||||
// Check fastmath flags ('ninf').
|
||||
if (!LHSI->hasNoInfs() || !I.hasNoInfs())
|
||||
return nullptr;
|
||||
|
||||
// Check the properties of the dividend. It must not be zero to avoid a
|
||||
// division by zero (see Proof).
|
||||
const APFloat *C;
|
||||
if (!match(LHSI->getOperand(0), m_APFloat(C)))
|
||||
return nullptr;
|
||||
|
||||
if (C->isZero())
|
||||
return nullptr;
|
||||
|
||||
// Get swapped predicate if necessary.
|
||||
if (C->isNegative())
|
||||
Pred = I.getSwappedPredicate();
|
||||
|
||||
// Finally emit the new fcmp.
|
||||
Value *X = LHSI->getOperand(1);
|
||||
FCmpInst *NewFCI = new FCmpInst(Pred, X, RHSC);
|
||||
NewFCI->setFastMathFlags(I.getFastMathFlags());
|
||||
return NewFCI;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) {
|
||||
bool Changed = false;
|
||||
|
||||
@ -5363,6 +5414,10 @@ Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) {
|
||||
ConstantExpr::getFNeg(RHSC));
|
||||
break;
|
||||
}
|
||||
case Instruction::FDiv:
|
||||
if (Instruction *NV = foldFCmpReciprocalAndZero(I, LHSI, RHSC))
|
||||
return NV;
|
||||
break;
|
||||
case Instruction::Load:
|
||||
if (GetElementPtrInst *GEP =
|
||||
dyn_cast<GetElementPtrInst>(LHSI->getOperand(0))) {
|
||||
|
@ -380,8 +380,7 @@ define i1 @test19_undef_ordered() {
|
||||
; Can fold 1.0 / X < 0.0 --> X < 0 with ninf
|
||||
define i1 @test20_recipX_olt_0(float %X) {
|
||||
; CHECK-LABEL: @test20_recipX_olt_0(
|
||||
; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf float 1.000000e+00, [[X:%.*]]
|
||||
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf olt float [[DIV]], 0.000000e+00
|
||||
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf olt float [[X:%.*]], 0.000000e+00
|
||||
; CHECK-NEXT: ret i1 [[CMP]]
|
||||
;
|
||||
%div = fdiv ninf float 1.0, %X
|
||||
@ -392,8 +391,7 @@ define i1 @test20_recipX_olt_0(float %X) {
|
||||
; Can fold -2.0 / X <= 0.0 --> X >= 0 with ninf
|
||||
define i1 @test21_recipX_ole_0(float %X) {
|
||||
; CHECK-LABEL: @test21_recipX_ole_0(
|
||||
; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf float -2.000000e+00, [[X:%.*]]
|
||||
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ole float [[DIV]], 0.000000e+00
|
||||
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf oge float [[X:%.*]], 0.000000e+00
|
||||
; CHECK-NEXT: ret i1 [[CMP]]
|
||||
;
|
||||
%div = fdiv ninf float -2.0, %X
|
||||
@ -404,8 +402,7 @@ define i1 @test21_recipX_ole_0(float %X) {
|
||||
; Can fold 2.0 / X > 0.0 --> X > 0 with ninf
|
||||
define i1 @test22_recipX_ogt_0(float %X) {
|
||||
; CHECK-LABEL: @test22_recipX_ogt_0(
|
||||
; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf float 2.000000e+00, [[X:%.*]]
|
||||
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt float [[DIV]], 0.000000e+00
|
||||
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt float [[X:%.*]], 0.000000e+00
|
||||
; CHECK-NEXT: ret i1 [[CMP]]
|
||||
;
|
||||
%div = fdiv ninf float 2.0, %X
|
||||
@ -416,8 +413,7 @@ define i1 @test22_recipX_ogt_0(float %X) {
|
||||
; Can fold -1.0 / X >= 0.0 --> X <= 0 with ninf
|
||||
define i1 @test23_recipX_oge_0(float %X) {
|
||||
; CHECK-LABEL: @test23_recipX_oge_0(
|
||||
; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf float -1.000000e+00, [[X:%.*]]
|
||||
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf oge float [[DIV]], 0.000000e+00
|
||||
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ole float [[X:%.*]], 0.000000e+00
|
||||
; CHECK-NEXT: ret i1 [[CMP]]
|
||||
;
|
||||
%div = fdiv ninf float -1.0, %X
|
||||
@ -464,8 +460,7 @@ define i1 @test26_recipX_unorderd(float %X) {
|
||||
; Fold <-1.0, -1.0> / X > <-0.0, -0.0>
|
||||
define <2 x i1> @test27_recipX_gt_vecsplat(<2 x float> %X) {
|
||||
; CHECK-LABEL: @test27_recipX_gt_vecsplat(
|
||||
; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf <2 x float> <float -1.000000e+00, float -1.000000e+00>, [[X:%.*]]
|
||||
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt <2 x float> [[DIV]], <float -0.000000e+00, float -0.000000e+00>
|
||||
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf olt <2 x float> [[X:%.*]], <float -0.000000e+00, float -0.000000e+00>
|
||||
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
||||
;
|
||||
%div = fdiv ninf <2 x float> <float -1.0, float -1.0>, %X
|
||||
|
Loading…
x
Reference in New Issue
Block a user