--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java Sat Dec 08 05:04:19 2018 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java Sat Dec 08 00:56:10 2018 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -53,6 +53,18 @@
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64Shift.SAR;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64Shift.SHL;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64Shift.SHR;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VADDSD;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VADDSS;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VDIVSD;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VDIVSS;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VMULSD;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VMULSS;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VORPD;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VORPS;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VSUBSD;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VSUBSS;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VXORPD;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VXORPS;
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.BYTE;
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.DWORD;
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.PD;
@@ -84,9 +96,11 @@
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64Shift;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexGeneralPurposeRMOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexGeneralPurposeRVMOp;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexGeneralPurposeRMOp;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp;
import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
+import org.graalvm.compiler.asm.amd64.AVXKind;
import org.graalvm.compiler.asm.amd64.AVXKind.AVXSize;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.NumUtil;
@@ -110,15 +124,18 @@
import org.graalvm.compiler.lir.amd64.AMD64SignExtendOp;
import org.graalvm.compiler.lir.amd64.AMD64Unary;
import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary;
+import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary.AVXBinaryOp;
import org.graalvm.compiler.lir.amd64.vector.AMD64VectorUnary;
import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator;
import org.graalvm.compiler.lir.gen.LIRGenerator;
import jdk.vm.ci.amd64.AMD64;
+import jdk.vm.ci.amd64.AMD64.CPUFeature;
import jdk.vm.ci.amd64.AMD64Kind;
import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.RegisterValue;
+import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.meta.AllocatableValue;
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.JavaConstant;
@@ -175,6 +192,7 @@
public Variable emitNegate(Value inputVal) {
AllocatableValue input = asAllocatable(inputVal);
Variable result = getLIRGen().newVariable(LIRKind.combine(input));
+ boolean isAvx = supportAVX();
switch ((AMD64Kind) input.getPlatformKind()) {
case DWORD:
getLIRGen().append(new AMD64Unary.MOp(NEG, DWORD, result, input));
@@ -183,10 +201,20 @@
getLIRGen().append(new AMD64Unary.MOp(NEG, QWORD, result, input));
break;
case SINGLE:
- getLIRGen().append(new AMD64Binary.DataTwoOp(SSEOp.XOR, PS, result, input, JavaConstant.forFloat(Float.intBitsToFloat(0x80000000)), 16));
+ JavaConstant floatMask = JavaConstant.forFloat(Float.intBitsToFloat(0x80000000));
+ if (isAvx) {
+ getLIRGen().append(new AVXBinaryOp(VXORPS, getRegisterSize(result), result, asAllocatable(input), asAllocatable(getLIRGen().emitJavaConstant(floatMask))));
+ } else {
+ getLIRGen().append(new AMD64Binary.DataTwoOp(SSEOp.XOR, PS, result, input, floatMask, 16));
+ }
break;
case DOUBLE:
- getLIRGen().append(new AMD64Binary.DataTwoOp(SSEOp.XOR, PD, result, input, JavaConstant.forDouble(Double.longBitsToDouble(0x8000000000000000L)), 16));
+ JavaConstant doubleMask = JavaConstant.forDouble(Double.longBitsToDouble(0x8000000000000000L));
+ if (isAvx) {
+ getLIRGen().append(new AVXBinaryOp(VXORPD, getRegisterSize(result), result, asAllocatable(input), asAllocatable(getLIRGen().emitJavaConstant(doubleMask))));
+ } else {
+ getLIRGen().append(new AMD64Binary.DataTwoOp(SSEOp.XOR, PD, result, input, doubleMask, 16));
+ }
break;
default:
throw GraalError.shouldNotReachHere(input.getPlatformKind().toString());
@@ -301,6 +329,7 @@
@Override
public Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags) {
+ boolean isAvx = supportAVX();
switch ((AMD64Kind) a.getPlatformKind()) {
case DWORD:
if (isJavaConstant(b) && !setFlags) {
@@ -319,9 +348,17 @@
}
return emitBinary(resultKind, ADD, QWORD, true, a, b, setFlags);
case SINGLE:
- return emitBinary(resultKind, SSEOp.ADD, SS, true, a, b);
+ if (isAvx) {
+ return emitBinary(resultKind, VADDSS, a, b);
+ } else {
+ return emitBinary(resultKind, SSEOp.ADD, SS, true, a, b);
+ }
case DOUBLE:
- return emitBinary(resultKind, SSEOp.ADD, SD, true, a, b);
+ if (isAvx) {
+ return emitBinary(resultKind, VADDSD, a, b);
+ } else {
+ return emitBinary(resultKind, SSEOp.ADD, SD, true, a, b);
+ }
default:
throw GraalError.shouldNotReachHere();
}
@@ -329,15 +366,24 @@
@Override
public Variable emitSub(LIRKind resultKind, Value a, Value b, boolean setFlags) {
+ boolean isAvx = supportAVX();
switch ((AMD64Kind) a.getPlatformKind()) {
case DWORD:
return emitBinary(resultKind, SUB, DWORD, false, a, b, setFlags);
case QWORD:
return emitBinary(resultKind, SUB, QWORD, false, a, b, setFlags);
case SINGLE:
- return emitBinary(resultKind, SSEOp.SUB, SS, false, a, b);
+ if (isAvx) {
+ return emitBinary(resultKind, VSUBSS, a, b);
+ } else {
+ return emitBinary(resultKind, SSEOp.SUB, SS, false, a, b);
+ }
case DOUBLE:
- return emitBinary(resultKind, SSEOp.SUB, SD, false, a, b);
+ if (isAvx) {
+ return emitBinary(resultKind, VSUBSD, a, b);
+ } else {
+ return emitBinary(resultKind, SSEOp.SUB, SD, false, a, b);
+ }
default:
throw GraalError.shouldNotReachHere();
}
@@ -374,6 +420,7 @@
@Override
public Variable emitMul(Value a, Value b, boolean setFlags) {
+ boolean isAvx = supportAVX();
LIRKind resultKind = LIRKind.combine(a, b);
switch ((AMD64Kind) a.getPlatformKind()) {
case DWORD:
@@ -381,9 +428,17 @@
case QWORD:
return emitIMUL(QWORD, a, b);
case SINGLE:
- return emitBinary(resultKind, SSEOp.MUL, SS, true, a, b);
+ if (isAvx) {
+ return emitBinary(resultKind, VMULSS, a, b);
+ } else {
+ return emitBinary(resultKind, SSEOp.MUL, SS, true, a, b);
+ }
case DOUBLE:
- return emitBinary(resultKind, SSEOp.MUL, SD, true, a, b);
+ if (isAvx) {
+ return emitBinary(resultKind, VMULSD, a, b);
+ } else {
+ return emitBinary(resultKind, SSEOp.MUL, SD, true, a, b);
+ }
default:
throw GraalError.shouldNotReachHere();
}
@@ -507,6 +562,7 @@
@Override
public Value emitDiv(Value a, Value b, LIRFrameState state) {
+ boolean isAvx = supportAVX();
LIRKind resultKind = LIRKind.combine(a, b);
switch ((AMD64Kind) a.getPlatformKind()) {
case DWORD:
@@ -516,9 +572,17 @@
AMD64MulDivOp lop = emitIDIV(QWORD, a, b, state);
return getLIRGen().emitMove(lop.getQuotient());
case SINGLE:
- return emitBinary(resultKind, SSEOp.DIV, SS, false, a, b);
+ if (isAvx) {
+ return emitBinary(resultKind, VDIVSS, a, b);
+ } else {
+ return emitBinary(resultKind, SSEOp.DIV, SS, false, a, b);
+ }
case DOUBLE:
- return emitBinary(resultKind, SSEOp.DIV, SD, false, a, b);
+ if (isAvx) {
+ return emitBinary(resultKind, VDIVSD, a, b);
+ } else {
+ return emitBinary(resultKind, SSEOp.DIV, SD, false, a, b);
+ }
default:
throw GraalError.shouldNotReachHere();
}
@@ -599,6 +663,7 @@
@Override
public Variable emitOr(Value a, Value b) {
+ boolean isAvx = supportAVX();
LIRKind resultKind = LIRKind.combine(a, b);
switch ((AMD64Kind) a.getPlatformKind()) {
case DWORD:
@@ -606,9 +671,17 @@
case QWORD:
return emitBinary(resultKind, OR, QWORD, true, a, b, false);
case SINGLE:
- return emitBinary(resultKind, SSEOp.OR, PS, true, a, b);
+ if (isAvx) {
+ return emitBinary(resultKind, VORPS, a, b);
+ } else {
+ return emitBinary(resultKind, SSEOp.OR, PS, true, a, b);
+ }
case DOUBLE:
- return emitBinary(resultKind, SSEOp.OR, PD, true, a, b);
+ if (isAvx) {
+ return emitBinary(resultKind, VORPD, a, b);
+ } else {
+ return emitBinary(resultKind, SSEOp.OR, PD, true, a, b);
+ }
default:
throw GraalError.shouldNotReachHere();
}
@@ -616,6 +689,7 @@
@Override
public Variable emitXor(Value a, Value b) {
+ boolean isAvx = supportAVX();
LIRKind resultKind = LIRKind.combine(a, b);
switch ((AMD64Kind) a.getPlatformKind()) {
case DWORD:
@@ -623,9 +697,17 @@
case QWORD:
return emitBinary(resultKind, XOR, QWORD, true, a, b, false);
case SINGLE:
- return emitBinary(resultKind, SSEOp.XOR, PS, true, a, b);
+ if (isAvx) {
+ return emitBinary(resultKind, VXORPS, a, b);
+ } else {
+ return emitBinary(resultKind, SSEOp.XOR, PS, true, a, b);
+ }
case DOUBLE:
- return emitBinary(resultKind, SSEOp.XOR, PD, true, a, b);
+ if (isAvx) {
+ return emitBinary(resultKind, VXORPD, a, b);
+ } else {
+ return emitBinary(resultKind, SSEOp.XOR, PD, true, a, b);
+ }
default:
throw GraalError.shouldNotReachHere();
}
@@ -1292,4 +1374,25 @@
}
return result;
}
+
+ private boolean supportAVX() {
+ TargetDescription target = getLIRGen().target();
+ return ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX);
+ }
+
+ private static AVXSize getRegisterSize(Value a) {
+ AMD64Kind kind = (AMD64Kind) a.getPlatformKind();
+ if (kind.isXMM()) {
+ return AVXKind.getRegisterSize(kind);
+ } else {
+ return AVXSize.XMM;
+ }
+ }
+
+ private Variable emitBinary(LIRKind resultKind, VexRVMOp op, Value a, Value b) {
+ Variable result = getLIRGen().newVariable(resultKind);
+ getLIRGen().append(new AVXBinaryOp(op, getRegisterSize(result), result, asAllocatable(a), asAllocatable(b)));
+ return result;
+ }
+
}