Home | History | Annotate | Download | only in ssa
      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