1 /*
   2  * Copyright (c) 2009, 2020, 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 
  26 package org.graalvm.compiler.core.sparc;
  27 
  28 import static jdk.vm.ci.sparc.SPARCKind.BYTE;
  29 import static jdk.vm.ci.sparc.SPARCKind.HWORD;
  30 import static jdk.vm.ci.sparc.SPARCKind.WORD;
  31 import static jdk.vm.ci.sparc.SPARCKind.XWORD;
  32 
  33 import org.graalvm.compiler.core.common.LIRKind;
  34 import org.graalvm.compiler.core.common.calc.CanonicalCondition;
  35 import org.graalvm.compiler.core.common.calc.Condition;
  36 import org.graalvm.compiler.core.gen.NodeMatchRules;
  37 import org.graalvm.compiler.core.match.ComplexMatchResult;
  38 import org.graalvm.compiler.core.match.MatchRule;
  39 import org.graalvm.compiler.debug.GraalError;
  40 import org.graalvm.compiler.lir.LIRFrameState;
  41 import org.graalvm.compiler.lir.LabelRef;
  42 import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
  43 import org.graalvm.compiler.lir.sparc.SPARCAddressValue;
  44 import org.graalvm.compiler.nodes.DeoptimizingNode;
  45 import org.graalvm.compiler.nodes.IfNode;
  46 import org.graalvm.compiler.nodes.NodeView;
  47 import org.graalvm.compiler.nodes.ValueNode;
  48 import org.graalvm.compiler.nodes.calc.CompareNode;
  49 import org.graalvm.compiler.nodes.calc.SignExtendNode;
  50 import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
  51 import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode;
  52 import org.graalvm.compiler.nodes.memory.AddressableMemoryAccess;
  53 import org.graalvm.compiler.nodes.memory.LIRLowerableAccess;
  54 import org.graalvm.compiler.nodes.memory.MemoryAccess;
  55 
  56 import jdk.vm.ci.meta.JavaConstant;
  57 import jdk.vm.ci.meta.Value;
  58 import jdk.vm.ci.sparc.SPARCKind;
  59 
  60 /**
  61  * This class implements the SPARC specific portion of the LIR generator.
  62  */
  63 public class SPARCNodeMatchRules extends NodeMatchRules {
  64 
  65     public SPARCNodeMatchRules(LIRGeneratorTool gen) {
  66         super(gen);
  67     }
  68 
  69     protected LIRFrameState getState(MemoryAccess access) {
  70         if (access instanceof DeoptimizingNode) {
  71             return state((DeoptimizingNode) access);
  72         }
  73         return null;
  74     }
  75 
  76     protected LIRKind getLirKind(LIRLowerableAccess access) {
  77         return gen.getLIRKind(access.getAccessStamp(NodeView.DEFAULT));
  78     }
  79 
  80     private ComplexMatchResult emitSignExtendMemory(AddressableMemoryAccess access, int fromBits, int toBits) {
  81         assert fromBits <= toBits && toBits <= 64;
  82         SPARCKind toKind = null;
  83         SPARCKind fromKind = null;
  84         if (fromBits == toBits) {
  85             return null;
  86         }
  87         toKind = toBits > 32 ? XWORD : WORD;
  88         switch (fromBits) {
  89             case 8:
  90                 fromKind = BYTE;
  91                 break;
  92             case 16:
  93                 fromKind = HWORD;
  94                 break;
  95             case 32:
  96                 fromKind = WORD;
  97                 break;
  98             default:
  99                 throw GraalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)");
 100         }
 101         SPARCKind localFromKind = fromKind;
 102         SPARCKind localToKind = toKind;
 103         return builder -> {
 104             return getLIRGeneratorTool().emitSignExtendLoad(LIRKind.value(localFromKind), LIRKind.value(localToKind), operand(access.getAddress()), getState(access));
 105         };
 106     }
 107 
 108     private ComplexMatchResult emitZeroExtendMemory(AddressableMemoryAccess access, int fromBits, int toBits) {
 109         assert fromBits <= toBits && toBits <= 64;
 110         SPARCKind toKind = null;
 111         SPARCKind fromKind = null;
 112         if (fromBits == toBits) {
 113             return null;
 114         }
 115         toKind = toBits > 32 ? XWORD : WORD;
 116         switch (fromBits) {
 117             case 8:
 118                 fromKind = BYTE;
 119                 break;
 120             case 16:
 121                 fromKind = HWORD;
 122                 break;
 123             case 32:
 124                 fromKind = WORD;
 125                 break;
 126             default:
 127                 throw GraalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)");
 128         }
 129         SPARCKind localFromKind = fromKind;
 130         SPARCKind localToKind = toKind;
 131         return builder -> {
 132             // Loads are always zero extending load
 133             return getLIRGeneratorTool().emitZeroExtendLoad(LIRKind.value(localFromKind), LIRKind.value(localToKind), operand(access.getAddress()), getState(access));
 134         };
 135     }
 136 
 137     @MatchRule("(SignExtend Read=access)")
 138     @MatchRule("(SignExtend FloatingRead=access)")
 139     @MatchRule("(SignExtend VolatileRead=access)")
 140     public ComplexMatchResult signExtend(SignExtendNode root, AddressableMemoryAccess access) {
 141         return emitSignExtendMemory(access, root.getInputBits(), root.getResultBits());
 142     }
 143 
 144     @MatchRule("(ZeroExtend Read=access)")
 145     @MatchRule("(ZeroExtend FloatingRead=access)")
 146     @MatchRule("(ZeroExtend VolatileRead=access)")
 147     public ComplexMatchResult zeroExtend(ZeroExtendNode root, AddressableMemoryAccess access) {
 148         return emitZeroExtendMemory(access, root.getInputBits(), root.getResultBits());
 149     }
 150 
 151     @MatchRule("(If (ObjectEquals=compare value LogicCompareAndSwap=cas))")
 152     @MatchRule("(If (PointerEquals=compare value LogicCompareAndSwap=cas))")
 153     @MatchRule("(If (FloatEquals=compare value LogicCompareAndSwap=cas))")
 154     @MatchRule("(If (IntegerEquals=compare value LogicCompareAndSwap=cas))")
 155     public ComplexMatchResult ifCompareLogicCas(IfNode root, CompareNode compare, ValueNode value, LogicCompareAndSwapNode cas) {
 156         JavaConstant constant = value.asJavaConstant();
 157         assert compare.condition() == CanonicalCondition.EQ;
 158         if (constant != null && cas.hasExactlyOneUsage()) {
 159             long constantValue = constant.asLong();
 160             boolean successIsTrue;
 161             if (constantValue == 0) {
 162                 successIsTrue = false;
 163             } else if (constantValue == 1) {
 164                 successIsTrue = true;
 165             } else {
 166                 return null;
 167             }
 168             return builder -> {
 169                 LIRKind kind = getLirKind(cas);
 170                 LabelRef trueLabel = getLIRBlock(root.trueSuccessor());
 171                 LabelRef falseLabel = getLIRBlock(root.falseSuccessor());
 172                 double trueLabelProbability = root.probability(root.trueSuccessor());
 173                 Value expectedValue = operand(cas.getExpectedValue());
 174                 Value newValue = operand(cas.getNewValue());
 175                 SPARCAddressValue address = (SPARCAddressValue) operand(cas.getAddress());
 176                 Condition condition = successIsTrue ? Condition.EQ : Condition.NE;
 177 
 178                 Value result = getLIRGeneratorTool().emitValueCompareAndSwap(kind, address, expectedValue, newValue);
 179                 getLIRGeneratorTool().emitCompareBranch(kind.getPlatformKind(), result, expectedValue, condition, false, trueLabel, falseLabel, trueLabelProbability);
 180                 return null;
 181             };
 182         }
 183         return null;
 184     }
 185 
 186     @Override
 187     public SPARCLIRGenerator getLIRGeneratorTool() {
 188         return (SPARCLIRGenerator) super.getLIRGeneratorTool();
 189     }
 190 
 191     protected SPARCArithmeticLIRGenerator getArithmeticLIRGenerator() {
 192         return (SPARCArithmeticLIRGenerator) getLIRGeneratorTool().getArithmetic();
 193     }
 194 }