PageRenderTime 29ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/dalvik/dx/src/com/android/dx/ssa/back/RegisterAllocator.java

https://gitlab.com/brian0218/rk3188_r-box_android4.2.2_sdk
Java | 197 lines | 81 code | 31 blank | 85 comment | 11 complexity | de159c6a890c6c1fdd97567e95c034ba MD5 | raw file
  1. /*
  2. * Copyright (C) 2007 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. package com.android.dx.ssa.back;
  17. import com.android.dx.rop.code.RegOps;
  18. import com.android.dx.rop.code.RegisterSpec;
  19. import com.android.dx.rop.code.PlainInsn;
  20. import com.android.dx.rop.code.Rops;
  21. import com.android.dx.rop.code.SourcePosition;
  22. import com.android.dx.rop.code.RegisterSpecList;
  23. import com.android.dx.ssa.NormalSsaInsn;
  24. import com.android.dx.ssa.RegisterMapper;
  25. import com.android.dx.ssa.SsaInsn;
  26. import com.android.dx.ssa.SsaMethod;
  27. import com.android.dx.ssa.SsaBasicBlock;
  28. import com.android.dx.util.IntSet;
  29. import com.android.dx.util.IntIterator;
  30. import java.util.BitSet;
  31. import java.util.ArrayList;
  32. /**
  33. * Base class of all register allocators.
  34. */
  35. public abstract class RegisterAllocator {
  36. /** method being processed */
  37. protected final SsaMethod ssaMeth;
  38. /** interference graph, indexed by register in both dimensions */
  39. protected final InterferenceGraph interference;
  40. /**
  41. * Creates an instance. Call {@code allocateRegisters} to run.
  42. * @param ssaMeth method to process.
  43. * @param interference Interference graph, indexed by register in both
  44. * dimensions.
  45. */
  46. public RegisterAllocator(SsaMethod ssaMeth,
  47. InterferenceGraph interference) {
  48. this.ssaMeth = ssaMeth;
  49. this.interference = interference;
  50. }
  51. /**
  52. * Indicates whether the method params were allocated at the bottom
  53. * of the namespace, and thus should be moved up to the top of the
  54. * namespace after phi removal.
  55. *
  56. * @return {@code true} if params should be moved from low to high
  57. */
  58. public abstract boolean wantsParamsMovedHigh();
  59. /**
  60. * Runs the algorithm.
  61. *
  62. * @return a register mapper to apply to the {@code SsaMethod}
  63. */
  64. public abstract RegisterMapper allocateRegisters();
  65. /**
  66. * Returns the category (width) of the definition site of the register.
  67. * Returns {@code 1} for undefined registers.
  68. *
  69. * @param reg register
  70. * @return {@code 1..2}
  71. */
  72. protected final int getCategoryForSsaReg(int reg) {
  73. SsaInsn definition = ssaMeth.getDefinitionForRegister(reg);
  74. if (definition == null) {
  75. // an undefined reg
  76. return 1;
  77. } else {
  78. return definition.getResult().getCategory();
  79. }
  80. }
  81. /**
  82. * Returns the RegisterSpec of the definition of the register.
  83. *
  84. * @param reg {@code >= 0;} SSA register
  85. * @return definition spec of the register or null if it is never defined
  86. * (for the case of "version 0" SSA registers)
  87. */
  88. protected final RegisterSpec getDefinitionSpecForSsaReg(int reg) {
  89. SsaInsn definition = ssaMeth.getDefinitionForRegister(reg);
  90. return definition == null ? null : definition.getResult();
  91. }
  92. /**
  93. * Returns true if the definition site of this register is a
  94. * move-param (ie, this is a method parameter).
  95. *
  96. * @param reg register in question
  97. * @return {@code true} if this is a method parameter
  98. */
  99. protected boolean isDefinitionMoveParam(int reg) {
  100. SsaInsn defInsn = ssaMeth.getDefinitionForRegister(reg);
  101. if (defInsn instanceof NormalSsaInsn) {
  102. NormalSsaInsn ndefInsn = (NormalSsaInsn) defInsn;
  103. return ndefInsn.getOpcode().getOpcode() == RegOps.MOVE_PARAM;
  104. }
  105. return false;
  106. }
  107. /**
  108. * Inserts a move instruction for a specified SSA register before a
  109. * specified instruction, creating a new SSA register and adjusting the
  110. * interference graph in the process. The insn currently must be the
  111. * last insn in a block.
  112. *
  113. * @param insn {@code non-null;} insn to insert move before, must
  114. * be last insn in block
  115. * @param reg {@code non-null;} SSA register to duplicate
  116. * @return {@code non-null;} spec of new SSA register created by move
  117. */
  118. protected final RegisterSpec insertMoveBefore(SsaInsn insn,
  119. RegisterSpec reg) {
  120. SsaBasicBlock block = insn.getBlock();
  121. ArrayList<SsaInsn> insns = block.getInsns();
  122. int insnIndex = insns.indexOf(insn);
  123. if (insnIndex < 0) {
  124. throw new IllegalArgumentException (
  125. "specified insn is not in this block");
  126. }
  127. if (insnIndex != insns.size() - 1) {
  128. /*
  129. * Presently, the interference updater only works when
  130. * adding before the last insn, and the last insn must have no
  131. * result
  132. */
  133. throw new IllegalArgumentException(
  134. "Adding move here not supported:" + insn.toHuman());
  135. }
  136. /*
  137. * Get new register and make new move instruction.
  138. */
  139. // The new result must not have an associated local variable.
  140. RegisterSpec newRegSpec = RegisterSpec.make(ssaMeth.makeNewSsaReg(),
  141. reg.getTypeBearer());
  142. SsaInsn toAdd = SsaInsn.makeFromRop(
  143. new PlainInsn(Rops.opMove(newRegSpec.getType()),
  144. SourcePosition.NO_INFO, newRegSpec,
  145. RegisterSpecList.make(reg)), block);
  146. insns.add(insnIndex, toAdd);
  147. int newReg = newRegSpec.getReg();
  148. /*
  149. * Adjust interference graph based on what's live out of the current
  150. * block and what's used by the final instruction.
  151. */
  152. IntSet liveOut = block.getLiveOutRegs();
  153. IntIterator liveOutIter = liveOut.iterator();
  154. while (liveOutIter.hasNext()) {
  155. interference.add(newReg, liveOutIter.next());
  156. }
  157. // Everything that's a source in the last insn interferes.
  158. RegisterSpecList sources = insn.getSources();
  159. int szSources = sources.size();
  160. for (int i = 0; i < szSources; i++) {
  161. interference.add(newReg, sources.get(i).getReg());
  162. }
  163. ssaMeth.onInsnsChanged();
  164. return newRegSpec;
  165. }
  166. }