1/* 2 * Copyright (c) 2009, 2016, 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 24package org.graalvm.compiler.core.amd64; 25 26import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.ADD; 27import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.AND; 28import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.OR; 29import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.SUB; 30import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.XOR; 31import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSX; 32import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSXB; 33import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSXD; 34import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.DWORD; 35import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD; 36import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SD; 37import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SS; 38 39import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; 40import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp; 41import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RRMOp; 42import org.graalvm.compiler.asm.amd64.AMD64Assembler.AVXOp; 43import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize; 44import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp; 45import org.graalvm.compiler.core.common.LIRKind; 46import org.graalvm.compiler.core.common.NumUtil; 47import org.graalvm.compiler.core.common.calc.Condition; 48import org.graalvm.compiler.core.gen.NodeLIRBuilder; 49import org.graalvm.compiler.core.gen.NodeMatchRules; 50import org.graalvm.compiler.core.match.ComplexMatchResult; 51import org.graalvm.compiler.core.match.MatchRule; 52import org.graalvm.compiler.debug.GraalError; 53import org.graalvm.compiler.lir.LIRFrameState; 54import org.graalvm.compiler.lir.LIRValueUtil; 55import org.graalvm.compiler.lir.LabelRef; 56import org.graalvm.compiler.lir.amd64.AMD64AddressValue; 57import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer; 58import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.BranchOp; 59import org.graalvm.compiler.lir.gen.LIRGeneratorTool; 60import org.graalvm.compiler.nodes.ConstantNode; 61import org.graalvm.compiler.nodes.DeoptimizingNode; 62import org.graalvm.compiler.nodes.IfNode; 63import org.graalvm.compiler.nodes.ValueNode; 64import org.graalvm.compiler.nodes.calc.CompareNode; 65import org.graalvm.compiler.nodes.calc.FloatConvertNode; 66import org.graalvm.compiler.nodes.calc.LeftShiftNode; 67import org.graalvm.compiler.nodes.calc.NarrowNode; 68import org.graalvm.compiler.nodes.calc.ReinterpretNode; 69import org.graalvm.compiler.nodes.calc.SignExtendNode; 70import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode; 71import org.graalvm.compiler.nodes.calc.ZeroExtendNode; 72import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode; 73import org.graalvm.compiler.nodes.java.ValueCompareAndSwapNode; 74import org.graalvm.compiler.nodes.memory.Access; 75import org.graalvm.compiler.nodes.memory.LIRLowerableAccess; 76import org.graalvm.compiler.nodes.memory.WriteNode; 77import org.graalvm.compiler.nodes.util.GraphUtil; 78 79import jdk.vm.ci.amd64.AMD64; 80import jdk.vm.ci.amd64.AMD64.CPUFeature; 81import jdk.vm.ci.amd64.AMD64Kind; 82import jdk.vm.ci.code.TargetDescription; 83import jdk.vm.ci.meta.AllocatableValue; 84import jdk.vm.ci.meta.JavaConstant; 85import jdk.vm.ci.meta.PlatformKind; 86import jdk.vm.ci.meta.Value; 87import jdk.vm.ci.meta.ValueKind; 88 89public class AMD64NodeMatchRules extends NodeMatchRules { 90 91 public AMD64NodeMatchRules(LIRGeneratorTool gen) { 92 super(gen); 93 } 94 95 protected LIRFrameState getState(Access access) { 96 if (access instanceof DeoptimizingNode) { 97 return state((DeoptimizingNode) access); 98 } 99 return null; 100 } 101 102 protected AMD64Kind getMemoryKind(LIRLowerableAccess access) { 103 return (AMD64Kind) getLirKind(access).getPlatformKind(); 104 } 105 106 protected LIRKind getLirKind(LIRLowerableAccess access) { 107 return gen.getLIRKind(access.getAccessStamp()); 108 } 109 110 protected OperandSize getMemorySize(LIRLowerableAccess access) { 111 switch (getMemoryKind(access)) { 112 case BYTE: 113 return OperandSize.BYTE; 114 case WORD: 115 return OperandSize.WORD; 116 case DWORD: 117 return OperandSize.DWORD; 118 case QWORD: 119 return OperandSize.QWORD; 120 case SINGLE: 121 return OperandSize.SS; 122 case DOUBLE: 123 return OperandSize.SD; 124 default: 125 throw GraalError.shouldNotReachHere("unsupported memory access type " + getMemoryKind(access)); 126 } 127 } 128 129 protected ComplexMatchResult emitCompareBranchMemory(IfNode ifNode, CompareNode compare, ValueNode value, LIRLowerableAccess access) { 130 Condition cond = compare.condition(); 131 AMD64Kind kind = getMemoryKind(access); 132 boolean matchedAsConstant = false; // For assertion checking 133 134 if (value.isConstant()) { 135 JavaConstant constant = value.asJavaConstant(); 136 if (constant != null) { 137 if (kind == AMD64Kind.QWORD && !constant.getJavaKind().isObject() && !NumUtil.isInt(constant.asLong())) { 138 // Only imm32 as long 139 return null; 140 } 141 // A QWORD that can be encoded as int can be embedded as a constant 142 matchedAsConstant = kind == AMD64Kind.QWORD && !constant.getJavaKind().isObject() && NumUtil.isInt(constant.asLong()); 143 } 144 if (kind == AMD64Kind.DWORD) { 145 // Any DWORD value should be embeddable as a constant 146 matchedAsConstant = true; 147 } 148 if (kind.isXMM()) { 149 ifNode.getDebug().log("Skipping constant compares for float kinds"); 150 return null; 151 } 152 } 153 boolean matchedAsConstantFinal = matchedAsConstant; 154 155 /* 156 * emitCompareBranchMemory expects the memory on the right, so mirror the condition if 157 * that's not true. It might be mirrored again the actual compare is emitted but that's ok. 158 */ 159 Condition finalCondition = GraphUtil.unproxify(compare.getX()) == access ? cond.mirror() : cond; 160 return new ComplexMatchResult() { 161 @Override 162 public Value evaluate(NodeLIRBuilder builder) { 163 LabelRef trueLabel = getLIRBlock(ifNode.trueSuccessor()); 164 LabelRef falseLabel = getLIRBlock(ifNode.falseSuccessor()); 165 boolean unorderedIsTrue = compare.unorderedIsTrue(); 166 double trueLabelProbability = ifNode.probability(ifNode.trueSuccessor()); 167 Value other = operand(value); 168 /* 169 * Check that patterns which were matched as a constant actually end up seeing a 170 * constant in the LIR. 171 */ 172 assert !matchedAsConstantFinal || !LIRValueUtil.isVariable(other) : "expected constant value " + value; 173 AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress()); 174 getLIRGeneratorTool().emitCompareBranchMemory(kind, other, address, getState(access), finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability); 175 return null; 176 } 177 }; 178 } 179 180 private ComplexMatchResult emitIntegerTestBranchMemory(IfNode x, ValueNode value, LIRLowerableAccess access) { 181 LabelRef trueLabel = getLIRBlock(x.trueSuccessor()); 182 LabelRef falseLabel = getLIRBlock(x.falseSuccessor()); 183 double trueLabelProbability = x.probability(x.trueSuccessor()); 184 AMD64Kind kind = getMemoryKind(access); 185 OperandSize size = kind == AMD64Kind.QWORD ? QWORD : DWORD; 186 if (value.isConstant()) { 187 JavaConstant constant = value.asJavaConstant(); 188 if (constant != null && kind == AMD64Kind.QWORD && !NumUtil.isInt(constant.asLong())) { 189 // Only imm32 as long 190 return null; 191 } 192 return builder -> { 193 AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress()); 194 gen.append(new AMD64BinaryConsumer.MemoryConstOp(AMD64MIOp.TEST, size, address, (int) constant.asLong(), getState(access))); 195 gen.append(new BranchOp(Condition.EQ, trueLabel, falseLabel, trueLabelProbability)); 196 return null; 197 }; 198 } else { 199 return builder -> { 200 AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress()); 201 gen.append(new AMD64BinaryConsumer.MemoryRMOp(AMD64RMOp.TEST, size, gen.asAllocatable(operand(value)), address, getState(access))); 202 gen.append(new BranchOp(Condition.EQ, trueLabel, falseLabel, trueLabelProbability)); 203 return null; 204 }; 205 } 206 } 207 208 protected ComplexMatchResult emitConvertMemoryOp(PlatformKind kind, AMD64RMOp op, OperandSize size, Access access, ValueKind<?> addressKind) { 209 return builder -> { 210 AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress()); 211 LIRFrameState state = getState(access); 212 if (addressKind != null) { 213 address = address.withKind(addressKind); 214 } 215 return getArithmeticLIRGenerator().emitConvertMemoryOp(kind, op, size, address, state); 216 }; 217 } 218 219 protected ComplexMatchResult emitConvertMemoryOp(PlatformKind kind, AMD64RMOp op, OperandSize size, Access access) { 220 return emitConvertMemoryOp(kind, op, size, access, null); 221 } 222 223 private ComplexMatchResult emitSignExtendMemory(Access access, int fromBits, int toBits, ValueKind<?> addressKind) { 224 assert fromBits <= toBits && toBits <= 64; 225 AMD64Kind kind = null; 226 AMD64RMOp op; 227 OperandSize size; 228 if (fromBits == toBits) { 229 return null; 230 } else if (toBits > 32) { 231 kind = AMD64Kind.QWORD; 232 size = OperandSize.QWORD; 233 // sign extend to 64 bits 234 switch (fromBits) { 235 case 8: 236 op = MOVSXB; 237 break; 238 case 16: 239 op = MOVSX; 240 break; 241 case 32: 242 op = MOVSXD; 243 break; 244 default: 245 throw GraalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)"); 246 } 247 } else { 248 kind = AMD64Kind.DWORD; 249 size = OperandSize.DWORD; 250 // sign extend to 32 bits (smaller values are internally represented as 32 bit values) 251 switch (fromBits) { 252 case 8: 253 op = MOVSXB; 254 break; 255 case 16: 256 op = MOVSX; 257 break; 258 case 32: 259 return null; 260 default: 261 throw GraalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)"); 262 } 263 } 264 if (kind != null && op != null) { 265 return emitConvertMemoryOp(kind, op, size, access, addressKind); 266 } 267 return null; 268 } 269 270 private Value emitReinterpretMemory(LIRKind to, Access access) { 271 AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress()); 272 LIRFrameState state = getState(access); 273 return getArithmeticLIRGenerator().emitLoad(to, address, state); 274 } 275 276 @MatchRule("(If (IntegerTest Read=access value))") 277 @MatchRule("(If (IntegerTest FloatingRead=access value))") 278 public ComplexMatchResult integerTestBranchMemory(IfNode root, LIRLowerableAccess access, ValueNode value) { 279 return emitIntegerTestBranchMemory(root, value, access); 280 } 281 282 @MatchRule("(If (IntegerEquals=compare value Read=access))") 283 @MatchRule("(If (IntegerLessThan=compare value Read=access))") 284 @MatchRule("(If (IntegerBelow=compare value Read=access))") 285 @MatchRule("(If (IntegerEquals=compare value FloatingRead=access))") 286 @MatchRule("(If (IntegerLessThan=compare value FloatingRead=access))") 287 @MatchRule("(If (IntegerBelow=compare value FloatingRead=access))") 288 @MatchRule("(If (FloatEquals=compare value Read=access))") 289 @MatchRule("(If (FloatEquals=compare value FloatingRead=access))") 290 @MatchRule("(If (FloatLessThan=compare value Read=access))") 291 @MatchRule("(If (FloatLessThan=compare value FloatingRead=access))") 292 @MatchRule("(If (PointerEquals=compare value Read=access))") 293 @MatchRule("(If (PointerEquals=compare value FloatingRead=access))") 294 @MatchRule("(If (ObjectEquals=compare value Read=access))") 295 @MatchRule("(If (ObjectEquals=compare value FloatingRead=access))") 296 public ComplexMatchResult ifCompareMemory(IfNode root, CompareNode compare, ValueNode value, LIRLowerableAccess access) { 297 return emitCompareBranchMemory(root, compare, value, access); 298 } 299 300 @MatchRule("(If (ObjectEquals=compare value ValueCompareAndSwap=cas))") 301 @MatchRule("(If (PointerEquals=compare value ValueCompareAndSwap=cas))") 302 @MatchRule("(If (FloatEquals=compare value ValueCompareAndSwap=cas))") 303 @MatchRule("(If (IntegerEquals=compare value ValueCompareAndSwap=cas))") 304 public ComplexMatchResult ifCompareValueCas(IfNode root, CompareNode compare, ValueNode value, ValueCompareAndSwapNode cas) { 305 assert compare.condition() == Condition.EQ; 306 if (value == cas.getExpectedValue() && cas.usages().count() == 1) { 307 return builder -> { 308 LIRKind kind = getLirKind(cas); 309 LabelRef trueLabel = getLIRBlock(root.trueSuccessor()); 310 LabelRef falseLabel = getLIRBlock(root.falseSuccessor()); 311 double trueLabelProbability = root.probability(root.trueSuccessor()); 312 Value expectedValue = operand(cas.getExpectedValue()); 313 Value newValue = operand(cas.getNewValue()); 314 AMD64AddressValue address = (AMD64AddressValue) operand(cas.getAddress()); 315 getLIRGeneratorTool().emitCompareAndSwapBranch(kind, address, expectedValue, newValue, Condition.EQ, trueLabel, falseLabel, trueLabelProbability); 316 return null; 317 }; 318 } 319 return null; 320 } 321 322 @MatchRule("(If (ObjectEquals=compare value LogicCompareAndSwap=cas))") 323 @MatchRule("(If (PointerEquals=compare value LogicCompareAndSwap=cas))") 324 @MatchRule("(If (FloatEquals=compare value LogicCompareAndSwap=cas))") 325 @MatchRule("(If (IntegerEquals=compare value LogicCompareAndSwap=cas))") 326 public ComplexMatchResult ifCompareLogicCas(IfNode root, CompareNode compare, ValueNode value, LogicCompareAndSwapNode cas) { 327 JavaConstant constant = value.asJavaConstant(); 328 assert compare.condition() == Condition.EQ; 329 if (constant != null && cas.usages().count() == 1) { 330 long constantValue = constant.asLong(); 331 boolean successIsTrue; 332 if (constantValue == 0) { 333 successIsTrue = false; 334 } else if (constantValue == 1) { 335 successIsTrue = true; 336 } else { 337 return null; 338 } 339 return builder -> { 340 LIRKind kind = getLirKind(cas); 341 LabelRef trueLabel = getLIRBlock(root.trueSuccessor()); 342 LabelRef falseLabel = getLIRBlock(root.falseSuccessor()); 343 double trueLabelProbability = root.probability(root.trueSuccessor()); 344 Value expectedValue = operand(cas.getExpectedValue()); 345 Value newValue = operand(cas.getNewValue()); 346 AMD64AddressValue address = (AMD64AddressValue) operand(cas.getAddress()); 347 Condition condition = successIsTrue ? Condition.EQ : Condition.NE; 348 getLIRGeneratorTool().emitCompareAndSwapBranch(kind, address, expectedValue, newValue, condition, trueLabel, falseLabel, trueLabelProbability); 349 return null; 350 }; 351 } 352 return null; 353 } 354 355 @MatchRule("(If (ObjectEquals=compare value FloatingRead=access))") 356 public ComplexMatchResult ifLogicCas(IfNode root, CompareNode compare, ValueNode value, LIRLowerableAccess access) { 357 return emitCompareBranchMemory(root, compare, value, access); 358 } 359 360 @MatchRule("(Or (LeftShift=lshift value Constant) (UnsignedRightShift=rshift value Constant))") 361 public ComplexMatchResult rotateLeftConstant(LeftShiftNode lshift, UnsignedRightShiftNode rshift) { 362 if ((lshift.getShiftAmountMask() & (lshift.getY().asJavaConstant().asInt() + rshift.getY().asJavaConstant().asInt())) == 0) { 363 return builder -> getArithmeticLIRGenerator().emitRol(operand(lshift.getX()), operand(lshift.getY())); 364 } 365 return null; 366 } 367 368 @MatchRule("(Or (LeftShift value (Sub Constant=delta shiftAmount)) (UnsignedRightShift value shiftAmount))") 369 public ComplexMatchResult rotateRightVariable(ValueNode value, ConstantNode delta, ValueNode shiftAmount) { 370 if (delta.asJavaConstant().asLong() == 0 || delta.asJavaConstant().asLong() == 32) { 371 return builder -> getArithmeticLIRGenerator().emitRor(operand(value), operand(shiftAmount)); 372 } 373 return null; 374 } 375 376 @MatchRule("(Or (LeftShift value shiftAmount) (UnsignedRightShift value (Sub Constant=delta shiftAmount)))") 377 public ComplexMatchResult rotateLeftVariable(ValueNode value, ValueNode shiftAmount, ConstantNode delta) { 378 if (delta.asJavaConstant().asLong() == 0 || delta.asJavaConstant().asLong() == 32) { 379 return builder -> getArithmeticLIRGenerator().emitRol(operand(value), operand(shiftAmount)); 380 } 381 return null; 382 } 383 384 private ComplexMatchResult binaryRead(AMD64RMOp op, OperandSize size, ValueNode value, LIRLowerableAccess access) { 385 return builder -> getArithmeticLIRGenerator().emitBinaryMemory(op, size, getLIRGeneratorTool().asAllocatable(operand(value)), (AMD64AddressValue) operand(access.getAddress()), 386 getState(access)); 387 } 388 389 private ComplexMatchResult binaryRead(AMD64RRMOp op, OperandSize size, ValueNode value, LIRLowerableAccess access) { 390 return builder -> getArithmeticLIRGenerator().emitBinaryMemory(op, size, getLIRGeneratorTool().asAllocatable(operand(value)), (AMD64AddressValue) operand(access.getAddress()), 391 getState(access)); 392 } 393 394 @MatchRule("(Add value Read=access)") 395 @MatchRule("(Add value FloatingRead=access)") 396 public ComplexMatchResult addMemory(ValueNode value, LIRLowerableAccess access) { 397 OperandSize size = getMemorySize(access); 398 if (size.isXmmType()) { 399 TargetDescription target = getLIRGeneratorTool().target(); 400 boolean isAvx = ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX); 401 if (isAvx) { 402 return binaryRead(AVXOp.ADD, size, value, access); 403 } else { 404 return binaryRead(SSEOp.ADD, size, value, access); 405 } 406 } else { 407 return binaryRead(ADD.getRMOpcode(size), size, value, access); 408 } 409 } 410 411 @MatchRule("(Sub value Read=access)") 412 @MatchRule("(Sub value FloatingRead=access)") 413 public ComplexMatchResult subMemory(ValueNode value, LIRLowerableAccess access) { 414 OperandSize size = getMemorySize(access); 415 if (size.isXmmType()) { 416 TargetDescription target = getLIRGeneratorTool().target(); 417 boolean isAvx = ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX); 418 if (isAvx) { 419 return binaryRead(AVXOp.SUB, size, value, access); 420 } else { 421 return binaryRead(SSEOp.SUB, size, value, access); 422 } 423 } else { 424 return binaryRead(SUB.getRMOpcode(size), size, value, access); 425 } 426 } 427 428 @MatchRule("(Mul value Read=access)") 429 @MatchRule("(Mul value FloatingRead=access)") 430 public ComplexMatchResult mulMemory(ValueNode value, LIRLowerableAccess access) { 431 OperandSize size = getMemorySize(access); 432 if (size.isXmmType()) { 433 TargetDescription target = getLIRGeneratorTool().target(); 434 boolean isAvx = ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX); 435 if (isAvx) { 436 return binaryRead(AVXOp.MUL, size, value, access); 437 } else { 438 return binaryRead(SSEOp.MUL, size, value, access); 439 } 440 } else { 441 return binaryRead(AMD64RMOp.IMUL, size, value, access); 442 } 443 } 444 445 @MatchRule("(And value Read=access)") 446 @MatchRule("(And value FloatingRead=access)") 447 public ComplexMatchResult andMemory(ValueNode value, LIRLowerableAccess access) { 448 OperandSize size = getMemorySize(access); 449 if (size.isXmmType()) { 450 return null; 451 } else { 452 return binaryRead(AND.getRMOpcode(size), size, value, access); 453 } 454 } 455 456 @MatchRule("(Or value Read=access)") 457 @MatchRule("(Or value FloatingRead=access)") 458 public ComplexMatchResult orMemory(ValueNode value, LIRLowerableAccess access) { 459 OperandSize size = getMemorySize(access); 460 if (size.isXmmType()) { 461 return null; 462 } else { 463 return binaryRead(OR.getRMOpcode(size), size, value, access); 464 } 465 } 466 467 @MatchRule("(Xor value Read=access)") 468 @MatchRule("(Xor value FloatingRead=access)") 469 public ComplexMatchResult xorMemory(ValueNode value, LIRLowerableAccess access) { 470 OperandSize size = getMemorySize(access); 471 if (size.isXmmType()) { 472 return null; 473 } else { 474 return binaryRead(XOR.getRMOpcode(size), size, value, access); 475 } 476 } 477 478 @MatchRule("(Write object Narrow=narrow)") 479 public ComplexMatchResult writeNarrow(WriteNode root, NarrowNode narrow) { 480 return builder -> { 481 LIRKind writeKind = getLIRGeneratorTool().getLIRKind(root.value().stamp()); 482 getArithmeticLIRGenerator().emitStore(writeKind, operand(root.getAddress()), operand(narrow.getValue()), state(root)); 483 return null; 484 }; 485 } 486 487 @MatchRule("(SignExtend Read=access)") 488 @MatchRule("(SignExtend FloatingRead=access)") 489 public ComplexMatchResult signExtend(SignExtendNode root, LIRLowerableAccess access) { 490 return emitSignExtendMemory(access, root.getInputBits(), root.getResultBits(), null); 491 } 492 493 @MatchRule("(ZeroExtend Read=access)") 494 @MatchRule("(ZeroExtend FloatingRead=access)") 495 public ComplexMatchResult zeroExtend(ZeroExtendNode root, LIRLowerableAccess access) { 496 AMD64Kind memoryKind = getMemoryKind(access); 497 return builder -> getArithmeticLIRGenerator().emitZeroExtendMemory(memoryKind, root.getResultBits(), (AMD64AddressValue) operand(access.getAddress()), getState(access)); 498 } 499 500 @MatchRule("(Narrow Read=access)") 501 @MatchRule("(Narrow FloatingRead=access)") 502 public ComplexMatchResult narrowRead(NarrowNode root, LIRLowerableAccess access) { 503 return new ComplexMatchResult() { 504 @Override 505 public Value evaluate(NodeLIRBuilder builder) { 506 AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress()); 507 LIRKind addressKind = LIRKind.combineDerived(getLIRGeneratorTool().getLIRKind(root.asNode().stamp()), 508 address.getBase(), address.getIndex()); 509 AMD64AddressValue newAddress = address.withKind(addressKind); 510 LIRKind readKind = getLIRGeneratorTool().getLIRKind(root.stamp()); 511 return getArithmeticLIRGenerator().emitZeroExtendMemory((AMD64Kind) readKind.getPlatformKind(), 512 root.getResultBits(), newAddress, getState(access)); 513 } 514 }; 515 } 516 517 @MatchRule("(SignExtend (Narrow=narrow Read=access))") 518 @MatchRule("(SignExtend (Narrow=narrow FloatingRead=access))") 519 public ComplexMatchResult signExtendNarrowRead(SignExtendNode root, NarrowNode narrow, LIRLowerableAccess access) { 520 LIRKind kind = getLIRGeneratorTool().getLIRKind(narrow.stamp()); 521 return emitSignExtendMemory(access, narrow.getResultBits(), root.getResultBits(), kind); 522 } 523 524 @MatchRule("(FloatConvert Read=access)") 525 @MatchRule("(FloatConvert FloatingRead=access)") 526 public ComplexMatchResult floatConvert(FloatConvertNode root, LIRLowerableAccess access) { 527 switch (root.getFloatConvert()) { 528 case D2F: 529 return emitConvertMemoryOp(AMD64Kind.SINGLE, SSEOp.CVTSD2SS, SD, access); 530 case D2I: 531 return emitConvertMemoryOp(AMD64Kind.DWORD, SSEOp.CVTTSD2SI, DWORD, access); 532 case D2L: 533 return emitConvertMemoryOp(AMD64Kind.QWORD, SSEOp.CVTTSD2SI, QWORD, access); 534 case F2D: 535 return emitConvertMemoryOp(AMD64Kind.DOUBLE, SSEOp.CVTSS2SD, SS, access); 536 case F2I: 537 return emitConvertMemoryOp(AMD64Kind.DWORD, SSEOp.CVTTSS2SI, DWORD, access); 538 case F2L: 539 return emitConvertMemoryOp(AMD64Kind.QWORD, SSEOp.CVTTSS2SI, QWORD, access); 540 case I2D: 541 return emitConvertMemoryOp(AMD64Kind.DOUBLE, SSEOp.CVTSI2SD, DWORD, access); 542 case I2F: 543 return emitConvertMemoryOp(AMD64Kind.SINGLE, SSEOp.CVTSI2SS, DWORD, access); 544 case L2D: 545 return emitConvertMemoryOp(AMD64Kind.DOUBLE, SSEOp.CVTSI2SD, QWORD, access); 546 case L2F: 547 return emitConvertMemoryOp(AMD64Kind.SINGLE, SSEOp.CVTSI2SS, QWORD, access); 548 default: 549 throw GraalError.shouldNotReachHere(); 550 } 551 } 552 553 @MatchRule("(Reinterpret Read=access)") 554 @MatchRule("(Reinterpret FloatingRead=access)") 555 public ComplexMatchResult reinterpret(ReinterpretNode root, LIRLowerableAccess access) { 556 return builder -> { 557 LIRKind kind = getLIRGeneratorTool().getLIRKind(root.stamp()); 558 return emitReinterpretMemory(kind, access); 559 }; 560 561 } 562 563 @MatchRule("(Write object Reinterpret=reinterpret)") 564 public ComplexMatchResult writeReinterpret(WriteNode root, ReinterpretNode reinterpret) { 565 return builder -> { 566 LIRKind kind = getLIRGeneratorTool().getLIRKind(reinterpret.getValue().stamp()); 567 AllocatableValue value = getLIRGeneratorTool().asAllocatable(operand(reinterpret.getValue())); 568 569 AMD64AddressValue address = (AMD64AddressValue) operand(root.getAddress()); 570 getArithmeticLIRGenerator().emitStore((AMD64Kind) kind.getPlatformKind(), address, value, getState(root)); 571 return null; 572 }; 573 } 574 575 @Override 576 public AMD64LIRGenerator getLIRGeneratorTool() { 577 return (AMD64LIRGenerator) gen; 578 } 579 580 protected AMD64ArithmeticLIRGenerator getArithmeticLIRGenerator() { 581 return (AMD64ArithmeticLIRGenerator) getLIRGeneratorTool().getArithmetic(); 582 } 583} 584