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