# HG changeset patch # User Gilles Duboscq # Date 1367344384 -7200 # Node ID 490d283dbe90142f54681aeb1a7a3cbad39f31c5 # Parent 46e83862cc03c872f4aaf33b0cb76c229c7796ef Add Logic conjunction and disjunction and expand them before lir generation diff -r 46e83862cc03 -r 490d283dbe90 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Tue Apr 30 19:51:49 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Tue Apr 30 19:53:04 2013 +0200 @@ -34,6 +34,8 @@ addPhase(new FrameStateAssignmentPhase()); + addPhase(new ExpandLogicPhase()); + addPhase(new DeadCodeEliminationPhase()); } } diff -r 46e83862cc03 -r 490d283dbe90 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicBinaryNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicBinaryNode.java Tue Apr 30 19:53:04 2013 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013, 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.nodes; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.spi.*; + +public abstract class LogicBinaryNode extends LogicNode implements Negatable, Node.IterableNodeType { + + @Input private LogicNode x; + @Input private LogicNode y; + private boolean xNegated; + private boolean yNegated; + + public LogicBinaryNode(LogicNode x, LogicNode y) { + this(x, false, y, false); + } + + public LogicBinaryNode(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated) { + this.x = x; + this.xNegated = xNegated; + this.y = y; + this.yNegated = yNegated; + } + + public LogicNode getX() { + return x; + } + + public LogicNode getY() { + return y; + } + + public boolean isXNegated() { + return xNegated; + } + + public boolean isYNegated() { + return yNegated; + } + + @Override + public Negatable negate(LogicNode condition) { + if (condition == x) { + xNegated = !xNegated; + } + if (condition == y) { + yNegated = !yNegated; + } + return this; + } +} diff -r 46e83862cc03 -r 490d283dbe90 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConjunctionNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConjunctionNode.java Tue Apr 30 19:53:04 2013 +0200 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2013, 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.nodes; + +import com.oracle.graal.nodes.spi.*; + +/** + * This node is true if {@link #getX() x} and {@link #getY() y} are true. + * + */ +public class LogicConjunctionNode extends LogicBinaryNode implements Canonicalizable { + + public LogicConjunctionNode(LogicNode x, LogicNode y) { + this(x, false, y, false); + } + + public LogicConjunctionNode(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated) { + super(x, xNegated, y, yNegated); + } + + @Override + public LogicNode canonical(CanonicalizerTool tool) { + LogicNode x = getX(); + LogicNode y = getY(); + if (x == y) { + return x; + } + if (x instanceof LogicConstantNode) { + if (((LogicConstantNode) x).getValue() ^ isXNegated()) { + if (isYNegated()) { + negateUsages(); + } + return y; + } else { + return LogicConstantNode.contradiction(graph()); + } + } + if (y instanceof LogicConstantNode) { + if (((LogicConstantNode) y).getValue() ^ isYNegated()) { + if (isXNegated()) { + negateUsages(); + } + return x; + } else { + return LogicConstantNode.contradiction(graph()); + } + } + return this; + } +} diff -r 46e83862cc03 -r 490d283dbe90 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicDisjunctionNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicDisjunctionNode.java Tue Apr 30 19:53:04 2013 +0200 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2013, 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.nodes; + +import com.oracle.graal.nodes.spi.*; + +/** + * This node is true if {@link #getX() x} or {@link #getY() y} are true. + * + */ +public class LogicDisjunctionNode extends LogicBinaryNode implements Canonicalizable { + + public LogicDisjunctionNode(LogicNode x, LogicNode y) { + this(x, false, y, false); + } + + public LogicDisjunctionNode(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated) { + super(x, xNegated, y, yNegated); + } + + @Override + public LogicNode canonical(CanonicalizerTool tool) { + LogicNode x = getX(); + LogicNode y = getY(); + if (x == y) { + return x; + } + if (x instanceof LogicConstantNode) { + if (((LogicConstantNode) x).getValue() ^ isXNegated()) { + return LogicConstantNode.tautology(graph()); + } else { + if (isYNegated()) { + negateUsages(); + } + return y; + } + } + if (y instanceof LogicConstantNode) { + if (((LogicConstantNode) y).getValue() ^ isYNegated()) { + return LogicConstantNode.tautology(graph()); + } else { + if (isXNegated()) { + negateUsages(); + } + return x; + } + } + return this; + } + +} diff -r 46e83862cc03 -r 490d283dbe90 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java Tue Apr 30 19:53:04 2013 +0200 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2013, 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.phases.common; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.phases.*; + +public class ExpandLogicPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + for (LogicBinaryNode logic : graph.getNodes(LogicBinaryNode.class)) { + processBinary(logic); + } + } + + private static void processBinary(LogicBinaryNode binary) { + while (binary.usages().isNotEmpty()) { + Node usage = binary.usages().first(); + if (usage instanceof LogicBinaryNode) { + processBinary((LogicBinaryNode) usage); + } else if (usage instanceof IfNode) { + if (binary instanceof LogicConjunctionNode) { + processIf(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (IfNode) usage, false); + } else if (binary instanceof LogicDisjunctionNode) { + processIf(binary.getX(), !binary.isXNegated(), binary.getY(), !binary.isYNegated(), (IfNode) usage, true); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } else if (usage instanceof ConditionalNode) { + if (binary instanceof LogicConjunctionNode) { + processConditional(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (ConditionalNode) usage, false); + } else if (binary instanceof LogicDisjunctionNode) { + processConditional(binary.getX(), !binary.isXNegated(), binary.getY(), !binary.isYNegated(), (ConditionalNode) usage, true); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } + binary.safeDelete(); + } + + private static void processIf(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, IfNode ifNode, boolean negateTargets) { + AbstractBeginNode trueTarget = negateTargets ? ifNode.falseSuccessor() : ifNode.trueSuccessor(); + AbstractBeginNode falseTarget = negateTargets ? ifNode.trueSuccessor() : ifNode.falseSuccessor(); + double p = Math.sqrt(ifNode.probability(trueTarget)); + ifNode.clearSuccessors(); + Graph graph = ifNode.graph(); + MergeNode falseTargetMerge = graph.add(new MergeNode()); + falseTargetMerge.setNext(falseTarget); + EndNode firstFalseEnd = graph.add(new EndNode()); + EndNode secondFalseEnd = graph.add(new EndNode()); + falseTargetMerge.addForwardEnd(firstFalseEnd); + falseTargetMerge.addForwardEnd(secondFalseEnd); + AbstractBeginNode firstFalseTarget = AbstractBeginNode.begin(firstFalseEnd); + AbstractBeginNode secondFalseTarget = AbstractBeginNode.begin(secondFalseEnd); + AbstractBeginNode secondIf = AbstractBeginNode.begin(graph.add(new IfNode(y, yNegated ? firstFalseTarget : trueTarget, yNegated ? trueTarget : firstFalseTarget, yNegated ? 1 - p : p))); + IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondFalseTarget : secondIf, xNegated ? secondIf : secondFalseTarget, xNegated ? 1 - p : p)); + ifNode.replaceAtPredecessor(firstIf); + ifNode.safeDelete(); + } + + private static void processConditional(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, ConditionalNode conditional, boolean negateTargets) { + ValueNode trueTarget = negateTargets ? conditional.falseValue() : conditional.trueValue(); + ValueNode falseTarget = negateTargets ? conditional.trueValue() : conditional.falseValue(); + Graph graph = conditional.graph(); + ConditionalNode secondConditional = graph.unique(new ConditionalNode(y, yNegated ? falseTarget : trueTarget, yNegated ? trueTarget : falseTarget)); + ConditionalNode firstConditional = graph.unique(new ConditionalNode(x, xNegated ? falseTarget : secondConditional, xNegated ? secondConditional : falseTarget)); + conditional.replaceAndDelete(firstConditional); + } +}