src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64VZeroUpper.java
author dlong
Thu, 14 Nov 2019 12:21:00 -0800
changeset 59095 03fbcd06b4c0
parent 58299 6df94ce3ab2f
permissions -rw-r--r--
8233841: Update Graal Reviewed-by: kvn
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
43972
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
     1
/*
58299
6df94ce3ab2f 8229201: Update Graal
dlong
parents: 52910
diff changeset
     2
 * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
43972
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
     4
 *
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
     7
 * published by the Free Software Foundation.
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
     8
 *
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    13
 * accompanied this code).
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    14
 *
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    18
 *
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    21
 * questions.
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    22
 */
50858
2d3e99a72541 8205824: Update Graal
never
parents: 47216
diff changeset
    23
2d3e99a72541 8205824: Update Graal
never
parents: 47216
diff changeset
    24
43972
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    25
package org.graalvm.compiler.lir.amd64;
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    26
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    27
import static jdk.vm.ci.code.ValueUtil.asRegister;
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    28
import static jdk.vm.ci.code.ValueUtil.isRegister;
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    29
58299
6df94ce3ab2f 8229201: Update Graal
dlong
parents: 52910
diff changeset
    30
import java.util.ArrayList;
43972
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    31
import java.util.BitSet;
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    32
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    33
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    34
import org.graalvm.compiler.lir.LIRInstructionClass;
59095
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    35
import org.graalvm.compiler.lir.amd64.AMD64Call.ForeignCallOp;
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    36
import org.graalvm.compiler.lir.amd64.vector.AMD64VectorInstruction;
43972
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    37
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    38
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    39
import jdk.vm.ci.amd64.AMD64;
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    40
import jdk.vm.ci.code.Register;
58299
6df94ce3ab2f 8229201: Update Graal
dlong
parents: 52910
diff changeset
    41
import jdk.vm.ci.code.RegisterConfig;
43972
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    42
import jdk.vm.ci.code.RegisterValue;
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    43
import jdk.vm.ci.meta.Value;
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    44
59095
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    45
/**
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    46
 * vzeroupper is essential to avoid performance penalty during SSE-AVX transition. Specifically,
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    47
 * once we have executed instructions that modify the upper bits (i.e., 128+) of the YMM registers,
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    48
 * we need to perform vzeroupper to transit the state to 128bits before executing any SSE
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    49
 * instructions. We don't need to place vzeroupper between VEX-encoded SSE instructions and legacy
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    50
 * SSE instructions, nor between AVX instructions and VEX-encoded SSE instructions.
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    51
 *
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    52
 * When running Graal on HotSpot, we emit a vzeroupper LIR operation (i.e. an instance of this
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    53
 * class) before a foreign call to the runtime function where Graal has no knowledge. The underlying
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    54
 * reason is that HotSpot is SSE-compiled so as to support older CPUs. We also emit a vzeroupper
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    55
 * instruction (see {@code AMD64HotSpotReturnOp.emitCode}) upon returning, if the current LIR graph
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    56
 * contains LIR operations that touch the upper bits of the YMM registers, including but not limited
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    57
 * to {@link AMD64VectorInstruction}, {@link AMD64ArrayCompareToOp}, {@link AMD64ArrayEqualsOp},
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    58
 * {@link AMD64ArrayIndexOfOp}, and {@link ForeignCallOp} that invokes to Graal-compiled stubs. For
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    59
 * the last case, since Graal-compiled stubs is under our control, we don't emit vzeroupper upon
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    60
 * returning of the stub, but rather do that upon returning of the current method.
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    61
 *
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    62
 * On JDK8, C2 does not emit many vzeroupper instructions, potentially because that YMM registers
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    63
 * are not heavily employed (C2 vectorization starts using YMM registers in 9, source
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    64
 * https://cr.openjdk.java.net/~vlivanov/talks/2017_Vectorization_in_HotSpot_JVM.pdf) and thus less
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    65
 * care has been taken to place these instructions. One example is that many intrinsics employ YMM
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    66
 * registers starting from https://bugs.openjdk.java.net/browse/JDK-8005419, but does not properly
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    67
 * place vzeroupper upon returning of the intrinsic stub or the caller of the stub.
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    68
 *
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    69
 * Most vzeroupper were added in JDK 10 (https://bugs.openjdk.java.net/browse/JDK-8178811), and was
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    70
 * later restricted on Haswell Xeon due to performance regression
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    71
 * (https://bugs.openjdk.java.net/browse/JDK-8190934). The actual condition for placing vzeroupper
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    72
 * is at http://hg.openjdk.java.net/jdk/jdk/file/c7d9df2e470c/src/hotspot/cpu/x86/x86_64.ad#l428. To
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    73
 * summarize, if nmethod employs YMM registers (or intrinsics which use them, search for
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    74
 * clear_upper_avx() in opto/library_call.cpp) vzeroupper will be generated on nmethod's exit and
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    75
 * before any calls in nmethod, because even compiled nmethods can still use only SSE instructions.
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    76
 *
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    77
 * This means, if a Java method performs a call to an intrinsic that employs YMM registers,
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    78
 * C2-compiled code will place a vzeroupper before the call, upon exit of the stub and upon exit of
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    79
 * this method. Graal will only place the last, because it ensures that Graal-compiled Java method
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    80
 * and stubs will be consistent on using VEX-encoding.
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    81
 *
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    82
 * In SubstrateVM, since the whole image is compiled consistently with or without VEX encoding (the
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    83
 * later is the default behavior, see {@code NativeImageGenerator.createTarget}), there is no need
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    84
 * for vzeroupper. For dynamic compilation on a SubstrateVM image, if the image is SSE-compiled, we
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    85
 * then need vzeroupper when returning from the dynamic compiled code to the pre-built image code.
03fbcd06b4c0 8233841: Update Graal
dlong
parents: 58299
diff changeset
    86
 */
43972
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    87
public class AMD64VZeroUpper extends AMD64LIRInstruction {
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    88
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    89
    public static final LIRInstructionClass<AMD64VZeroUpper> TYPE = LIRInstructionClass.create(AMD64VZeroUpper.class);
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    90
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    91
    @Temp protected final RegisterValue[] xmmRegisters;
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    92
58299
6df94ce3ab2f 8229201: Update Graal
dlong
parents: 52910
diff changeset
    93
    public AMD64VZeroUpper(Value[] exclude, RegisterConfig registerConfig) {
43972
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    94
        super(TYPE);
58299
6df94ce3ab2f 8229201: Update Graal
dlong
parents: 52910
diff changeset
    95
        xmmRegisters = initRegisterValues(exclude, registerConfig);
43972
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    96
    }
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    97
58299
6df94ce3ab2f 8229201: Update Graal
dlong
parents: 52910
diff changeset
    98
    private static RegisterValue[] initRegisterValues(Value[] exclude, RegisterConfig registerConfig) {
43972
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
    99
        BitSet skippedRegs = new BitSet();
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
   100
        if (exclude != null) {
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
   101
            for (Value value : exclude) {
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
   102
                if (isRegister(value) && asRegister(value).getRegisterCategory().equals(AMD64.XMM)) {
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
   103
                    skippedRegs.set(asRegister(value).number);
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
   104
                }
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
   105
            }
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
   106
        }
58299
6df94ce3ab2f 8229201: Update Graal
dlong
parents: 52910
diff changeset
   107
        ArrayList<RegisterValue> regs = new ArrayList<>();
6df94ce3ab2f 8229201: Update Graal
dlong
parents: 52910
diff changeset
   108
        for (Register r : registerConfig.getCallerSaveRegisters()) {
6df94ce3ab2f 8229201: Update Graal
dlong
parents: 52910
diff changeset
   109
            if (r.getRegisterCategory().equals(AMD64.XMM) && !skippedRegs.get(r.number)) {
6df94ce3ab2f 8229201: Update Graal
dlong
parents: 52910
diff changeset
   110
                regs.add(r.asValue());
43972
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
   111
            }
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
   112
        }
58299
6df94ce3ab2f 8229201: Update Graal
dlong
parents: 52910
diff changeset
   113
        return regs.toArray(new RegisterValue[regs.size()]);
43972
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
   114
    }
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
   115
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
   116
    @Override
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
   117
    public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler asm) {
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
   118
        asm.vzeroupper();
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
   119
    }
1ade39b8381b 8174879: Rename jdk.vm.ci to jdk.internal.vm.ci
kvn
parents:
diff changeset
   120
}