001/* 002 * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.nodes; 024 025import com.oracle.graal.graph.*; 026import com.oracle.graal.graph.spi.*; 027import com.oracle.graal.nodeinfo.*; 028 029@NodeInfo 030public final class ShortCircuitOrNode extends LogicNode implements IterableNodeType, Canonicalizable.Binary<LogicNode> { 031 032 public static final NodeClass<ShortCircuitOrNode> TYPE = NodeClass.create(ShortCircuitOrNode.class); 033 @Input(InputType.Condition) LogicNode x; 034 @Input(InputType.Condition) LogicNode y; 035 protected boolean xNegated; 036 protected boolean yNegated; 037 protected double shortCircuitProbability; 038 039 public ShortCircuitOrNode(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, double shortCircuitProbability) { 040 super(TYPE); 041 this.x = x; 042 this.xNegated = xNegated; 043 this.y = y; 044 this.yNegated = yNegated; 045 this.shortCircuitProbability = shortCircuitProbability; 046 } 047 048 public LogicNode getX() { 049 return x; 050 } 051 052 public LogicNode getY() { 053 return y; 054 } 055 056 public boolean isXNegated() { 057 return xNegated; 058 } 059 060 public boolean isYNegated() { 061 return yNegated; 062 } 063 064 /** 065 * Gets the probability that the {@link #getY() y} part of this binary node is <b>not</b> 066 * evaluated. This is the probability that this operator will short-circuit its execution. 067 */ 068 public double getShortCircuitProbability() { 069 return shortCircuitProbability; 070 } 071 072 protected ShortCircuitOrNode canonicalizeNegation(LogicNode forX, LogicNode forY) { 073 LogicNode xCond = forX; 074 boolean xNeg = xNegated; 075 while (xCond instanceof LogicNegationNode) { 076 xCond = ((LogicNegationNode) xCond).getValue(); 077 xNeg = !xNeg; 078 } 079 080 LogicNode yCond = forY; 081 boolean yNeg = yNegated; 082 while (yCond instanceof LogicNegationNode) { 083 yCond = ((LogicNegationNode) yCond).getValue(); 084 yNeg = !yNeg; 085 } 086 087 if (xCond != forX || yCond != forY) { 088 return new ShortCircuitOrNode(xCond, xNeg, yCond, yNeg, shortCircuitProbability); 089 } else { 090 return this; 091 } 092 } 093 094 public LogicNode canonical(CanonicalizerTool tool, LogicNode forX, LogicNode forY) { 095 ShortCircuitOrNode ret = canonicalizeNegation(forX, forY); 096 if (ret != this) { 097 return ret; 098 } 099 100 if (forX == forY) { 101 // @formatter:off 102 // a || a = a 103 // a || !a = true 104 // !a || a = true 105 // !a || !a = !a 106 // @formatter:on 107 if (isXNegated()) { 108 if (isYNegated()) { 109 // !a || !a = !a 110 return LogicNegationNode.create(forX); 111 } else { 112 // !a || a = true 113 return LogicConstantNode.tautology(); 114 } 115 } else { 116 if (isYNegated()) { 117 // a || !a = true 118 return LogicConstantNode.tautology(); 119 } else { 120 // a || a = a 121 return forX; 122 } 123 } 124 } 125 if (forX instanceof LogicConstantNode) { 126 if (((LogicConstantNode) forX).getValue() ^ isXNegated()) { 127 return LogicConstantNode.tautology(); 128 } else { 129 if (isYNegated()) { 130 return new LogicNegationNode(forY); 131 } else { 132 return forY; 133 } 134 } 135 } 136 if (forY instanceof LogicConstantNode) { 137 if (((LogicConstantNode) forY).getValue() ^ isYNegated()) { 138 return LogicConstantNode.tautology(); 139 } else { 140 if (isXNegated()) { 141 return new LogicNegationNode(forX); 142 } else { 143 return forX; 144 } 145 } 146 } 147 return this; 148 } 149}