1 /*
   2  * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.graalvm.compiler.hotspot.sparc;
  24 
  25 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC;
  26 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.isGlobalRegister;
  27 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.NOT_ANNUL;
  28 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_NOT_TAKEN;
  29 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CC.Xcc;
  30 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.NotEqual;
  31 import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry;
  32 import static jdk.vm.ci.code.ValueUtil.asRegister;
  33 import static jdk.vm.ci.code.ValueUtil.isRegister;
  34 import static jdk.vm.ci.sparc.SPARC.g0;
  35 import static jdk.vm.ci.sparc.SPARC.g5;
  36 import static jdk.vm.ci.sparc.SPARC.i0;
  37 import static jdk.vm.ci.sparc.SPARC.i7;
  38 import static jdk.vm.ci.sparc.SPARC.l0;
  39 import static jdk.vm.ci.sparc.SPARC.l7;
  40 import static jdk.vm.ci.sparc.SPARC.o0;
  41 import static jdk.vm.ci.sparc.SPARC.o7;
  42 import static jdk.vm.ci.sparc.SPARC.sp;
  43 
  44 import java.util.HashSet;
  45 import java.util.List;
  46 import java.util.Map;
  47 import java.util.Set;
  48 import java.util.concurrent.ConcurrentHashMap;
  49 
  50 import org.graalvm.compiler.asm.Assembler;
  51 import org.graalvm.compiler.asm.Label;
  52 import org.graalvm.compiler.asm.sparc.SPARCAddress;
  53 import org.graalvm.compiler.asm.sparc.SPARCAssembler;
  54 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
  55 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister;
  56 import org.graalvm.compiler.code.CompilationResult;
  57 import org.graalvm.compiler.code.DataSection;
  58 import org.graalvm.compiler.code.DataSection.Data;
  59 import org.graalvm.compiler.core.common.CompilationIdentifier;
  60 import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
  61 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
  62 import org.graalvm.compiler.core.sparc.SPARCNodeMatchRules;
  63 import org.graalvm.compiler.debug.Debug;
  64 import org.graalvm.compiler.debug.DebugCounter;
  65 import org.graalvm.compiler.hotspot.HotSpotDataBuilder;
  66 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
  67 import org.graalvm.compiler.hotspot.HotSpotHostBackend;
  68 import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult;
  69 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
  70 import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
  71 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
  72 import org.graalvm.compiler.hotspot.stubs.Stub;
  73 import org.graalvm.compiler.lir.InstructionValueConsumer;
  74 import org.graalvm.compiler.lir.LIR;
  75 import org.graalvm.compiler.lir.LIRFrameState;
  76 import org.graalvm.compiler.lir.LIRInstruction;
  77 import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
  78 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
  79 import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
  80 import org.graalvm.compiler.lir.asm.DataBuilder;
  81 import org.graalvm.compiler.lir.asm.FrameContext;
  82 import org.graalvm.compiler.lir.framemap.FrameMap;
  83 import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
  84 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
  85 import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
  86 import org.graalvm.compiler.lir.sparc.SPARCCall;
  87 import org.graalvm.compiler.lir.sparc.SPARCDelayedControlTransfer;
  88 import org.graalvm.compiler.lir.sparc.SPARCFrameMap;
  89 import org.graalvm.compiler.lir.sparc.SPARCFrameMapBuilder;
  90 import org.graalvm.compiler.lir.sparc.SPARCLIRInstructionMixin;
  91 import org.graalvm.compiler.lir.sparc.SPARCLIRInstructionMixin.SizeEstimate;
  92 import org.graalvm.compiler.lir.sparc.SPARCTailDelayedLIRInstruction;
  93 import org.graalvm.compiler.nodes.StructuredGraph;
  94 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
  95 
  96 import jdk.vm.ci.code.CallingConvention;
  97 import jdk.vm.ci.code.Register;
  98 import jdk.vm.ci.code.RegisterConfig;
  99 import jdk.vm.ci.code.StackSlot;
 100 import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
 101 import jdk.vm.ci.meta.JavaType;
 102 import jdk.vm.ci.meta.ResolvedJavaMethod;
 103 
 104 /**
 105  * HotSpot SPARC specific backend.
 106  */
 107 public class SPARCHotSpotBackend extends HotSpotHostBackend {
 108 
 109     private static final SizeEstimateStatistics CONSTANT_ESTIMATED_STATS = new SizeEstimateStatistics("ESTIMATE");
 110     private static final SizeEstimateStatistics CONSTANT_ACTUAL_STATS = new SizeEstimateStatistics("ACTUAL");
 111 
 112     public SPARCHotSpotBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) {
 113         super(config, runtime, providers);
 114     }
 115 
 116     private static class SizeEstimateStatistics {
 117         private static final ConcurrentHashMap<String, DebugCounter> counters = new ConcurrentHashMap<>();
 118         private final String suffix;
 119 
 120         SizeEstimateStatistics(String suffix) {
 121             super();
 122             this.suffix = suffix;
 123         }
 124 
 125         public void add(Class<?> c, int count) {
 126             String name = SizeEstimateStatistics.class.getSimpleName() + "_" + c.getSimpleName() + "." + suffix;
 127             DebugCounter m = counters.computeIfAbsent(name, (n) -> Debug.counter(n));
 128             m.add(count);
 129         }
 130     }
 131 
 132     @Override
 133     public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
 134         RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
 135         return new SPARCFrameMapBuilder(newFrameMap(registerConfigNonNull), getCodeCache(), registerConfigNonNull);
 136     }
 137 
 138     @Override
 139     public FrameMap newFrameMap(RegisterConfig registerConfig) {
 140         return new SPARCFrameMap(getCodeCache(), registerConfig, this);
 141     }
 142 
 143     @Override
 144     public LIRGeneratorTool newLIRGenerator(LIRGenerationResult lirGenRes) {
 145         return new SPARCHotSpotLIRGenerator(getProviders(), getRuntime().getVMConfig(), lirGenRes);
 146     }
 147 
 148     @Override
 149     public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, StructuredGraph graph, Object stub) {
 150         return new HotSpotLIRGenerationResult(compilationId, lir, frameMapBuilder, makeCallingConvention(graph, (Stub) stub), stub);
 151     }
 152 
 153     @Override
 154     public NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) {
 155         return new SPARCHotSpotNodeLIRBuilder(graph, lirGen, new SPARCNodeMatchRules(lirGen));
 156     }
 157 
 158     @Override
 159     protected void bangStackWithOffset(CompilationResultBuilder crb, int bangOffset) {
 160         // Use SPARCAddress to get the final displacement including the stack bias.
 161         SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm;
 162         SPARCAddress address = new SPARCAddress(sp, -bangOffset);
 163         if (SPARCAssembler.isSimm13(address.getDisplacement())) {
 164             masm.stx(g0, address);
 165         } else {
 166             try (ScratchRegister sc = masm.getScratchRegister()) {
 167                 Register scratch = sc.getRegister();
 168                 assert isGlobalRegister(scratch) : "Only global (g1-g7) registers are allowed if the frame was not initialized here. Got register " + scratch;
 169                 masm.setx(address.getDisplacement(), scratch, false);
 170                 masm.stx(g0, new SPARCAddress(sp, scratch));
 171             }
 172         }
 173     }
 174 
 175     public class HotSpotFrameContext implements FrameContext {
 176 
 177         final boolean isStub;
 178 
 179         HotSpotFrameContext(boolean isStub) {
 180             this.isStub = isStub;
 181         }
 182 
 183         @Override
 184         public boolean hasFrame() {
 185             return true;
 186         }
 187 
 188         @Override
 189         public void enter(CompilationResultBuilder crb) {
 190             final int frameSize = crb.frameMap.totalFrameSize();
 191             final int stackpoinerChange = -frameSize;
 192             SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm;
 193             emitStackOverflowCheck(crb);
 194 
 195             if (SPARCAssembler.isSimm13(stackpoinerChange)) {
 196                 masm.save(sp, stackpoinerChange, sp);
 197             } else {
 198                 try (ScratchRegister sc = masm.getScratchRegister()) {
 199                     Register scratch = sc.getRegister();
 200                     assert isGlobalRegister(scratch) : "Only global registers are allowed before save. Got register " + scratch;
 201                     masm.setx(stackpoinerChange, scratch, false);
 202                     masm.save(sp, scratch, sp);
 203                 }
 204             }
 205 
 206             if (ZapStackOnMethodEntry.getValue()) {
 207                 final int slotSize = 8;
 208                 for (int i = 0; i < frameSize / slotSize; ++i) {
 209                     // 0xC1C1C1C1
 210                     masm.stx(g0, new SPARCAddress(sp, i * slotSize));
 211                 }
 212             }
 213         }
 214 
 215         @Override
 216         public void leave(CompilationResultBuilder crb) {
 217             SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm;
 218             masm.restoreWindow();
 219         }
 220     }
 221 
 222     @Override
 223     protected Assembler createAssembler(FrameMap frameMap) {
 224         return new SPARCMacroAssembler(getTarget());
 225     }
 226 
 227     @Override
 228     public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
 229         HotSpotLIRGenerationResult gen = (HotSpotLIRGenerationResult) lirGenRes;
 230         LIR lir = gen.getLIR();
 231         assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame";
 232 
 233         Stub stub = gen.getStub();
 234         Assembler masm = createAssembler(frameMap);
 235         // On SPARC we always use stack frames.
 236         HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null);
 237         DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget());
 238         CompilationResultBuilder crb = factory.createBuilder(getProviders().getCodeCache(), getProviders().getForeignCalls(), frameMap, masm, dataBuilder, frameContext, compilationResult);
 239         crb.setTotalFrameSize(frameMap.totalFrameSize());
 240         crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize());
 241         StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot();
 242         if (deoptimizationRescueSlot != null && stub == null) {
 243             crb.compilationResult.setCustomStackAreaOffset(deoptimizationRescueSlot);
 244         }
 245 
 246         if (stub != null) {
 247             // Even on sparc we need to save floating point registers
 248             Set<Register> destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir);
 249             Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = gen.getCalleeSaveInfo();
 250             updateStub(stub, destroyedCallerRegisters, calleeSaveInfo, frameMap);
 251         }
 252         assert registerSizePredictionValidator(crb);
 253         return crb;
 254     }
 255 
 256     /**
 257      * Registers a verifier which checks if the LIRInstructions estimate of constants size is
 258      * greater or equal to the actual one.
 259      */
 260     private static boolean registerSizePredictionValidator(final CompilationResultBuilder crb) {
 261         /**
 262          * Used to hold state between beforeOp and afterOp
 263          */
 264         class ValidationState {
 265             LIRInstruction op;
 266             int constantSizeBefore;
 267 
 268             public void before(LIRInstruction before) {
 269                 assert op == null : "LIRInstruction " + op + " no after call received";
 270                 op = before;
 271                 constantSizeBefore = calculateDataSectionSize(crb.compilationResult.getDataSection());
 272             }
 273 
 274             public void after(LIRInstruction after) {
 275                 assert after.equals(op) : "Instructions before/after don't match " + op + "/" + after;
 276                 int constantSizeAfter = calculateDataSectionSize(crb.compilationResult.getDataSection());
 277                 int actual = constantSizeAfter - constantSizeBefore;
 278                 if (op instanceof SPARCLIRInstructionMixin) {
 279                     org.graalvm.compiler.lir.sparc.SPARCLIRInstructionMixin.SizeEstimate size = ((SPARCLIRInstructionMixin) op).estimateSize();
 280                     assert size != null : "No size prediction available for op: " + op;
 281                     Class<?> c = op.getClass();
 282                     CONSTANT_ESTIMATED_STATS.add(c, size.constantSize);
 283                     CONSTANT_ACTUAL_STATS.add(c, actual);
 284                     assert size.constantSize >= actual : "Op " + op + " exceeded estimated constant size; predicted: " + size.constantSize + " actual: " + actual;
 285                 } else {
 286                     assert actual == 0 : "Op " + op + " emitted to DataSection without any estimate.";
 287                 }
 288                 op = null;
 289                 constantSizeBefore = 0;
 290             }
 291         }
 292         final ValidationState state = new ValidationState();
 293         crb.setOpCallback(op -> state.before(op), op -> state.after(op));
 294         return true;
 295     }
 296 
 297     private static int calculateDataSectionSize(DataSection ds) {
 298         int sum = 0;
 299         for (Data d : ds) {
 300             sum += d.getSize();
 301         }
 302         return sum;
 303     }
 304 
 305     @Override
 306     public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) {
 307         SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm;
 308         // TODO: (sa) Fold the two traversals into one
 309         stuffDelayedControlTransfers(lir);
 310         int constantSize = calculateConstantSize(lir);
 311         boolean canUseImmediateConstantLoad = constantSize < (1 << 13);
 312         masm.setImmediateConstantLoad(canUseImmediateConstantLoad);
 313         FrameMap frameMap = crb.frameMap;
 314         RegisterConfig regConfig = frameMap.getRegisterConfig();
 315         Label unverifiedStub = installedCodeOwner == null || installedCodeOwner.isStatic() ? null : new Label();
 316         for (int i = 0; i < 2; i++) {
 317             if (i > 0) {
 318                 crb.resetForEmittingCode();
 319                 lir.resetLabels();
 320                 resetDelayedControlTransfers(lir);
 321             }
 322 
 323             // Emit the prefix
 324             if (unverifiedStub != null) {
 325                 crb.recordMark(config.MARKID_UNVERIFIED_ENTRY);
 326                 // We need to use JavaCall here because we haven't entered the frame yet.
 327                 CallingConvention cc = regConfig.getCallingConvention(HotSpotCallingConventionType.JavaCall, null, new JavaType[]{getProviders().getMetaAccess().lookupJavaType(Object.class)}, this);
 328                 Register inlineCacheKlass = g5; // see MacroAssembler::ic_call
 329 
 330                 try (ScratchRegister sc = masm.getScratchRegister()) {
 331                     Register scratch = sc.getRegister();
 332                     Register receiver = asRegister(cc.getArgument(0));
 333                     SPARCAddress src = new SPARCAddress(receiver, config.hubOffset);
 334 
 335                     masm.ldx(src, scratch);
 336                     masm.cmp(scratch, inlineCacheKlass);
 337                 }
 338                 BPCC.emit(masm, Xcc, NotEqual, NOT_ANNUL, PREDICT_NOT_TAKEN, unverifiedStub);
 339                 masm.nop();  // delay slot
 340             }
 341 
 342             masm.align(config.codeEntryAlignment);
 343             crb.recordMark(config.MARKID_OSR_ENTRY);
 344             crb.recordMark(config.MARKID_VERIFIED_ENTRY);
 345 
 346             // Emit code for the LIR
 347             crb.emit(lir);
 348         }
 349         profileInstructions(lir, crb);
 350 
 351         HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext;
 352         HotSpotForeignCallsProvider foreignCalls = getProviders().getForeignCalls();
 353         if (!frameContext.isStub) {
 354             crb.recordMark(config.MARKID_EXCEPTION_HANDLER_ENTRY);
 355             SPARCCall.directCall(crb, masm, foreignCalls.lookupForeignCall(EXCEPTION_HANDLER), null, null);
 356             crb.recordMark(config.MARKID_DEOPT_HANDLER_ENTRY);
 357             SPARCCall.directCall(crb, masm, foreignCalls.lookupForeignCall(DEOPTIMIZATION_HANDLER), null, null);
 358         } else {
 359             // No need to emit the stubs for entries back into the method since
 360             // it has no calls that can cause such "return" entries
 361         }
 362 
 363         if (unverifiedStub != null) {
 364             masm.bind(unverifiedStub);
 365             try (ScratchRegister sc = masm.getScratchRegister()) {
 366                 Register scratch = sc.getRegister();
 367                 SPARCCall.indirectJmp(crb, masm, scratch, foreignCalls.lookupForeignCall(IC_MISS_HANDLER));
 368             }
 369         }
 370         masm.peephole();
 371     }
 372 
 373     private static int calculateConstantSize(LIR lir) {
 374         int size = 0;
 375         for (AbstractBlockBase<?> block : lir.codeEmittingOrder()) {
 376             if (block == null) {
 377                 continue;
 378             }
 379             for (LIRInstruction inst : lir.getLIRforBlock(block)) {
 380                 if (inst instanceof SPARCLIRInstructionMixin) {
 381                     SizeEstimate pred = ((SPARCLIRInstructionMixin) inst).estimateSize();
 382                     if (pred != null) {
 383                         size += pred.constantSize;
 384                     }
 385                 }
 386             }
 387         }
 388         return size;
 389     }
 390 
 391     private static void resetDelayedControlTransfers(LIR lir) {
 392         for (AbstractBlockBase<?> block : lir.codeEmittingOrder()) {
 393             if (block == null) {
 394                 continue;
 395             }
 396             for (LIRInstruction inst : lir.getLIRforBlock(block)) {
 397                 if (inst instanceof SPARCDelayedControlTransfer) {
 398                     ((SPARCDelayedControlTransfer) inst).resetState();
 399                 }
 400             }
 401         }
 402     }
 403 
 404     /**
 405      * Fix-up over whole LIR.
 406      *
 407      * @see #stuffDelayedControlTransfers(LIR, AbstractBlockBase)
 408      * @param l
 409      */
 410     private static void stuffDelayedControlTransfers(LIR l) {
 411         for (AbstractBlockBase<?> b : l.codeEmittingOrder()) {
 412             if (b != null) {
 413                 stuffDelayedControlTransfers(l, b);
 414             }
 415         }
 416     }
 417 
 418     /**
 419      * Tries to put DelayedControlTransfer instructions and DelayableLIRInstructions together. Also
 420      * it tries to move the DelayedLIRInstruction to the DelayedControlTransfer instruction, if
 421      * possible.
 422      */
 423     private static void stuffDelayedControlTransfers(LIR l, AbstractBlockBase<?> block) {
 424         List<LIRInstruction> instructions = l.getLIRforBlock(block);
 425         if (instructions.size() >= 2) {
 426             LIRDependencyAccumulator acc = new LIRDependencyAccumulator();
 427             SPARCDelayedControlTransfer delayedTransfer = null;
 428             int delayTransferPosition = -1;
 429             for (int i = instructions.size() - 1; i >= 0; i--) {
 430                 LIRInstruction inst = instructions.get(i);
 431                 boolean adjacent = delayTransferPosition - i == 1;
 432                 if (!adjacent || inst.destroysCallerSavedRegisters() || leavesRegisterWindow(inst)) {
 433                     delayedTransfer = null;
 434                 }
 435                 if (inst instanceof SPARCDelayedControlTransfer) {
 436                     delayedTransfer = (SPARCDelayedControlTransfer) inst;
 437                     acc.start(inst);
 438                     delayTransferPosition = i;
 439                 } else if (delayedTransfer != null) {
 440                     boolean overlap = acc.add(inst);
 441                     if (!overlap && inst instanceof SPARCTailDelayedLIRInstruction) {
 442                         // We have found a non overlapping LIR instruction which can be delayed
 443                         ((SPARCTailDelayedLIRInstruction) inst).setDelayedControlTransfer(delayedTransfer);
 444                         delayedTransfer = null;
 445                     }
 446                 }
 447             }
 448         }
 449     }
 450 
 451     private static boolean leavesRegisterWindow(LIRInstruction inst) {
 452         return inst instanceof SPARCLIRInstructionMixin && ((SPARCLIRInstructionMixin) inst).leavesRegisterWindow();
 453     }
 454 
 455     /**
 456      * Accumulates inputs/outputs/temp/alive in a set along we walk back the LIRInstructions and
 457      * detects, if there is any overlap. In this way LIRInstructions can be detected, which can be
 458      * moved nearer to the DelayedControlTransfer instruction.
 459      */
 460     private static class LIRDependencyAccumulator {
 461         private final Set<Object> inputs = new HashSet<>(10);
 462         private boolean overlap = false;
 463 
 464         private final InstructionValueConsumer valueConsumer = (instruction, value, mode, flags) -> {
 465             Object valueObject = value;
 466             if (isRegister(value)) { // Canonicalize registers
 467                 valueObject = asRegister(value);
 468             }
 469             if (!inputs.add(valueObject)) {
 470                 overlap = true;
 471             }
 472         };
 473 
 474         public void start(LIRInstruction initial) {
 475             inputs.clear();
 476             overlap = false;
 477             initial.visitEachInput(valueConsumer);
 478             initial.visitEachTemp(valueConsumer);
 479             initial.visitEachAlive(valueConsumer);
 480         }
 481 
 482         /**
 483          * Adds the inputs of lir instruction to the accumulator and returns, true if there was any
 484          * overlap of parameters.
 485          *
 486          * @param inst
 487          * @return true if an overlap was found
 488          */
 489         public boolean add(LIRInstruction inst) {
 490             overlap = false;
 491             inst.visitEachOutput(valueConsumer);
 492             inst.visitEachTemp(valueConsumer);
 493             inst.visitEachInput(valueConsumer);
 494             inst.visitEachAlive(valueConsumer);
 495             return overlap;
 496         }
 497     }
 498 
 499     @Override
 500     public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig) {
 501         RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
 502         return new SPARCHotSpotRegisterAllocationConfig(registerConfigNonNull);
 503     }
 504 
 505     @Override
 506     public Set<Register> translateToCallerRegisters(Set<Register> calleeRegisters) {
 507         HashSet<Register> callerRegisters = new HashSet<>(calleeRegisters.size());
 508         for (Register register : calleeRegisters) {
 509             if (l0.number <= register.number && register.number <= l7.number) {
 510                 // do nothing
 511             } else if (o0.number <= register.number && register.number <= o7.number) {
 512                 // do nothing
 513             } else if (i0.number <= register.number && register.number <= i7.number) {
 514                 // translate input to output registers
 515                 callerRegisters.add(translateInputToOutputRegister(register));
 516             } else {
 517                 callerRegisters.add(register);
 518             }
 519         }
 520         return callerRegisters;
 521     }
 522 
 523     private Register translateInputToOutputRegister(Register register) {
 524         assert i0.number <= register.number && register.number <= i7.number : "Not an input register " + register;
 525         return getTarget().arch.getRegisters().get(o0.number + register.number - i0.number);
 526     }
 527 }