Skip to content

Commit

Permalink
Merge pull request #7355 from somzzz/vrp_quick_math
Browse files Browse the repository at this point in the history
Refactor VRP + fix issue 15289
  • Loading branch information
andralex committed Dec 12, 2017
2 parents 79ecfc2 + d8873ee commit ddd07f6
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 169 deletions.
90 changes: 12 additions & 78 deletions src/ddmd/dcast.d
Expand Up @@ -3518,95 +3518,44 @@ extern (C++) IntRange getIntRange(Expression e)
{
IntRange ir1 = getIntRange(e.e1);
IntRange ir2 = getIntRange(e.e2);
range = IntRange(ir1.imin + ir2.imin, ir1.imax + ir2.imax)._cast(e.type);
range = (ir1 + ir2)._cast(e.type);
}

override void visit(MinExp e)
{
IntRange ir1 = getIntRange(e.e1);
IntRange ir2 = getIntRange(e.e2);
range = IntRange(ir1.imin - ir2.imax, ir1.imax - ir2.imin)._cast(e.type);
range = (ir1 - ir2)._cast(e.type);
}

override void visit(DivExp e)
{
IntRange ir1 = getIntRange(e.e1);
IntRange ir2 = getIntRange(e.e2);

// Should we ignore the possibility of div-by-0???
if (ir2.containsZero())
{
visit(cast(Expression)e);
return;
}

// [a,b] / [c,d] = [min (a/c, a/d, b/c, b/d), max (a/c, a/d, b/c, b/d)]
SignExtendedNumber[4] bdy;
bdy[0] = ir1.imin / ir2.imin;
bdy[1] = ir1.imin / ir2.imax;
bdy[2] = ir1.imax / ir2.imin;
bdy[3] = ir1.imax / ir2.imax;
range = IntRange.fromNumbers4(bdy.ptr)._cast(e.type);
range = (ir1 / ir2)._cast(e.type);
}

override void visit(MulExp e)
{
IntRange ir1 = getIntRange(e.e1);
IntRange ir2 = getIntRange(e.e2);

// [a,b] * [c,d] = [min (ac, ad, bc, bd), max (ac, ad, bc, bd)]
SignExtendedNumber[4] bdy;
bdy[0] = ir1.imin * ir2.imin;
bdy[1] = ir1.imin * ir2.imax;
bdy[2] = ir1.imax * ir2.imin;
bdy[3] = ir1.imax * ir2.imax;
range = IntRange.fromNumbers4(bdy.ptr)._cast(e.type);
range = (ir1 * ir2)._cast(e.type);
}

override void visit(ModExp e)
{
IntRange irNum = getIntRange(e.e1);
IntRange irDen = getIntRange(e.e2).absNeg();

/*
due to the rules of D (C)'s % operator, we need to consider the cases
separately in different range of signs.
case 1. [500, 1700] % [7, 23] (numerator is always positive)
= [0, 22]
case 2. [-500, 1700] % [7, 23] (numerator can be negative)
= [-22, 22]
case 3. [-1700, -500] % [7, 23] (numerator is always negative)
= [-22, 0]
the number 22 is the maximum absolute value in the denomator's range. We
don't care about divide by zero.
*/
IntRange ir1 = getIntRange(e.e1);
IntRange ir2 = getIntRange(e.e2);

// Modding on 0 is invalid anyway.
if (!irDen.imin.negative)
if (!ir2.absNeg().imin.negative)
{
visit(cast(Expression)e);
return;
}

irDen.imin = irDen.imin + SignExtendedNumber(1);
irDen.imax = -irDen.imin;

if (!irNum.imin.negative)
irNum.imin.value = 0;
else if (irNum.imin < irDen.imin)
irNum.imin = irDen.imin;

if (irNum.imax.negative)
{
irNum.imax.negative = false;
irNum.imax.value = 0;
}
else if (irNum.imax > irDen.imax)
irNum.imax = irDen.imax;

range = irNum._cast(e.type);
range = (ir1 % ir2)._cast(e.type);
}

override void visit(AndExp e)
Expand Down Expand Up @@ -3644,38 +3593,23 @@ extern (C++) IntRange getIntRange(Expression e)
IntRange ir1 = getIntRange(e.e1);
IntRange ir2 = getIntRange(e.e2);

if (ir2.imin.negative)
ir2 = IntRange(SignExtendedNumber(0), SignExtendedNumber(64));

SignExtendedNumber lower = ir1.imin << (ir1.imin.negative ? ir2.imax : ir2.imin);
SignExtendedNumber upper = ir1.imax << (ir1.imax.negative ? ir2.imin : ir2.imax);

range = IntRange(lower, upper)._cast(e.type);
range = (ir1 << ir2)._cast(e.type);
}

override void visit(ShrExp e)
{
IntRange ir1 = getIntRange(e.e1);
IntRange ir2 = getIntRange(e.e2);

if (ir2.imin.negative)
ir2 = IntRange(SignExtendedNumber(0), SignExtendedNumber(64));

SignExtendedNumber lower = ir1.imin >> (ir1.imin.negative ? ir2.imin : ir2.imax);
SignExtendedNumber upper = ir1.imax >> (ir1.imax.negative ? ir2.imax : ir2.imin);

range = IntRange(lower, upper)._cast(e.type);
range = (ir1 >> ir2)._cast(e.type);
}

override void visit(UshrExp e)
{
IntRange ir1 = getIntRange(e.e1).castUnsigned(e.e1.type);
IntRange ir2 = getIntRange(e.e2);

if (ir2.imin.negative)
ir2 = IntRange(SignExtendedNumber(0), SignExtendedNumber(64));

range = IntRange(ir1.imin >> ir2.imax, ir1.imax >> ir2.imin)._cast(e.type);
range = (ir1 >>> ir2)._cast(e.type);
}

override void visit(AssignExp e)
Expand Down Expand Up @@ -3717,7 +3651,7 @@ extern (C++) IntRange getIntRange(Expression e)
override void visit(NegExp e)
{
IntRange ir = getIntRange(e.e1);
range = IntRange(-ir.imax, -ir.imin)._cast(e.type);
range = (-ir)._cast(e.type);
}
}

Expand Down

0 comments on commit ddd07f6

Please sign in to comment.