blob: 11aaeddaf93221c179f5a3da8888fb8a37089794 [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"
Bill Buzbee89efc3d2009-07-28 11:22:22 -070019#include "ArmLIR.h"
Ben Chenge9695e52009-06-16 16:11:47 -070020
Bill Buzbee7ea0f642009-08-10 17:06:51 -070021ArmLIR* dvmCompilerGenCopy(CompilationUnit *cUnit, int rDest, int rSrc);
22
23/* Is this a Dalvik register access? */
24static inline bool isDalvikLoad(ArmLIR *lir)
25{
26 return ((lir->operands[1] == rFP) &&
27 ((lir->opCode == THUMB_LDR_RRI5) ||
28 (lir->opCode == THUMB2_LDR_RRI12) ||
29 (lir->opCode == THUMB2_VLDRS) ||
30 (lir->opCode == THUMB2_VLDRD)));
31}
32
33static inline bool isDalvikStore(ArmLIR *lir)
34{
35 return ((lir->operands[1] == rFP) &&
36 ((lir->opCode == THUMB_STR_RRI5) ||
37 (lir->opCode == THUMB2_STR_RRI12) ||
38 (lir->opCode == THUMB2_VSTRS) ||
39 (lir->opCode == THUMB2_VSTRD)));
40}
41
Ben Chenge9695e52009-06-16 16:11:47 -070042/*
43 * Perform a pass of top-down walk to
44 * 1) Eliminate redundant loads and stores
45 * 2) Sink stores to latest possible slot
46 */
47static void applyLoadStoreElimination(CompilationUnit *cUnit,
Bill Buzbee89efc3d2009-07-28 11:22:22 -070048 ArmLIR *headLIR,
49 ArmLIR *tailLIR)
Ben Chenge9695e52009-06-16 16:11:47 -070050{
Bill Buzbee89efc3d2009-07-28 11:22:22 -070051 ArmLIR *thisLIR;
Ben Chenge9695e52009-06-16 16:11:47 -070052
53 cUnit->optRound++;
54 for (thisLIR = headLIR;
55 thisLIR != tailLIR;
56 thisLIR = NEXT_LIR(thisLIR)) {
57 /* Skip newly added instructions */
58 if (thisLIR->age >= cUnit->optRound) {
59 continue;
60 }
Bill Buzbee7ea0f642009-08-10 17:06:51 -070061 if (isDalvikStore(thisLIR)) {
Ben Chenge9695e52009-06-16 16:11:47 -070062 int dRegId = thisLIR->operands[2];
63 int nativeRegId = thisLIR->operands[0];
Bill Buzbee89efc3d2009-07-28 11:22:22 -070064 ArmLIR *checkLIR;
Ben Chenge9695e52009-06-16 16:11:47 -070065 int sinkDistance = 0;
66
67 for (checkLIR = NEXT_LIR(thisLIR);
68 checkLIR != tailLIR;
69 checkLIR = NEXT_LIR(checkLIR)) {
70
71 /* Check if a Dalvik register load is redundant */
Bill Buzbee7ea0f642009-08-10 17:06:51 -070072 if (isDalvikLoad(checkLIR) &&
73 checkLIR->operands[2] == dRegId ) {
74 if (FPREG(nativeRegId) != FPREG(checkLIR->operands[0])) {
75 break; // TODO: handle gen<=>float copies
76 }
Ben Chenge9695e52009-06-16 16:11:47 -070077 /* Insert a move to replace the load */
78 if (checkLIR->operands[0] != nativeRegId) {
Bill Buzbee7ea0f642009-08-10 17:06:51 -070079 ArmLIR *moveLIR;
80 moveLIR = dvmCompilerRegCopy(cUnit,
81 checkLIR->operands[0],
82 nativeRegId);
Ben Chenge9695e52009-06-16 16:11:47 -070083 /*
84 * Insertion is guaranteed to succeed since checkLIR
85 * is never the first LIR on the list
86 */
87 dvmCompilerInsertLIRBefore((LIR *) checkLIR,
88 (LIR *) moveLIR);
89 }
90 checkLIR->isNop = true;
91 continue;
92
93 /* Found a true output dependency - nuke the previous store */
Bill Buzbee7ea0f642009-08-10 17:06:51 -070094 } else if (isDalvikStore(checkLIR) &&
Ben Chenge9695e52009-06-16 16:11:47 -070095 checkLIR->operands[2] == dRegId) {
96 thisLIR->isNop = true;
97 break;
98 /* Find out the latest slot that the store can be sunk into */
99 } else {
100 bool stopHere = false;
101
102 /* Last instruction reached */
103 stopHere |= checkLIR->generic.next == NULL;
104
Ben Chenge9695e52009-06-16 16:11:47 -0700105 /*
106 * Conservatively assume there is a memory dependency
107 * for st/ld multiples and reg+reg address mode
108 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700109 stopHere |= checkLIR->opCode == THUMB_STMIA ||
110 checkLIR->opCode == THUMB_LDMIA ||
111 checkLIR->opCode == THUMB_STR_RRR ||
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700112 checkLIR->opCode == THUMB_LDR_RRR ||
113 checkLIR->opCode == THUMB2_VLDRD ||
114 checkLIR->opCode == THUMB2_VSTRD;
115;
Ben Chenge9695e52009-06-16 16:11:47 -0700116
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700117 if (!isPseudoOpCode(checkLIR->opCode)) {
Bill Buzbee9bc3df32009-07-30 10:52:29 -0700118
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700119 /* Store data is clobbered */
120 stopHere |= (EncodingMap[checkLIR->opCode].flags &
121 CLOBBER_DEST) != 0 &&
122 checkLIR->operands[0] == nativeRegId;
123
124 stopHere |= (EncodingMap[checkLIR->opCode].flags &
125 IS_BRANCH) != 0;
126 }
Ben Chenge9695e52009-06-16 16:11:47 -0700127
128 /* Found a new place to put the store - move it here */
129 if (stopHere == true) {
130
131 /* The store can be sunk for at least one cycle */
132 if (sinkDistance != 0) {
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700133 ArmLIR *newStoreLIR =
134 dvmCompilerNew(sizeof(ArmLIR), true);
Ben Chenge9695e52009-06-16 16:11:47 -0700135 *newStoreLIR = *thisLIR;
136 newStoreLIR->age = cUnit->optRound;
137 /*
138 * Insertion is guaranteed to succeed since checkLIR
139 * is never the first LIR on the list
140 */
141 dvmCompilerInsertLIRBefore((LIR *) checkLIR,
142 (LIR *) newStoreLIR);
143 thisLIR->isNop = true;
144 }
145 break;
146 }
147
148 /*
149 * Saw a real instruction that the store can be sunk after
150 */
151 if (!isPseudoOpCode(checkLIR->opCode)) {
152 sinkDistance++;
153 }
154 }
155 }
156 }
157 }
158}
159
160void dvmCompilerApplyLocalOptimizations(CompilationUnit *cUnit, LIR *headLIR,
161 LIR *tailLIR)
162{
163 applyLoadStoreElimination(cUnit,
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700164 (ArmLIR *) headLIR,
165 (ArmLIR *) tailLIR);
Ben Chenge9695e52009-06-16 16:11:47 -0700166}