# HG changeset patch # User Doug Simon # Date 1384955387 -3600 # Node ID d6b4f61ff643fe20c76e4ce1559ab30721e16d3e # Parent f8aef2693731bf871b5b4d519d77c3f61ea3c1ad# Parent c13633a4d4726d86f1f16bc9f566422d3f6c8821 Merge. diff -r f8aef2693731 -r d6b4f61ff643 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Wed Nov 20 14:49:16 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Wed Nov 20 14:49:47 2013 +0100 @@ -1874,6 +1874,7 @@ printLir("After register number assignment", true); EdgeMoveOptimizer.optimize(ir); ControlFlowOptimizer.optimize(ir); + NullCheckOptimizer.optimize(ir, target.implicitNullCheckLimit); printLir("After control flow optimization", false); } }); diff -r f8aef2693731 -r d6b4f61ff643 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Wed Nov 20 14:49:16 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Wed Nov 20 14:49:47 2013 +0100 @@ -34,7 +34,9 @@ import com.oracle.graal.asm.amd64.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.ImplicitNullCheck; import com.oracle.graal.lir.StandardOp.MoveOp; +import com.oracle.graal.lir.StandardOp.NullCheck; import com.oracle.graal.lir.asm.*; public class AMD64Move { @@ -93,7 +95,7 @@ } } - public abstract static class MemOp extends AMD64LIRInstruction { + public abstract static class MemOp extends AMD64LIRInstruction implements ImplicitNullCheck { protected final Kind kind; @Use({COMPOSITE}) protected AMD64AddressValue address; @@ -114,6 +116,14 @@ } emitMemAccess(masm); } + + public boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit) { + if (state == null && value.equals(address.base) && address.index == Value.ILLEGAL && address.displacement >= 0 && address.displacement < implicitNullCheckLimit) { + state = nullCheckState; + return true; + } + return false; + } } public static class LoadOp extends MemOp { @@ -295,7 +305,7 @@ } } - public static class NullCheckOp extends AMD64LIRInstruction { + public static class NullCheckOp extends AMD64LIRInstruction implements NullCheck { @Use({REG}) protected AllocatableValue input; @State protected LIRFrameState state; @@ -310,6 +320,14 @@ tasm.recordImplicitException(masm.codeBuffer.position(), state); masm.nullCheck(asRegister(input)); } + + public Value getCheckedValue() { + return input; + } + + public LIRFrameState getState() { + return state; + } } @Opcode("CAS") diff -r f8aef2693731 -r d6b4f61ff643 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java Wed Nov 20 14:49:16 2013 +0100 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java Wed Nov 20 14:49:47 2013 +0100 @@ -32,7 +32,9 @@ import com.oracle.graal.asm.sparc.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.ImplicitNullCheck; import com.oracle.graal.lir.StandardOp.MoveOp; +import com.oracle.graal.lir.StandardOp.NullCheck; import com.oracle.graal.lir.asm.*; public class SPARCMove { @@ -91,7 +93,7 @@ } } - public abstract static class MemOp extends SPARCLIRInstruction { + public abstract static class MemOp extends SPARCLIRInstruction implements ImplicitNullCheck { protected final Kind kind; @Use({COMPOSITE}) protected SPARCAddressValue address; @@ -112,6 +114,14 @@ } emitMemAccess(masm); } + + public boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit) { + if (state == null && value.equals(address.base) && address.index == Value.ILLEGAL && address.displacement >= 0 && address.displacement < implicitNullCheckLimit) { + state = nullCheckState; + return true; + } + return false; + } } public static class LoadOp extends MemOp { @@ -193,7 +203,7 @@ } } - public static class NullCheckOp extends SPARCLIRInstruction { + public static class NullCheckOp extends SPARCLIRInstruction implements NullCheck { @Use({REG}) protected AllocatableValue input; @State protected LIRFrameState state; @@ -208,6 +218,14 @@ tasm.recordImplicitException(masm.codeBuffer.position(), state); new Ldx(new SPARCAddress(asRegister(input), 0), r0).emit(masm); } + + public Value getCheckedValue() { + return input; + } + + public LIRFrameState getState() { + return state; + } } @Opcode("CAS") diff -r f8aef2693731 -r d6b4f61ff643 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java Wed Nov 20 14:49:47 2013 +0100 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir; + +import java.util.*; + +import com.oracle.graal.lir.StandardOp.ImplicitNullCheck; +import com.oracle.graal.lir.StandardOp.NullCheck; +import com.oracle.graal.nodes.cfg.*; + +public final class NullCheckOptimizer { + + public static void optimize(LIR ir, int implicitNullCheckLimit) { + List blocks = ir.codeEmittingOrder(); + NullCheckOptimizer.foldNullChecks(ir, blocks, implicitNullCheckLimit); + } + + private NullCheckOptimizer() { + } + + private static void foldNullChecks(LIR ir, List blocks, int implicitNullCheckLimit) { + for (Block block : blocks) { + List list = ir.lir(block); + + if (!list.isEmpty()) { + + LIRInstruction lastInstruction = list.get(0); + for (int i = 0; i < list.size(); i++) { + LIRInstruction instruction = list.get(i); + + if (instruction instanceof ImplicitNullCheck && lastInstruction instanceof NullCheck) { + NullCheck nullCheck = (NullCheck) lastInstruction; + ImplicitNullCheck implicitNullCheck = (ImplicitNullCheck) instruction; + if (implicitNullCheck.makeNullCheckFor(nullCheck.getCheckedValue(), nullCheck.getState(), implicitNullCheckLimit)) { + list.remove(i - 1); + if (i < list.size()) { + instruction = list.get(i); + } + } + } + lastInstruction = instruction; + } + } + } + } +} diff -r f8aef2693731 -r d6b4f61ff643 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Wed Nov 20 14:49:16 2013 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Wed Nov 20 14:49:47 2013 +0100 @@ -51,6 +51,16 @@ void setFallThroughTarget(LabelRef target); } + public interface NullCheck { + Value getCheckedValue(); + + LIRFrameState getState(); + } + + public interface ImplicitNullCheck { + boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit); + } + /** * LIR operation that defines the position of a label. The first operation of every block must * implement this interface.