Skip to content

Commit dea8fb2

Browse files
author
gan74
committed
Merge remote-tracking branch 'origin/const-fold' into wip-local-opt
1 parent 03d660a commit dea8fb2

File tree

2 files changed

+66
-34
lines changed

2 files changed

+66
-34
lines changed

compiler/src/dotty/tools/dotc/transform/localopt/ConstantFold.scala

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,19 @@ import Simplify.desugarIdent
2121
* out (nested) if with equivalent branches wrt to isSimilar. For example:
2222
* - if (b) exp else exp → b; exp
2323
* - if (b1) e1 else if (b2) e1 else e2 → if (b1 || b2) e1 else e2
24+
* - if(!b) e1 else e2 → if(b) e2 else e1
2425
*
2526
* - Constant propagation over pattern matching.
2627
*
27-
* @author DarkDimius, OlivierBlanvillain
28+
* @author DarkDimius, OlivierBlanvillain, gan74
2829
*/
2930
class ConstantFold(val simplifyPhase: Simplify) extends Optimisation {
3031
import ast.tpd._
3132

3233
def visitor(implicit ctx: Context) = NoVisitor
3334
def clear(): Unit = ()
3435

35-
def transformer(implicit ctx: Context): Tree => Tree = { x => preEval(x) match {
36+
def transformer(implicit ctx: Context): Tree => Tree = { x => x match {
3637
// TODO: include handling of isInstanceOf similar to one in IsInstanceOfEvaluator
3738
// TODO: include methods such as Int.int2double(see ./tests/pos/harmonize.scala)
3839
case If(cond1, thenp, elsep) if isSimilar(thenp, elsep) =>
@@ -76,9 +77,6 @@ import Simplify.desugarIdent
7677
// cond.select(defn.Boolean_&&).appliedTo(elsep)
7778
// the other case ins't handled intentionally. See previous case for explanation
7879

79-
case If(t @ Select(recv, _), thenp, elsep) if t.symbol eq defn.Boolean_! =>
80-
If(recv, elsep, thenp)
81-
8280
case If(t @ Apply(Select(recv, _), Nil), thenp, elsep) if t.symbol eq defn.Boolean_! =>
8381
If(recv, elsep, thenp)
8482

@@ -141,7 +139,16 @@ import Simplify.desugarIdent
141139
// Block(List(lhs),
142140
// ref(defn.throwMethod).appliedTo(New(defn.ArithmeticExceptionClass.typeRef, defn.ArithmeticExceptionClass_stringConstructor, Literal(Constant("/ by zero")) :: Nil)))
143141

144-
case _ => t
142+
case _ =>
143+
val lhType = lhs.tpe.widenTermRefExpr
144+
val rhType = rhs.tpe.widenTermRefExpr
145+
(lhType, rhType) match {
146+
case (ConstantType(_), ConstantType(_)) =>
147+
val s = ConstFold.apply(t)
148+
if ((s ne null) && s.tpe.isInstanceOf[ConstantType]) Literal(s.tpe.asInstanceOf[ConstantType].value)
149+
else t
150+
case _ => t
151+
}
145152
}
146153

147154
// This case can only be triggered when running Simplify before pattern matching:
@@ -157,26 +164,11 @@ import Simplify.desugarIdent
157164

158165
case t: Literal => t
159166
case t: CaseDef => t
160-
case t if !isPureExpr(t) => t
161-
case t =>
162-
val s = ConstFold.apply(t)
163-
if ((s ne null) && s.tpe.isInstanceOf[ConstantType]) {
164-
val constant = s.tpe.asInstanceOf[ConstantType].value
165-
Literal(constant)
166-
} else t
167+
case t => t
167168
}
168169
}
169170

170-
def preEval(t: Tree)(implicit ctx: Context) = {
171-
if (t.isInstanceOf[Literal] || t.isInstanceOf[CaseDef] || !isPureExpr(t)) t
172-
else {
173-
val s = ConstFold.apply(t)
174-
if ((s ne null) && s.tpe.isInstanceOf[ConstantType]) {
175-
val constant = s.tpe.asInstanceOf[ConstantType].value
176-
Literal(constant)
177-
} else t
178-
}
179-
}
171+
180172

181173
def isSimilar(t1: Tree, t2: Tree)(implicit ctx: Context): Boolean = t1 match {
182174
case t1: Apply =>

compiler/test/dotty/tools/dotc/SimplifyTests.scala

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,17 +79,6 @@ abstract class SimplifyTests(val optimise: Boolean) extends DottyBytecodeTest {
7979
|print(new Some(new Tuple2(1, "s")))
8080
""")
8181

82-
@Test def constantFold =
83-
check(
84-
"""
85-
|val t = true // val needed, or typer takes care of this
86-
|if (t) print(1)
87-
|else print(2)
88-
""",
89-
"""
90-
|print(1)
91-
""")
92-
9382
@Test def dropNoEffects =
9483
check(
9584
"""
@@ -124,6 +113,57 @@ abstract class SimplifyTests(val optimise: Boolean) extends DottyBytecodeTest {
124113
|println(true)
125114
""")
126115

116+
117+
/*
118+
* Constant folding tests
119+
*/
120+
121+
@Test def basicConstantFold =
122+
check(
123+
"""
124+
|val i = 3
125+
|val j = i + 4
126+
|print(j)
127+
""",
128+
"""
129+
|print(7)
130+
""")
131+
132+
@Test def branchConstantFold =
133+
check(
134+
"""
135+
|val t = true // val needed, or typer takes care of this
136+
|if (t) print(1)
137+
|else print(2)
138+
""",
139+
"""
140+
|print(1)
141+
""")
142+
143+
@Test def arithmeticConstantFold =
144+
check(
145+
"""
146+
|val i = 3
147+
|val j = i + 4
148+
|if(j - i >= (i + 1) / 2)
149+
| print(i + 1)
150+
""",
151+
"""
152+
|print(4)
153+
""")
154+
155+
@Test def TwoValConstantFold =
156+
check(
157+
"""
158+
|val i = 3
159+
|val j = 4
160+
|val k = i * j
161+
|print(k - j)
162+
""",
163+
"""
164+
|print(8)
165+
""")
166+
127167
// @Test def listPatmapExample =
128168
// check(
129169
// """

0 commit comments

Comments
 (0)