1 /*
   2  * Copyright (c) 2019, 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 
  24 
  25 package org.graalvm.compiler.nodes.calc;
  26 
  27 import org.graalvm.compiler.core.common.type.Stamp;
  28 import org.graalvm.compiler.graph.NodeClass;
  29 import org.graalvm.compiler.graph.spi.Canonicalizable;
  30 import org.graalvm.compiler.nodeinfo.NodeInfo;
  31 import org.graalvm.compiler.nodes.NodeView;
  32 import org.graalvm.compiler.nodes.ValueNode;
  33 
  34 /**
  35  * The {@code TernaryNode} class is the base of arithmetic and logic operations with three inputs.
  36  */
  37 @NodeInfo
  38 public abstract class TernaryNode extends FloatingNode implements Canonicalizable.Ternary<ValueNode> {
  39 
  40     public static final NodeClass<TernaryNode> TYPE = NodeClass.create(TernaryNode.class);
  41     @Input protected ValueNode x;
  42     @Input protected ValueNode y;
  43     @Input protected ValueNode z;
  44 
  45     @Override
  46     public ValueNode getX() {
  47         return x;
  48     }
  49 
  50     @Override
  51     public ValueNode getY() {
  52         return y;
  53     }
  54 
  55     @Override
  56     public ValueNode getZ() {
  57         return z;
  58     }
  59 
  60     public void setX(ValueNode x) {
  61         updateUsages(this.x, x);
  62         this.x = x;
  63     }
  64 
  65     public void setY(ValueNode y) {
  66         updateUsages(this.y, y);
  67         this.y = y;
  68     }
  69 
  70     public void setZ(ValueNode z) {
  71         updateUsages(this.z, z);
  72         this.z = z;
  73     }
  74 
  75     /**
  76      * Creates a new TernaryNode instance.
  77      *
  78      * @param stamp the result type of this instruction
  79      * @param x the first input instruction
  80      * @param y the second input instruction
  81      * @param z the second input instruction
  82      */
  83     protected TernaryNode(NodeClass<? extends TernaryNode> c, Stamp stamp, ValueNode x, ValueNode y, ValueNode z) {
  84         super(c, stamp);
  85         this.x = x;
  86         this.y = y;
  87         this.z = z;
  88     }
  89 
  90     @Override
  91     public boolean inferStamp() {
  92         return updateStamp(foldStamp(getX().stamp(NodeView.DEFAULT), getY().stamp(NodeView.DEFAULT), getZ().stamp(NodeView.DEFAULT)));
  93     }
  94 
  95     /**
  96      * Compute an improved stamp for this node using the passed in stamps. The stamps must be
  97      * compatible with the current values of {@link #x}, {@link #y} and {@link #z}. This code is
  98      * used to provide the default implementation of {@link #inferStamp()} and may be used by
  99      * external optimizations.
 100      *
 101      * @param stampX
 102      * @param stampY
 103      * @param stampZ
 104      */
 105     public abstract Stamp foldStamp(Stamp stampX, Stamp stampY, Stamp stampZ);
 106 }