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 }