Skip to content

Commit e078d67

Browse files
committed
Optimize constFold
1 parent 9ff3203 commit e078d67

File tree

5 files changed

+67
-61
lines changed

5 files changed

+67
-61
lines changed

compiler/src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -583,14 +583,14 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
583583
case tree: Select if qualifier.tpe eq tree.qualifier.tpe =>
584584
tree1.withTypeUnchecked(tree.tpe)
585585
case _ =>
586-
val tree2 = tree.tpe match {
586+
val tree2: Select = tree.tpe match {
587587
case tpe: NamedType =>
588588
val qualType = qualifier.tpe.widenIfUnstable
589589
if qualType.isBottomType then tree1.withTypeUnchecked(tree.tpe)
590590
else tree1.withType(tpe.derivedSelect(qualType))
591591
case _ => tree1.withTypeUnchecked(tree.tpe)
592592
}
593-
ConstFold(tree2)
593+
ConstFold.Select(tree2)
594594
}
595595
}
596596

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1248,7 +1248,7 @@ object Types {
12481248
case TypeAlias(alias) => alias.dealias1(keep)
12491249
case _ => tp
12501250
}
1251-
case app @ AppliedType(tycon, args) =>
1251+
case app @ AppliedType(tycon, _) =>
12521252
val tycon1 = tycon.dealias1(keep)
12531253
if (tycon1 ne tycon) app.superType.dealias1(keep)
12541254
else this

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1050,7 +1050,7 @@ class TreeUnpickler(reader: TastyReader,
10501050
case name: TypeName => TypeRef(qualType, name, denot)
10511051
case name: TermName => TermRef(qualType, name, denot)
10521052
}
1053-
ConstFold(untpd.Select(qual, name).withType(tpe))
1053+
ConstFold.Select(untpd.Select(qual, name).withType(tpe))
10541054

10551055
def completeSelect(name: Name, sig: Signature): Select =
10561056
val qual = readTerm()

compiler/src/dotty/tools/dotc/typer/ConstFold.scala

Lines changed: 61 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -14,56 +14,63 @@ import StdNames._
1414
import Contexts._
1515
import transform.TypeUtils._
1616

17-
object ConstFold {
17+
object ConstFold:
1818

1919
import tpd._
2020

21-
/** If tree is a constant operation, replace with result. */
22-
def apply[T <: Tree](tree: T)(using Context): T = finish(tree) {
23-
tree match {
24-
case Apply(Select(xt, op), yt :: Nil) =>
21+
private val foldedBinops = Set[Name](
22+
nme.ZOR, nme.OR, nme.XOR, nme.ZAND, nme.AND, nme.EQ, nme.NE,
23+
nme.LT, nme.GT, nme.LE, nme.GE, nme.LSL, nme.LSR, nme.ASR,
24+
nme.ADD, nme.SUB, nme.MUL, nme.DIV, nme.MOD)
25+
26+
private val foldedUnops = Set[Name](
27+
nme.UNARY_!, nme.UNARY_~, nme.UNARY_+, nme.UNARY_-)
28+
29+
def Apply[T <: Apply](tree: T)(using Context): T =
30+
tree.fun match
31+
case Select(xt, op) if foldedBinops.contains(op) =>
2532
xt.tpe.widenTermRefExpr.normalized match
2633
case ConstantType(x) =>
27-
yt.tpe.widenTermRefExpr match
28-
case ConstantType(y) => foldBinop(op, x, y)
29-
case _ => null
30-
case _ => null
31-
case Select(xt, op) =>
32-
xt.tpe.widenTermRefExpr match {
33-
case ConstantType(x) => foldUnop(op, x)
34-
case _ => null
35-
}
36-
case TypeApply(_, List(targ)) if tree.symbol eq defn.Predef_classOf =>
37-
Constant(targ.tpe)
38-
case Apply(TypeApply(Select(qual, nme.getClass_), _), Nil)
39-
if qual.tpe.widen.isPrimitiveValueType =>
40-
Constant(qual.tpe.widen)
41-
case _ => null
42-
}
43-
}
34+
tree.args match
35+
case yt :: Nil =>
36+
yt.tpe.widenTermRefExpr.normalized match
37+
case ConstantType(y) => tree.withFoldedType(foldBinop(op, x, y))
38+
case _ => tree
39+
case _ => tree
40+
case _ => tree
41+
case TypeApply(Select(qual, nme.getClass_), _)
42+
if qual.tpe.widen.isPrimitiveValueType && tree.args.isEmpty =>
43+
tree.withFoldedType(Constant(qual.tpe.widen))
44+
case _ =>
45+
tree
46+
47+
def Select[T <: Select](tree: T)(using Context): T =
48+
if foldedUnops.contains(tree.name) then
49+
tree.qualifier.tpe.widenTermRefExpr.normalized match
50+
case ConstantType(x) => tree.withFoldedType(foldUnop(tree.name, x))
51+
case _ => tree
52+
else tree
53+
54+
/** If tree is a constant operation, replace with result. */
55+
def apply[T <: Tree](tree: T)(using Context): T = tree match
56+
case tree: Apply => Apply(tree)
57+
case tree: Select => Select(tree)
58+
case TypeApply(_, targ :: Nil) if tree.symbol eq defn.Predef_classOf =>
59+
tree.withFoldedType(Constant(targ.tpe))
60+
case _ => tree
4461

4562
/** If tree is a constant value that can be converted to type `pt`, perform
4663
* the conversion.
4764
*/
4865
def apply[T <: Tree](tree: T, pt: Type)(using Context): T =
49-
finish(apply(tree)) {
50-
tree.tpe.widenTermRefExpr.normalized match {
51-
case ConstantType(x) => x convertTo pt
52-
case _ => null
53-
}
54-
}
55-
56-
inline private def finish[T <: Tree](tree: T)(compX: => Constant)(using Context): T =
57-
try {
58-
val x = compX
59-
if (x ne null) tree.withType(ConstantType(x)).asInstanceOf[T]
60-
else tree
61-
}
62-
catch {
63-
case _: ArithmeticException => tree // the code will crash at runtime,
64-
// but that is better than the
65-
// compiler itself crashing
66-
}
66+
val tree1 = apply(tree)
67+
tree.tpe.widenTermRefExpr.normalized match
68+
case ConstantType(x) => tree1.withFoldedType(x.convertTo(pt))
69+
case _ => tree1
70+
71+
extension [T <: Tree](tree: T)(using Context)
72+
private def withFoldedType(c: Constant | Null): T =
73+
if c == null then tree else tree.withType(ConstantType(c)).asInstanceOf[T]
6774

6875
private def foldUnop(op: Name, x: Constant): Constant = (op, x.tag) match {
6976
case (nme.UNARY_!, BooleanTag) => Constant(!x.booleanValue)
@@ -166,23 +173,22 @@ object ConstFold {
166173
case _ => null
167174
}
168175

169-
private def foldBinop(op: Name, x: Constant, y: Constant): Constant = {
176+
private def foldBinop(op: Name, x: Constant, y: Constant): Constant =
170177
val optag =
171178
if (x.tag == y.tag) x.tag
172179
else if (x.isNumeric && y.isNumeric) math.max(x.tag, y.tag)
173180
else NoTag
174181

175-
try optag match {
176-
case BooleanTag => foldBooleanOp(op, x, y)
177-
case ByteTag | ShortTag | CharTag | IntTag => foldSubrangeOp(op, x, y)
178-
case LongTag => foldLongOp(op, x, y)
179-
case FloatTag => foldFloatOp(op, x, y)
180-
case DoubleTag => foldDoubleOp(op, x, y)
181-
case StringTag if op == nme.ADD => Constant(x.stringValue + y.stringValue)
182-
case _ => null
183-
}
184-
catch {
185-
case ex: ArithmeticException => null
186-
}
187-
}
188-
}
182+
try optag match
183+
case BooleanTag => foldBooleanOp(op, x, y)
184+
case ByteTag | ShortTag | CharTag | IntTag => foldSubrangeOp(op, x, y)
185+
case LongTag => foldLongOp(op, x, y)
186+
case FloatTag => foldFloatOp(op, x, y)
187+
case DoubleTag => foldDoubleOp(op, x, y)
188+
case StringTag if op == nme.ADD => Constant(x.stringValue + y.stringValue)
189+
case _ => null
190+
catch case ex: ArithmeticException => null // the code will crash at runtime,
191+
// but that is better than the
192+
// compiler itself crashing
193+
end foldBinop
194+
end ConstFold

compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ trait TypeAssigner {
211211

212212
case _ => accessibleSelectionType(tree, qual)
213213
}
214-
ConstFold(tree.withType(tp))
214+
ConstFold.Select(tree.withType(tp))
215215
}
216216

217217
/** Normalize type T appearing in a new T by following eta expansions to
@@ -301,7 +301,7 @@ trait TypeAssigner {
301301
if (ctx.settings.Ydebug.value) new FatalError("").printStackTrace()
302302
errorType(err.takesNoParamsStr(fn, ""), tree.srcPos)
303303
}
304-
ConstFold(tree.withType(ownType))
304+
ConstFold.Apply(tree.withType(ownType))
305305
}
306306

307307
def assignType(tree: untpd.TypeApply, fn: Tree, args: List[Tree])(using Context): TypeApply = {

0 commit comments

Comments
 (0)