blob: 5f43b870aa21dd8ad9c7b377d515b3b4f0bcbd94 [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
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,
Bill Buzbee89efc3d2009-07-28 11:22:22 -070027 ArmLIR *headLIR,
28 ArmLIR *tailLIR)
Ben Chenge9695e52009-06-16 16:11:47 -070029{
Bill Buzbee89efc3d2009-07-28 11:22:22 -070030 ArmLIR *thisLIR;
Ben Chenge9695e52009-06-16 16:11:47 -070031
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 }
Bill Buzbee89efc3d2009-07-28 11:22:22 -070040 if (thisLIR->opCode == THUMB_STR_RRI5 &&
Ben Chenge9695e52009-06-16 16:11:47 -070041 thisLIR->operands[1] == rFP) {
42 int dRegId = thisLIR->operands[2];
43 int nativeRegId = thisLIR->operands[0];
Bill Buzbee89efc3d2009-07-28 11:22:22 -070044 ArmLIR *checkLIR;
Ben Chenge9695e52009-06-16 16:11:47 -070045 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 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -070052 if (checkLIR->opCode == THUMB_LDR_RRI5 &&
Ben Chenge9695e52009-06-16 16:11:47 -070053 checkLIR->operands[1] == rFP &&
54 checkLIR->operands[2] == dRegId) {
55 /* Insert a move to replace the load */
56 if (checkLIR->operands[0] != nativeRegId) {
Bill Buzbee89efc3d2009-07-28 11:22:22 -070057 ArmLIR *moveLIR =
58 dvmCompilerNew(sizeof(ArmLIR), true);
59 moveLIR->opCode = THUMB_MOV_RR;
Ben Chenge9695e52009-06-16 16:11:47 -070060 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 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -070073 } else if (checkLIR->opCode == THUMB_STR_RRI5 &&
Ben Chenge9695e52009-06-16 16:11:47 -070074 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 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -070093 stopHere |= checkLIR->opCode == THUMB_STMIA ||
94 checkLIR->opCode == THUMB_LDMIA ||
95 checkLIR->opCode == THUMB_STR_RRR ||
96 checkLIR->opCode == THUMB_LDR_RRR;
Ben Chenge9695e52009-06-16 16:11:47 -070097
Bill Buzbee9bc3df32009-07-30 10:52:29 -070098// FIXME: need to enhance this code to sink & play well with coprocessor ld/str
99 stopHere |= checkLIR->opCode == THUMB2_VSTRS ||
100 checkLIR->opCode == THUMB2_VSTRD ||
101 checkLIR->opCode == THUMB2_VLDRS ||
102 checkLIR->opCode == THUMB2_VLDRD;
103
Ben Chenge9695e52009-06-16 16:11:47 -0700104 stopHere |= (EncodingMap[checkLIR->opCode].flags &
105 IS_BRANCH) != 0;
106
107 /* Found a new place to put the store - move it here */
108 if (stopHere == true) {
109
110 /* The store can be sunk for at least one cycle */
111 if (sinkDistance != 0) {
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700112 ArmLIR *newStoreLIR =
113 dvmCompilerNew(sizeof(ArmLIR), true);
Ben Chenge9695e52009-06-16 16:11:47 -0700114 *newStoreLIR = *thisLIR;
115 newStoreLIR->age = cUnit->optRound;
116 /*
117 * Insertion is guaranteed to succeed since checkLIR
118 * is never the first LIR on the list
119 */
120 dvmCompilerInsertLIRBefore((LIR *) checkLIR,
121 (LIR *) newStoreLIR);
122 thisLIR->isNop = true;
123 }
124 break;
125 }
126
127 /*
128 * Saw a real instruction that the store can be sunk after
129 */
130 if (!isPseudoOpCode(checkLIR->opCode)) {
131 sinkDistance++;
132 }
133 }
134 }
135 }
136 }
137}
138
139void dvmCompilerApplyLocalOptimizations(CompilationUnit *cUnit, LIR *headLIR,
140 LIR *tailLIR)
141{
142 applyLoadStoreElimination(cUnit,
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700143 (ArmLIR *) headLIR,
144 (ArmLIR *) tailLIR);
Ben Chenge9695e52009-06-16 16:11:47 -0700145}