diff graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java @ 17206:2d401b9ca70d

[SPARC] Improve the lookup for delayable candidates, renaming interfaces/methods
author Stefan Anzinger <stefan.anzinger@oracle.com>
date Tue, 23 Sep 2014 12:12:26 -0700
parents 805a26002dc7
children 5a7b82c1514e
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Mon Sep 22 11:20:35 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Tue Sep 23 12:12:26 2014 -0700
@@ -53,7 +53,6 @@
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.sparc.*;
-import com.oracle.graal.lir.sparc.SPARCCall.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.sparc.*;
@@ -209,7 +208,7 @@
 
     @Override
     public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) {
-        fixupDelayedInstructions(lir);
+        stuffDelayedControlTransfers(lir);
         SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm;
         FrameMap frameMap = crb.frameMap;
         RegisterConfig regConfig = frameMap.registerConfig;
@@ -264,82 +263,105 @@
         }
     }
 
-    private static void fixupDelayedInstructions(LIR l) {
+    /**
+     * Fix-up over whole LIR.
+     *
+     * @see #stuffDelayedControlTransfers(LIR, AbstractBlock)
+     * @param l
+     */
+    private static void stuffDelayedControlTransfers(LIR l) {
         for (AbstractBlock<?> b : l.codeEmittingOrder()) {
-            fixupDelayedInstructions(l, b);
+            stuffDelayedControlTransfers(l, b);
         }
     }
 
-    private static void fixupDelayedInstructions(LIR l, AbstractBlock<?> block) {
-        TailDelayedLIRInstruction lastDelayable = null;
-        for (LIRInstruction inst : l.getLIRforBlock(block)) {
-            if (lastDelayable != null && inst instanceof DelaySlotHolder) {
-                if (isDelayable(inst, (LIRInstruction) lastDelayable)) {
-                    lastDelayable.setDelaySlotHolder((DelaySlotHolder) inst);
+    /**
+     * Tries to put DelayedControlTransfer instructions and DelayableLIRInstructions together. Also
+     * it tries to move the DelayedLIRInstruction to the DelayedControlTransfer instruction, if
+     * possible.
+     */
+    private static void stuffDelayedControlTransfers(LIR l, AbstractBlock<?> block) {
+        List<LIRInstruction> instructions = l.getLIRforBlock(block);
+        if (instructions.size() >= 2) {
+            LIRDependencyAccumulator acc = new LIRDependencyAccumulator();
+            SPARCDelayedControlTransfer delayedTransfer = null;
+            int delayTransferPosition = -1;
+            for (int i = instructions.size() - 1; i >= 0; i--) {
+                LIRInstruction inst = instructions.get(i);
+                boolean adjacent = delayTransferPosition - i == 1;
+
+                if ((!adjacent && inst.hasState()) || inst.destroysCallerSavedRegisters() || leavesRegisterWindow(inst)) {
+                    delayedTransfer = null;
                 }
-                lastDelayable = null; // We must not pull over other delay slot holder.
-            } else if (inst instanceof TailDelayedLIRInstruction) {
-                lastDelayable = (TailDelayedLIRInstruction) inst;
-            } else {
-                lastDelayable = null;
+                if (inst instanceof SPARCDelayedControlTransfer) {
+                    delayedTransfer = (SPARCDelayedControlTransfer) inst;
+                    acc.start(inst);
+                    delayTransferPosition = i;
+                } else if (delayedTransfer != null) {
+                    boolean overlap = acc.add(inst);
+                    if (inst instanceof SPARCTailDelayedLIRInstruction && !overlap) {
+                        // We have found a non overlapping LIR instruction which can be delayed
+                        ((SPARCTailDelayedLIRInstruction) inst).setDelayedControlTransfer(delayedTransfer);
+                        delayedTransfer = null;
+                        if (!adjacent) {
+                            // If not adjacent, we make it adjacent
+                            instructions.remove(i);
+                            instructions.add(delayTransferPosition - 1, inst);
+                        }
+                    }
+                }
             }
         }
     }
 
-    public static boolean isDelayable(final LIRInstruction delaySlotHolder, final LIRInstruction other) {
-        final Set<Value> delaySlotHolderInputs = new HashSet<>(2);
-        final Set<LIRFrameState> otherFrameStates = new HashSet<>(2);
-        other.forEachState(new InstructionStateProcedure() {
-            @Override
-            protected void doState(LIRInstruction instruction, LIRFrameState state) {
-                otherFrameStates.add(state);
-            }
-        });
-        int frameStatesBefore = otherFrameStates.size();
-        delaySlotHolder.forEachState(new InstructionStateProcedure() {
-            @Override
-            protected void doState(LIRInstruction instruction, LIRFrameState state) {
-                otherFrameStates.add(state);
-            }
-        });
-        if (frameStatesBefore != otherFrameStates.size() && otherFrameStates.size() >= 2) {
-            // both have framestates, the instruction is not delayable
-            return false;
-        }
-        // Direct calls do not have dependencies to data before
-        if (delaySlotHolder instanceof DirectCallOp) {
-            return true;
-        }
-        delaySlotHolder.visitEachInput(new InstructionValueConsumer() {
+    private static boolean leavesRegisterWindow(LIRInstruction inst) {
+        return inst instanceof SPARCLIRInstruction && ((SPARCLIRInstruction) inst).leavesRegisterWindow();
+    }
+
+    /**
+     * Accumulates inputs/outputs/temp/alive in a set along we walk back the LIRInstructions and
+     * detects, if there is any overlap. In this way LIRInstructions can be detected, which can be
+     * moved nearer to the DelayedControlTransfer instruction.
+     */
+    private static class LIRDependencyAccumulator {
+        private final Set<Object> inputs = new HashSet<>(10);
+        private boolean overlap = false;
+
+        private final InstructionValueConsumer valueConsumer = new InstructionValueConsumer() {
             @Override
             protected void visitValue(LIRInstruction instruction, Value value) {
-                delaySlotHolderInputs.add(value);
+                Object valueObject = value;
+                if (isRegister(value)) { // Canonicalize registers
+                    valueObject = asRegister(value);
+                }
+                if (!inputs.add(valueObject)) {
+                    overlap = true;
+                }
             }
-        });
-        delaySlotHolder.visitEachTemp(new InstructionValueConsumer() {
-            @Override
-            protected void visitValue(LIRInstruction instruction, Value value) {
-                delaySlotHolderInputs.add(value);
-            }
-        });
-        if (delaySlotHolderInputs.size() == 0) {
-            return true;
+        };
+
+        public void start(LIRInstruction initial) {
+            inputs.clear();
+            overlap = false;
+            initial.visitEachInput(valueConsumer);
+            initial.visitEachTemp(valueConsumer);
+            initial.visitEachAlive(valueConsumer);
         }
-        final Set<Value> otherOutputs = new HashSet<>();
-        other.visitEachOutput(new InstructionValueConsumer() {
-            @Override
-            protected void visitValue(LIRInstruction instruction, Value value) {
-                otherOutputs.add(value);
-            }
-        });
-        other.visitEachTemp(new InstructionValueConsumer() {
-            @Override
-            protected void visitValue(LIRInstruction instruction, Value value) {
-                otherOutputs.add(value);
-            }
-        });
-        int sizeBefore = otherOutputs.size();
-        otherOutputs.removeAll(delaySlotHolderInputs);
-        return otherOutputs.size() == sizeBefore;
+
+        /**
+         * Adds the inputs of lir instruction to the accumulator and returns, true if there was any
+         * overlap of parameters.
+         *
+         * @param inst
+         * @return true if an overlap was found
+         */
+        public boolean add(LIRInstruction inst) {
+            overlap = false;
+            inst.visitEachOutput(valueConsumer);
+            inst.visitEachTemp(valueConsumer);
+            inst.visitEachInput(valueConsumer);
+            inst.visitEachAlive(valueConsumer);
+            return overlap;
+        }
     }
 }