blob: 1ce91aff5c4646dfe2f5c148078e4049dcc977c4 [file] [log] [blame]
Ben Chenge9695e52009-06-16 16:11:47 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "Dalvik.h"
18#include "vm/compiler/CompilerInternals.h"
19#include "Armv5teLIR.h"
20
21/*
22 * Perform a pass of top-down walk to
23 * 1) Eliminate redundant loads and stores
24 * 2) Sink stores to latest possible slot
25 */
26static void applyLoadStoreElimination(CompilationUnit *cUnit,
27 Armv5teLIR *headLIR,
28 Armv5teLIR *tailLIR)
29{
30 Armv5teLIR *thisLIR;
31
32 cUnit->optRound++;
33 for (thisLIR = headLIR;
34 thisLIR != tailLIR;
35 thisLIR = NEXT_LIR(thisLIR)) {
36 /* Skip newly added instructions */
37 if (thisLIR->age >= cUnit->optRound) {
38 continue;
39 }
40 if (thisLIR->opCode == ARMV5TE_STR_RRI5 &&
41 thisLIR->operands[1] == rFP) {
42 int dRegId = thisLIR->operands[2];
43 int nativeRegId = thisLIR->operands[0];
44 Armv5teLIR *checkLIR;
45 int sinkDistance = 0;
46
47 for (checkLIR = NEXT_LIR(thisLIR);
48 checkLIR != tailLIR;
49 checkLIR = NEXT_LIR(checkLIR)) {
50
51 /* Check if a Dalvik register load is redundant */
52 if (checkLIR->opCode == ARMV5TE_LDR_RRI5 &&
53 checkLIR->operands[1] == rFP &&
54 checkLIR->operands[2] == dRegId) {
55 /* Insert a move to replace the load */
56 if (checkLIR->operands[0] != nativeRegId) {
57 Armv5teLIR *moveLIR =
58 dvmCompilerNew(sizeof(Armv5teLIR), true);
59 moveLIR->opCode = ARMV5TE_MOV_RR;
60 moveLIR->operands[0] = checkLIR->operands[0];
61 moveLIR->operands[1] = nativeRegId;
62 /*
63 * Insertion is guaranteed to succeed since checkLIR
64 * is never the first LIR on the list
65 */
66 dvmCompilerInsertLIRBefore((LIR *) checkLIR,
67 (LIR *) moveLIR);
68 }
69 checkLIR->isNop = true;
70 continue;
71
72 /* Found a true output dependency - nuke the previous store */
73 } else if (checkLIR->opCode == ARMV5TE_STR_RRI5 &&
74 checkLIR->operands[1] == rFP &&
75 checkLIR->operands[2] == dRegId) {
76 thisLIR->isNop = true;
77 break;
78 /* Find out the latest slot that the store can be sunk into */
79 } else {
80 bool stopHere = false;
81
82 /* Last instruction reached */
83 stopHere |= checkLIR->generic.next == NULL;
84
85 /* Store data is clobbered */
86 stopHere |= (EncodingMap[checkLIR->opCode].flags &
87 CLOBBER_DEST) != 0 &&
88 checkLIR->operands[0] == nativeRegId;
89 /*
90 * Conservatively assume there is a memory dependency
91 * for st/ld multiples and reg+reg address mode
92 */
93 stopHere |= checkLIR->opCode == ARMV5TE_STMIA ||
94 checkLIR->opCode == ARMV5TE_LDMIA ||
95 checkLIR->opCode == ARMV5TE_STR_RRR ||
96 checkLIR->opCode == ARMV5TE_LDR_RRR;
97
98 stopHere |= (EncodingMap[checkLIR->opCode].flags &
99 IS_BRANCH) != 0;
100
101 /* Found a new place to put the store - move it here */
102 if (stopHere == true) {
103
104 /* The store can be sunk for at least one cycle */
105 if (sinkDistance != 0) {
106 Armv5teLIR *newStoreLIR =
107 dvmCompilerNew(sizeof(Armv5teLIR), true);
108 *newStoreLIR = *thisLIR;
109 newStoreLIR->age = cUnit->optRound;
110 /*
111 * Insertion is guaranteed to succeed since checkLIR
112 * is never the first LIR on the list
113 */
114 dvmCompilerInsertLIRBefore((LIR *) checkLIR,
115 (LIR *) newStoreLIR);
116 thisLIR->isNop = true;
117 }
118 break;
119 }
120
121 /*
122 * Saw a real instruction that the store can be sunk after
123 */
124 if (!isPseudoOpCode(checkLIR->opCode)) {
125 sinkDistance++;
126 }
127 }
128 }
129 }
130 }
131}
132
133void dvmCompilerApplyLocalOptimizations(CompilationUnit *cUnit, LIR *headLIR,
134 LIR *tailLIR)
135{
136 applyLoadStoreElimination(cUnit,
137 (Armv5teLIR *) headLIR,
138 (Armv5teLIR *) tailLIR);
139}