1 /* 2 * Copyright (C) 2008 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 package com.android.dx.ssa; 18 19 import com.android.dx.rop.code.CstInsn; 20 import com.android.dx.rop.code.LocalItem; 21 import com.android.dx.rop.code.RegOps; 22 import com.android.dx.rop.code.RegisterSpec; 23 import com.android.dx.rop.cst.CstInteger; 24 import java.util.HashSet; 25 import java.util.List; 26 27 /** 28 * Combine identical move-param insns, which may result from Ropper's 29 * handling of synchronized methods. 30 */ 31 public class MoveParamCombiner { 32 33 /** method to process */ 34 private final SsaMethod ssaMeth; 35 36 /** 37 * Processes a method with this optimization step. 38 * 39 * @param ssaMethod method to process 40 */ 41 public static void process(SsaMethod ssaMethod) { 42 new MoveParamCombiner(ssaMethod).run(); 43 } 44 45 private MoveParamCombiner(SsaMethod ssaMeth) { 46 this.ssaMeth = ssaMeth; 47 } 48 49 /** 50 * Runs this optimization step. 51 */ 52 private void run() { 53 // This will contain the definition specs for each parameter 54 final RegisterSpec[] paramSpecs 55 = new RegisterSpec[ssaMeth.getParamWidth()]; 56 57 // Insns to delete when all done 58 final HashSet<SsaInsn> deletedInsns = new HashSet(); 59 60 ssaMeth.forEachInsn(new SsaInsn.Visitor() { 61 public void visitMoveInsn (NormalSsaInsn insn) { 62 } 63 public void visitPhiInsn (PhiInsn phi) { 64 } 65 public void visitNonMoveInsn (NormalSsaInsn insn) { 66 if (insn.getOpcode().getOpcode() != RegOps.MOVE_PARAM) { 67 return; 68 } 69 70 int param = getParamIndex(insn); 71 72 if (paramSpecs[param] == null) { 73 paramSpecs[param] = insn.getResult(); 74 } else { 75 final RegisterSpec specA = paramSpecs[param]; 76 final RegisterSpec specB = insn.getResult(); 77 LocalItem localA = specA.getLocalItem(); 78 LocalItem localB = specB.getLocalItem(); 79 LocalItem newLocal; 80 81 /* 82 * Is there local information to preserve? 83 */ 84 85 if (localA == null) { 86 newLocal = localB; 87 } else if (localB == null) { 88 newLocal = localA; 89 } else if (localA.equals(localB)) { 90 newLocal = localA; 91 } else { 92 /* 93 * Oddly, these two identical move-params have distinct 94 * debug info. We'll just keep them distinct. 95 */ 96 return; 97 } 98 99 ssaMeth.getDefinitionForRegister(specA.getReg()) 100 .setResultLocal(newLocal); 101 102 /* 103 * Map all uses of specB to specA 104 */ 105 106 RegisterMapper mapper = new RegisterMapper() { 107 /** @inheritDoc */ 108 public int getNewRegisterCount() { 109 return ssaMeth.getRegCount(); 110 } 111 112 /** @inheritDoc */ 113 public RegisterSpec map(RegisterSpec registerSpec) { 114 if (registerSpec.getReg() == specB.getReg()) { 115 return specA; 116 } 117 118 return registerSpec; 119 } 120 }; 121 122 List<SsaInsn> uses 123 = ssaMeth.getUseListForRegister(specB.getReg()); 124 125 // Use list is modified by mapSourceRegisters 126 for (int i = uses.size() - 1; i >= 0; i--) { 127 SsaInsn use = uses.get(i); 128 use.mapSourceRegisters(mapper); 129 } 130 131 deletedInsns.add(insn); 132 } 133 134 } 135 }); 136 137 ssaMeth.deleteInsns(deletedInsns); 138 } 139 140 /** 141 * Returns the parameter index associated with a move-param insn. Does 142 * not verify that the insn is a move-param insn. 143 * 144 * @param insn {@code non-null;} a move-param insn 145 * @return {@code >=0;} parameter index 146 */ 147 private int getParamIndex(NormalSsaInsn insn) { 148 CstInsn cstInsn = (CstInsn)(insn.getOriginalRopInsn()); 149 150 int param = ((CstInteger)cstInsn.getConstant()).getValue(); 151 return param; 152 } 153 154 } 155