1 /*
   2  * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2017, Red Hat Inc. All rights reserved.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 
  26 
  27 package org.graalvm.compiler.core.aarch64;
  28 
  29 import jdk.vm.ci.aarch64.AArch64Kind;
  30 
  31 import org.graalvm.compiler.core.common.type.IntegerStamp;
  32 import org.graalvm.compiler.core.common.type.Stamp;
  33 import org.graalvm.compiler.graph.NodeClass;
  34 import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
  35 import org.graalvm.compiler.nodeinfo.NodeInfo;
  36 import org.graalvm.compiler.nodes.FrameState;
  37 import org.graalvm.compiler.nodes.NodeView;
  38 import org.graalvm.compiler.nodes.StructuredGraph;
  39 import org.graalvm.compiler.nodes.ValueNode;
  40 import org.graalvm.compiler.nodes.calc.SignExtendNode;
  41 import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
  42 import org.graalvm.compiler.nodes.extended.GuardingNode;
  43 import org.graalvm.compiler.nodes.memory.ReadNode;
  44 import org.graalvm.compiler.nodes.memory.address.AddressNode;
  45 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
  46 import jdk.internal.vm.compiler.word.LocationIdentity;
  47 
  48 /**
  49  * AArch64-specific subclass of ReadNode that knows how to merge ZeroExtend and SignExtend into the
  50  * read.
  51  */
  52 
  53 @NodeInfo
  54 public class AArch64ReadNode extends ReadNode {
  55     public static final NodeClass<AArch64ReadNode> TYPE = NodeClass.create(AArch64ReadNode.class);
  56     private final IntegerStamp accessStamp;
  57     private final boolean isSigned;
  58 
  59     public AArch64ReadNode(AddressNode address, LocationIdentity location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck,
  60                     FrameState stateBefore, IntegerStamp accessStamp, boolean isSigned) {
  61         super(TYPE, address, location, stamp, guard, barrierType, nullCheck, stateBefore);
  62         this.accessStamp = accessStamp;
  63         this.isSigned = isSigned;
  64     }
  65 
  66     @Override
  67     public void generate(NodeLIRBuilderTool gen) {
  68         AArch64LIRGenerator lirgen = (AArch64LIRGenerator) gen.getLIRGeneratorTool();
  69         AArch64ArithmeticLIRGenerator arithgen = (AArch64ArithmeticLIRGenerator) lirgen.getArithmetic();
  70         AArch64Kind readKind = (AArch64Kind) lirgen.getLIRKind(accessStamp).getPlatformKind();
  71         int resultBits = ((IntegerStamp) stamp(NodeView.DEFAULT)).getBits();
  72         gen.setResult(this, arithgen.emitExtendMemory(isSigned, readKind, resultBits, (AArch64AddressValue) gen.operand(getAddress()), gen.state(this)));
  73     }
  74 
  75     /**
  76      * replace a ReadNode with an AArch64-specific variant which knows how to merge a downstream
  77      * zero or sign extend into the read operation.
  78      *
  79      * @param readNode
  80      */
  81     public static void replace(ReadNode readNode) {
  82         assert readNode.getUsageCount() == 1;
  83         assert readNode.usages().first() instanceof ZeroExtendNode || readNode.usages().first() instanceof SignExtendNode;
  84 
  85         ValueNode usage = (ValueNode) readNode.usages().first();
  86         boolean isSigned = usage instanceof SignExtendNode;
  87         IntegerStamp accessStamp = ((IntegerStamp) readNode.getAccessStamp());
  88 
  89         AddressNode address = readNode.getAddress();
  90         LocationIdentity location = readNode.getLocationIdentity();
  91         Stamp stamp = usage.stamp(NodeView.DEFAULT);
  92         GuardingNode guard = readNode.getGuard();
  93         BarrierType barrierType = readNode.getBarrierType();
  94         boolean nullCheck = readNode.getNullCheck();
  95         FrameState stateBefore = readNode.stateBefore();
  96         AArch64ReadNode clone = new AArch64ReadNode(address, location, stamp, guard, barrierType, nullCheck, stateBefore, accessStamp, isSigned);
  97         StructuredGraph graph = readNode.graph();
  98         graph.add(clone);
  99         // splice out the extend node
 100         usage.replaceAtUsagesAndDelete(readNode);
 101         // swap the clone for the read
 102         graph.replaceFixedWithFixed(readNode, clone);
 103     }
 104 }