1
1
/* NSC -- new Scala compiler
2
* Copyright 2005-2011 LAMP/EPFL
2
* Copyright 2005-2013 LAMP/EPFL
3
3
* @author Iulian Dragos
7
6
package scala.tools.nsc
10
import scala.collection.mutable.{Map, HashMap}
11
9
import scala.tools.nsc.backend.icode.analysis.LubException
12
10
import scala.tools.nsc.symtab._
37
35
case (STORE_LOCAL(x), LOAD_LOCAL(y)) if (x == y) =>
38
36
var liveOut = liveness.out(bb)
40
log("store/load to a dead local? " + x)
38
debuglog("store/load to a dead local? " + x)
41
39
val instrs = bb.getArray
42
40
var idx = instrs.length - 1
43
41
while (idx > 0 && (instrs(idx) ne i2)) {
96
95
import copyPropagation._
98
97
/* Some embryonic copy propagation. */
99
def analyzeMethod(m: IMethod): Unit = try {if (m.code ne null) {
100
log("Analyzing " + m)
98
def analyzeMethod(m: IMethod): Unit = try {if (m.hasCode) {
104
for (bb <- linearizer.linearize(m)) {
102
m.linearizedBlocks() foreach { bb =>
105
103
var info = cpp.in(bb)
106
if (settings.debug.value) log("Cpp info at entry to block " + bb + ": " + info)
104
debuglog("Cpp info at entry to block " + bb + ": " + info)
110
108
case LOAD_LOCAL(l) if info.bindings isDefinedAt LocalVar(l) =>
111
109
val t = info.getBinding(l)
113
case Deref(LocalVar(_)) | Deref(This) | Const(_) =>
111
case Deref(This) | Const(_) =>
114
112
bb.replaceInstruction(i, valueToInstruction(t));
115
log("replaced " + i + " with " + t)
113
debuglog(s"replaced $i with $t")
118
bb.replaceInstruction(i, LOAD_LOCAL(info.getAlias(l)))
119
log("replaced " + i + " with " + info.getAlias(l))
116
val t = info.getAlias(l)
117
bb.replaceInstruction(i, LOAD_LOCAL(t))
118
debuglog(s"replaced $i with $t")
123
121
case LOAD_FIELD(f, false) /* if accessible(f, m.symbol) */ =>
124
122
def replaceFieldAccess(r: Record) {
125
123
val Record(cls, bindings) = r
126
info.getFieldNonRecordValue(r, f) match {
128
bb.replaceInstruction(i,
129
DROP(REFERENCE(cls)) :: valueToInstruction(v) :: Nil);
130
log("Replaced " + i + " with " + info.getFieldNonRecordValue(r, f));
124
info.getFieldNonRecordValue(r, f) foreach { v =>
125
bb.replaceInstruction(i, DROP(REFERENCE(cls)) :: valueToInstruction(v) :: Nil)
126
debuglog(s"replaced $i with $v")
150
case UNBOX(boxType) =>
156
151
info.stack match {
157
152
case Deref(LocalVar(loc1)) :: _ if info.bindings isDefinedAt LocalVar(loc1) =>
158
153
val value = info.getBinding(loc1)
160
case Boxed(LocalVar(loc2)) =>
155
case Boxed(LocalVar(loc2)) if loc2.kind == boxType =>
161
156
bb.replaceInstruction(i, DROP(icodes.ObjectReference) :: valueToInstruction(info.getBinding(loc2)) :: Nil)
162
log("replaced " + i + " with " + info.getBinding(loc2))
157
debuglog("replaced " + i + " with " + info.getBinding(loc2))
166
case Boxed(LocalVar(loc1)) :: _ =>
161
case Boxed(LocalVar(loc1)) :: _ if loc1.kind == boxType =>
167
162
val loc2 = info.getAlias(loc1)
168
163
bb.replaceInstruction(i, DROP(icodes.ObjectReference) :: valueToInstruction(Deref(LocalVar(loc2))) :: Nil)
169
log("replaced " + i + " with " + LocalVar(loc2))
164
debuglog("replaced " + i + " with " + LocalVar(loc2))
203
198
/** Peephole optimization. */
204
199
abstract class PeepholeOpt {
206
private var method: IMethod = null
201
private var method: IMethod = NoIMethod
208
203
/** Concrete implementations will perform their optimizations here */
209
204
def peep(bb: BasicBlock, i1: Instruction, i2: Instruction): Option[List[Instruction]]
211
206
var liveness: global.icodes.liveness.LivenessAnalysis = null
213
def apply(m: IMethod): Unit = if (m.code ne null) {
208
def apply(m: IMethod): Unit = if (m.hasCode) {
215
210
liveness = new global.icodes.liveness.LivenessAnalysis
218
for (b <- m.code.blocks)
213
m foreachBlock transformBlock
222
216
def transformBlock(b: BasicBlock): Unit = if (b.size >= 2) {
223
var newInstructions: List[Instruction] = Nil
225
newInstructions = b.toList
217
var newInstructions: List[Instruction] = b.toList
229
221
var h = newInstructions.head
230
222
var t = newInstructions.tail