src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayCompareToOp.java
author dlong
Mon, 18 Jun 2018 09:48:22 -0700
changeset 50609 bf414874c28f
parent 49873 26ebfe8ce852
child 50858 2d3e99a72541
permissions -rw-r--r--
8204231: Update Graal Reviewed-by: kvn
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
49451
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
     1
/*
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
     2
 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
     4
 *
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
     7
 * published by the Free Software Foundation.
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
     8
 *
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    13
 * accompanied this code).
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    14
 *
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    18
 *
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    21
 * questions.
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    22
 */
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    23
package org.graalvm.compiler.lir.amd64;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    24
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    25
import static jdk.vm.ci.amd64.AMD64.k7;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    26
import static jdk.vm.ci.amd64.AMD64.rax;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    27
import static jdk.vm.ci.amd64.AMD64.rcx;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    28
import static jdk.vm.ci.amd64.AMD64.rdx;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    29
import static jdk.vm.ci.code.ValueUtil.asRegister;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    30
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    31
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    32
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    33
import java.lang.reflect.Array;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    34
import java.lang.reflect.Field;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    35
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    36
import org.graalvm.compiler.asm.Label;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    37
import org.graalvm.compiler.asm.amd64.AMD64Address;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    38
import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    39
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AvxVectorLen;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    40
import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    41
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    42
import org.graalvm.compiler.core.common.LIRKind;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    43
import org.graalvm.compiler.lir.LIRInstructionClass;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    44
import org.graalvm.compiler.lir.Opcode;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    45
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    46
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    47
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    48
import jdk.vm.ci.amd64.AMD64;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    49
import jdk.vm.ci.amd64.AMD64.CPUFeature;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    50
import jdk.vm.ci.amd64.AMD64Kind;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    51
import jdk.vm.ci.code.Register;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    52
import jdk.vm.ci.code.TargetDescription;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    53
import jdk.vm.ci.meta.JavaKind;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    54
import jdk.vm.ci.meta.Value;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    55
import sun.misc.Unsafe;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    56
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    57
/**
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    58
 * Emits code which compares two arrays lexicographically. If the CPU supports any vector
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    59
 * instructions specialized code is emitted to leverage these instructions.
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    60
 */
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    61
@Opcode("ARRAY_COMPARE_TO")
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    62
public final class AMD64ArrayCompareToOp extends AMD64LIRInstruction {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    63
    public static final LIRInstructionClass<AMD64ArrayCompareToOp> TYPE = LIRInstructionClass.create(AMD64ArrayCompareToOp.class);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    64
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    65
    private final JavaKind kind1;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    66
    private final JavaKind kind2;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    67
    private final int array1BaseOffset;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    68
    private final int array2BaseOffset;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    69
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    70
    @Def({REG}) protected Value resultValue;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    71
    @Alive({REG}) protected Value array1Value;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    72
    @Alive({REG}) protected Value array2Value;
49873
26ebfe8ce852 8199755: Update Graal
dlong
parents: 49451
diff changeset
    73
    @Use({REG}) protected Value length1Value;
26ebfe8ce852 8199755: Update Graal
dlong
parents: 49451
diff changeset
    74
    @Use({REG}) protected Value length2Value;
26ebfe8ce852 8199755: Update Graal
dlong
parents: 49451
diff changeset
    75
    @Temp({REG}) protected Value length1ValueTemp;
26ebfe8ce852 8199755: Update Graal
dlong
parents: 49451
diff changeset
    76
    @Temp({REG}) protected Value length2ValueTemp;
49451
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    77
    @Temp({REG}) protected Value temp1;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    78
    @Temp({REG}) protected Value temp2;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    79
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    80
    @Temp({REG, ILLEGAL}) protected Value vectorTemp1;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    81
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    82
    public AMD64ArrayCompareToOp(LIRGeneratorTool tool, JavaKind kind1, JavaKind kind2, Value result, Value array1, Value array2, Value length1, Value length2) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    83
        super(TYPE);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    84
        this.kind1 = kind1;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    85
        this.kind2 = kind2;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    86
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    87
        // Both offsets should be the same but better be safe than sorry.
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    88
        Class<?> array1Class = Array.newInstance(kind1.toJavaClass(), 0).getClass();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    89
        Class<?> array2Class = Array.newInstance(kind2.toJavaClass(), 0).getClass();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    90
        this.array1BaseOffset = UNSAFE.arrayBaseOffset(array1Class);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    91
        this.array2BaseOffset = UNSAFE.arrayBaseOffset(array2Class);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    92
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    93
        this.resultValue = result;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    94
        this.array1Value = array1;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
    95
        this.array2Value = array2;
49873
26ebfe8ce852 8199755: Update Graal
dlong
parents: 49451
diff changeset
    96
        /*
26ebfe8ce852 8199755: Update Graal
dlong
parents: 49451
diff changeset
    97
         * The length values are inputs but are also killed like temporaries so need both Use and
26ebfe8ce852 8199755: Update Graal
dlong
parents: 49451
diff changeset
    98
         * Temp annotations, which will only work with fixed registers.
26ebfe8ce852 8199755: Update Graal
dlong
parents: 49451
diff changeset
    99
         */
49451
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   100
        this.length1Value = length1;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   101
        this.length2Value = length2;
49873
26ebfe8ce852 8199755: Update Graal
dlong
parents: 49451
diff changeset
   102
        this.length1ValueTemp = length1;
26ebfe8ce852 8199755: Update Graal
dlong
parents: 49451
diff changeset
   103
        this.length2ValueTemp = length2;
49451
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   104
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   105
        // Allocate some temporaries.
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   106
        this.temp1 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   107
        this.temp2 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   108
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   109
        // We only need the vector temporaries if we generate SSE code.
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   110
        if (supportsSSE42(tool.target())) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   111
            this.vectorTemp1 = tool.newVariable(LIRKind.value(AMD64Kind.DOUBLE));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   112
        } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   113
            this.vectorTemp1 = Value.ILLEGAL;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   114
        }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   115
    }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   116
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   117
    private static boolean supportsSSE42(TargetDescription target) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   118
        AMD64 arch = (AMD64) target.arch;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   119
        return arch.getFeatures().contains(CPUFeature.SSE4_2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   120
    }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   121
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   122
    private static boolean supportsAVX2(TargetDescription target) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   123
        AMD64 arch = (AMD64) target.arch;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   124
        return arch.getFeatures().contains(CPUFeature.AVX2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   125
    }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   126
50609
bf414874c28f 8204231: Update Graal
dlong
parents: 49873
diff changeset
   127
    private static boolean supportsAVX512VLBW(@SuppressWarnings("unused") TargetDescription target) {
bf414874c28f 8204231: Update Graal
dlong
parents: 49873
diff changeset
   128
        // TODO Add EVEX encoder in our assembler.
bf414874c28f 8204231: Update Graal
dlong
parents: 49873
diff changeset
   129
        return false;
49451
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   130
    }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   131
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   132
    @Override
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   133
    public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   134
        Register result = asRegister(resultValue);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   135
        Register str1 = asRegister(temp1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   136
        Register str2 = asRegister(temp2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   137
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   138
        // Load array base addresses.
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   139
        masm.leaq(str1, new AMD64Address(asRegister(array1Value), array1BaseOffset));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   140
        masm.leaq(str2, new AMD64Address(asRegister(array2Value), array2BaseOffset));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   141
        Register cnt1 = asRegister(length1Value);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   142
        Register cnt2 = asRegister(length2Value);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   143
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   144
        // Checkstyle: stop
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   145
        Label LENGTH_DIFF_LABEL = new Label();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   146
        Label POP_LABEL = new Label();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   147
        Label DONE_LABEL = new Label();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   148
        Label WHILE_HEAD_LABEL = new Label();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   149
        Label COMPARE_WIDE_VECTORS_LOOP_FAILED = new Label(); // used only _LP64 && AVX3
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   150
        int stride, stride2;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   151
        int adr_stride = -1;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   152
        int adr_stride1 = -1;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   153
        int adr_stride2 = -1;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   154
        // Checkstyle: resume
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   155
        int stride2x2 = 0x40;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   156
        AMD64Address.Scale scale = null;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   157
        AMD64Address.Scale scale1 = null;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   158
        AMD64Address.Scale scale2 = null;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   159
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   160
        // if (ae != StrIntrinsicNode::LL) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   161
        if (kind1 == JavaKind.Byte && kind2 == JavaKind.Byte) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   162
            stride2x2 = 0x20;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   163
        }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   164
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   165
        // if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   166
        if (kind1 != kind2) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   167
            masm.shrl(cnt2, 1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   168
        }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   169
        // Compute the minimum of the string lengths and the
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   170
        // difference of the string lengths (stack).
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   171
        // Do the conditional move stuff
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   172
        masm.movl(result, cnt1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   173
        masm.subl(cnt1, cnt2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   174
        masm.push(cnt1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   175
        masm.cmovl(ConditionFlag.LessEqual, cnt2, result);    // cnt2 = min(cnt1, cnt2)
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   176
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   177
        // Is the minimum length zero?
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   178
        masm.testl(cnt2, cnt2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   179
        masm.jcc(ConditionFlag.Zero, LENGTH_DIFF_LABEL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   180
        // if (ae == StrIntrinsicNode::LL) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   181
        if (kind1 == JavaKind.Byte && kind2 == JavaKind.Byte) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   182
            // Load first bytes
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   183
            masm.movzbl(result, new AMD64Address(str1, 0));  // result = str1[0]
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   184
            masm.movzbl(cnt1, new AMD64Address(str2, 0));    // cnt1 = str2[0]
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   185
            // } else if (ae == StrIntrinsicNode::UU) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   186
        } else if (kind1 == JavaKind.Char && kind2 == JavaKind.Char) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   187
            // Load first characters
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   188
            masm.movzwl(result, new AMD64Address(str1, 0));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   189
            masm.movzwl(cnt1, new AMD64Address(str2, 0));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   190
        } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   191
            masm.movzbl(result, new AMD64Address(str1, 0));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   192
            masm.movzwl(cnt1, new AMD64Address(str2, 0));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   193
        }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   194
        masm.subl(result, cnt1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   195
        masm.jcc(ConditionFlag.NotZero, POP_LABEL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   196
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   197
        // if (ae == StrIntrinsicNode::UU) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   198
        if (kind1 == JavaKind.Char && kind2 == JavaKind.Char) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   199
            // Divide length by 2 to get number of chars
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   200
            masm.shrl(cnt2, 1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   201
        }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   202
        masm.cmpl(cnt2, 1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   203
        masm.jcc(ConditionFlag.Equal, LENGTH_DIFF_LABEL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   204
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   205
        // Check if the strings start at the same location and setup scale and stride
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   206
        // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   207
        if (kind1 == kind2) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   208
            masm.cmpptr(str1, str2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   209
            masm.jcc(ConditionFlag.Equal, LENGTH_DIFF_LABEL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   210
            // if (ae == StrIntrinsicNode::LL) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   211
            if (kind1 == JavaKind.Byte && kind2 == JavaKind.Byte) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   212
                scale = AMD64Address.Scale.Times1;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   213
                stride = 16;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   214
            } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   215
                scale = AMD64Address.Scale.Times2;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   216
                stride = 8;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   217
            }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   218
        } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   219
            scale1 = AMD64Address.Scale.Times1;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   220
            scale2 = AMD64Address.Scale.Times2;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   221
            // scale not used
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   222
            stride = 8;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   223
        }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   224
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   225
        // if (UseAVX >= 2 && UseSSE42Intrinsics) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   226
        if (supportsAVX2(crb.target) && supportsSSE42(crb.target)) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   227
            Register vec1 = asRegister(vectorTemp1, AMD64Kind.DOUBLE);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   228
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   229
            // Checkstyle: stop
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   230
            Label COMPARE_WIDE_VECTORS = new Label();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   231
            Label VECTOR_NOT_EQUAL = new Label();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   232
            Label COMPARE_WIDE_TAIL = new Label();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   233
            Label COMPARE_SMALL_STR = new Label();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   234
            Label COMPARE_WIDE_VECTORS_LOOP = new Label();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   235
            Label COMPARE_16_CHARS = new Label();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   236
            Label COMPARE_INDEX_CHAR = new Label();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   237
            Label COMPARE_WIDE_VECTORS_LOOP_AVX2 = new Label();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   238
            Label COMPARE_TAIL_LONG = new Label();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   239
            Label COMPARE_WIDE_VECTORS_LOOP_AVX3 = new Label();  // used only _LP64 && AVX3
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   240
            // Checkstyle: resume
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   241
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   242
            int pcmpmask = 0x19;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   243
            // if (ae == StrIntrinsicNode::LL) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   244
            if (kind1 == JavaKind.Byte && kind2 == JavaKind.Byte) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   245
                pcmpmask &= ~0x01;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   246
            }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   247
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   248
            // Setup to compare 16-chars (32-bytes) vectors,
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   249
            // start from first character again because it has aligned address.
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   250
            // if (ae == StrIntrinsicNode::LL) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   251
            if (kind1 == JavaKind.Byte && kind2 == JavaKind.Byte) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   252
                stride2 = 32;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   253
            } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   254
                stride2 = 16;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   255
            }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   256
            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   257
            if (kind1 == kind2) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   258
                adr_stride = stride << scale.log2;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   259
            } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   260
                adr_stride1 = 8;  // stride << scale1;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   261
                adr_stride2 = 16; // stride << scale2;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   262
            }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   263
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   264
            assert result.equals(rax) && cnt2.equals(rdx) && cnt1.equals(rcx) : "pcmpestri";
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   265
            // rax and rdx are used by pcmpestri as elements counters
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   266
            masm.movl(result, cnt2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   267
            masm.andl(cnt2, ~(stride2 - 1));   // cnt2 holds the vector count
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   268
            masm.jcc(ConditionFlag.Zero, COMPARE_TAIL_LONG);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   269
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   270
            // fast path : compare first 2 8-char vectors.
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   271
            masm.bind(COMPARE_16_CHARS);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   272
            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   273
            if (kind1 == kind2) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   274
                masm.movdqu(vec1, new AMD64Address(str1, 0));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   275
            } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   276
                masm.pmovzxbw(vec1, new AMD64Address(str1, 0));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   277
            }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   278
            masm.pcmpestri(vec1, new AMD64Address(str2, 0), pcmpmask);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   279
            masm.jccb(ConditionFlag.Below, COMPARE_INDEX_CHAR);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   280
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   281
            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   282
            if (kind1 == kind2) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   283
                masm.movdqu(vec1, new AMD64Address(str1, adr_stride));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   284
                masm.pcmpestri(vec1, new AMD64Address(str2, adr_stride), pcmpmask);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   285
            } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   286
                masm.pmovzxbw(vec1, new AMD64Address(str1, adr_stride1));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   287
                masm.pcmpestri(vec1, new AMD64Address(str2, adr_stride2), pcmpmask);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   288
            }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   289
            masm.jccb(ConditionFlag.AboveEqual, COMPARE_WIDE_VECTORS);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   290
            masm.addl(cnt1, stride);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   291
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   292
            // Compare the characters at index in cnt1
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   293
            masm.bind(COMPARE_INDEX_CHAR); // cnt1 has the offset of the mismatching character
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   294
            loadNextElements(masm, result, cnt2, str1, str2, scale, scale1, scale2, cnt1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   295
            masm.subl(result, cnt2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   296
            masm.jmp(POP_LABEL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   297
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   298
            // Setup the registers to start vector comparison loop
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   299
            masm.bind(COMPARE_WIDE_VECTORS);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   300
            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   301
            if (kind1 == kind2) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   302
                masm.leaq(str1, new AMD64Address(str1, result, scale));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   303
                masm.leaq(str2, new AMD64Address(str2, result, scale));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   304
            } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   305
                masm.leaq(str1, new AMD64Address(str1, result, scale1));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   306
                masm.leaq(str2, new AMD64Address(str2, result, scale2));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   307
            }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   308
            masm.subl(result, stride2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   309
            masm.subl(cnt2, stride2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   310
            masm.jcc(ConditionFlag.Zero, COMPARE_WIDE_TAIL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   311
            masm.negq(result);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   312
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   313
            // In a loop, compare 16-chars (32-bytes) at once using (vpxor+vptest)
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   314
            masm.bind(COMPARE_WIDE_VECTORS_LOOP);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   315
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   316
            // if (VM_Version::supports_avx512vlbw()) { // trying 64 bytes fast loop
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   317
            if (supportsAVX512VLBW(crb.target)) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   318
                masm.cmpl(cnt2, stride2x2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   319
                masm.jccb(ConditionFlag.Below, COMPARE_WIDE_VECTORS_LOOP_AVX2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   320
                masm.testl(cnt2, stride2x2 - 1);   // cnt2 holds the vector count
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   321
                // means we cannot subtract by 0x40
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   322
                masm.jccb(ConditionFlag.NotZero, COMPARE_WIDE_VECTORS_LOOP_AVX2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   323
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   324
                masm.bind(COMPARE_WIDE_VECTORS_LOOP_AVX3); // the hottest loop
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   325
                // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   326
                if (kind1 == kind2) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   327
                    masm.evmovdquq(vec1, new AMD64Address(str1, result, scale), AvxVectorLen.AVX_512bit);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   328
                    // k7 == 11..11, if operands equal, otherwise k7 has some 0
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   329
                    masm.evpcmpeqb(k7, vec1, new AMD64Address(str2, result, scale), AvxVectorLen.AVX_512bit);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   330
                } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   331
                    masm.vpmovzxbw(vec1, new AMD64Address(str1, result, scale1), AvxVectorLen.AVX_512bit);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   332
                    // k7 == 11..11, if operands equal, otherwise k7 has some 0
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   333
                    masm.evpcmpeqb(k7, vec1, new AMD64Address(str2, result, scale2), AvxVectorLen.AVX_512bit);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   334
                }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   335
                masm.kortestql(k7, k7);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   336
                masm.jcc(ConditionFlag.AboveEqual, COMPARE_WIDE_VECTORS_LOOP_FAILED);     // miscompare
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   337
                masm.addq(result, stride2x2);  // update since we already compared at this addr
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   338
                masm.subl(cnt2, stride2x2);      // and sub the size too
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   339
                masm.jccb(ConditionFlag.NotZero, COMPARE_WIDE_VECTORS_LOOP_AVX3);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   340
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   341
                masm.vpxor(vec1, vec1, vec1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   342
                masm.jmpb(COMPARE_WIDE_TAIL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   343
            }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   344
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   345
            masm.bind(COMPARE_WIDE_VECTORS_LOOP_AVX2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   346
            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   347
            if (kind1 == kind2) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   348
                masm.vmovdqu(vec1, new AMD64Address(str1, result, scale));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   349
                masm.vpxor(vec1, vec1, new AMD64Address(str2, result, scale));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   350
            } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   351
                masm.vpmovzxbw(vec1, new AMD64Address(str1, result, scale1), AvxVectorLen.AVX_256bit);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   352
                masm.vpxor(vec1, vec1, new AMD64Address(str2, result, scale2));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   353
            }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   354
            masm.vptest(vec1, vec1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   355
            masm.jcc(ConditionFlag.NotZero, VECTOR_NOT_EQUAL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   356
            masm.addq(result, stride2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   357
            masm.subl(cnt2, stride2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   358
            masm.jcc(ConditionFlag.NotZero, COMPARE_WIDE_VECTORS_LOOP);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   359
            // clean upper bits of YMM registers
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   360
            masm.vpxor(vec1, vec1, vec1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   361
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   362
            // compare wide vectors tail
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   363
            masm.bind(COMPARE_WIDE_TAIL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   364
            masm.testq(result, result);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   365
            masm.jcc(ConditionFlag.Zero, LENGTH_DIFF_LABEL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   366
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   367
            masm.movl(result, stride2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   368
            masm.movl(cnt2, result);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   369
            masm.negq(result);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   370
            masm.jmp(COMPARE_WIDE_VECTORS_LOOP_AVX2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   371
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   372
            // Identifies the mismatching (higher or lower)16-bytes in the 32-byte vectors.
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   373
            masm.bind(VECTOR_NOT_EQUAL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   374
            // clean upper bits of YMM registers
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   375
            masm.vpxor(vec1, vec1, vec1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   376
            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   377
            if (kind1 == kind2) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   378
                masm.leaq(str1, new AMD64Address(str1, result, scale));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   379
                masm.leaq(str2, new AMD64Address(str2, result, scale));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   380
            } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   381
                masm.leaq(str1, new AMD64Address(str1, result, scale1));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   382
                masm.leaq(str2, new AMD64Address(str2, result, scale2));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   383
            }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   384
            masm.jmp(COMPARE_16_CHARS);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   385
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   386
            // Compare tail chars, length between 1 to 15 chars
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   387
            masm.bind(COMPARE_TAIL_LONG);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   388
            masm.movl(cnt2, result);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   389
            masm.cmpl(cnt2, stride);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   390
            masm.jcc(ConditionFlag.Less, COMPARE_SMALL_STR);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   391
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   392
            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   393
            if (kind1 == kind2) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   394
                masm.movdqu(vec1, new AMD64Address(str1, 0));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   395
            } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   396
                masm.pmovzxbw(vec1, new AMD64Address(str1, 0));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   397
            }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   398
            masm.pcmpestri(vec1, new AMD64Address(str2, 0), pcmpmask);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   399
            masm.jcc(ConditionFlag.Below, COMPARE_INDEX_CHAR);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   400
            masm.subq(cnt2, stride);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   401
            masm.jcc(ConditionFlag.Zero, LENGTH_DIFF_LABEL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   402
            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   403
            if (kind1 == kind2) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   404
                masm.leaq(str1, new AMD64Address(str1, result, scale));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   405
                masm.leaq(str2, new AMD64Address(str2, result, scale));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   406
            } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   407
                masm.leaq(str1, new AMD64Address(str1, result, scale1));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   408
                masm.leaq(str2, new AMD64Address(str2, result, scale2));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   409
            }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   410
            masm.negq(cnt2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   411
            masm.jmpb(WHILE_HEAD_LABEL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   412
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   413
            masm.bind(COMPARE_SMALL_STR);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   414
        } else if (supportsSSE42(crb.target)) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   415
            Register vec1 = asRegister(vectorTemp1, AMD64Kind.DOUBLE);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   416
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   417
            // Checkstyle: stop
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   418
            Label COMPARE_WIDE_VECTORS = new Label();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   419
            Label VECTOR_NOT_EQUAL = new Label();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   420
            Label COMPARE_TAIL = new Label();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   421
            // Checkstyle: resume
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   422
            int pcmpmask = 0x19;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   423
            // Setup to compare 8-char (16-byte) vectors,
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   424
            // start from first character again because it has aligned address.
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   425
            masm.movl(result, cnt2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   426
            masm.andl(cnt2, ~(stride - 1));   // cnt2 holds the vector count
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   427
            // if (ae == StrIntrinsicNode::LL) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   428
            if (kind1 == JavaKind.Byte && kind2 == JavaKind.Byte) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   429
                pcmpmask &= ~0x01;
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   430
            }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   431
            masm.jcc(ConditionFlag.Zero, COMPARE_TAIL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   432
            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   433
            if (kind1 == kind2) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   434
                masm.leaq(str1, new AMD64Address(str1, result, scale));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   435
                masm.leaq(str2, new AMD64Address(str2, result, scale));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   436
            } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   437
                masm.leaq(str1, new AMD64Address(str1, result, scale1));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   438
                masm.leaq(str2, new AMD64Address(str2, result, scale2));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   439
            }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   440
            masm.negq(result);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   441
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   442
            // pcmpestri
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   443
            // inputs:
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   444
            // vec1- substring
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   445
            // rax - negative string length (elements count)
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   446
            // mem - scanned string
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   447
            // rdx - string length (elements count)
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   448
            // pcmpmask - cmp mode: 11000 (string compare with negated result)
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   449
            // + 00 (unsigned bytes) or + 01 (unsigned shorts)
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   450
            // outputs:
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   451
            // rcx - first mismatched element index
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   452
            assert result.equals(rax) && cnt2.equals(rdx) && cnt1.equals(rcx) : "pcmpestri";
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   453
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   454
            masm.bind(COMPARE_WIDE_VECTORS);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   455
            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   456
            if (kind1 == kind2) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   457
                masm.movdqu(vec1, new AMD64Address(str1, result, scale));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   458
                masm.pcmpestri(vec1, new AMD64Address(str2, result, scale), pcmpmask);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   459
            } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   460
                masm.pmovzxbw(vec1, new AMD64Address(str1, result, scale1));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   461
                masm.pcmpestri(vec1, new AMD64Address(str2, result, scale2), pcmpmask);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   462
            }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   463
            // After pcmpestri cnt1(rcx) contains mismatched element index
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   464
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   465
            masm.jccb(ConditionFlag.Below, VECTOR_NOT_EQUAL);  // CF==1
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   466
            masm.addq(result, stride);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   467
            masm.subq(cnt2, stride);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   468
            masm.jccb(ConditionFlag.NotZero, COMPARE_WIDE_VECTORS);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   469
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   470
            // compare wide vectors tail
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   471
            masm.testq(result, result);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   472
            masm.jcc(ConditionFlag.Zero, LENGTH_DIFF_LABEL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   473
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   474
            masm.movl(cnt2, stride);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   475
            masm.movl(result, stride);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   476
            masm.negq(result);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   477
            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   478
            if (kind1 == kind2) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   479
                masm.movdqu(vec1, new AMD64Address(str1, result, scale));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   480
                masm.pcmpestri(vec1, new AMD64Address(str2, result, scale), pcmpmask);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   481
            } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   482
                masm.pmovzxbw(vec1, new AMD64Address(str1, result, scale1));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   483
                masm.pcmpestri(vec1, new AMD64Address(str2, result, scale2), pcmpmask);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   484
            }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   485
            masm.jccb(ConditionFlag.AboveEqual, LENGTH_DIFF_LABEL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   486
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   487
            // Mismatched characters in the vectors
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   488
            masm.bind(VECTOR_NOT_EQUAL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   489
            masm.addq(cnt1, result);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   490
            loadNextElements(masm, result, cnt2, str1, str2, scale, scale1, scale2, cnt1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   491
            masm.subl(result, cnt2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   492
            masm.jmpb(POP_LABEL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   493
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   494
            masm.bind(COMPARE_TAIL); // limit is zero
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   495
            masm.movl(cnt2, result);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   496
            // Fallthru to tail compare
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   497
        }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   498
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   499
        // Shift str2 and str1 to the end of the arrays, negate min
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   500
        // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   501
        if (kind1 == kind2) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   502
            masm.leaq(str1, new AMD64Address(str1, cnt2, scale));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   503
            masm.leaq(str2, new AMD64Address(str2, cnt2, scale));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   504
        } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   505
            masm.leaq(str1, new AMD64Address(str1, cnt2, scale1));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   506
            masm.leaq(str2, new AMD64Address(str2, cnt2, scale2));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   507
        }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   508
        masm.decrementl(cnt2);  // first character was compared already
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   509
        masm.negq(cnt2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   510
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   511
        // Compare the rest of the elements
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   512
        masm.bind(WHILE_HEAD_LABEL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   513
        loadNextElements(masm, result, cnt1, str1, str2, scale, scale1, scale2, cnt2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   514
        masm.subl(result, cnt1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   515
        masm.jccb(ConditionFlag.NotZero, POP_LABEL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   516
        masm.incrementq(cnt2, 1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   517
        masm.jccb(ConditionFlag.NotZero, WHILE_HEAD_LABEL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   518
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   519
        // Strings are equal up to min length. Return the length difference.
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   520
        masm.bind(LENGTH_DIFF_LABEL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   521
        masm.pop(result);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   522
        // if (ae == StrIntrinsicNode::UU) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   523
        if (kind1 == JavaKind.Char && kind2 == JavaKind.Char) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   524
            // Divide diff by 2 to get number of chars
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   525
            masm.sarl(result, 1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   526
        }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   527
        masm.jmpb(DONE_LABEL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   528
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   529
        // if (VM_Version::supports_avx512vlbw()) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   530
        if (supportsAVX512VLBW(crb.target)) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   531
            masm.bind(COMPARE_WIDE_VECTORS_LOOP_FAILED);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   532
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   533
            masm.kmovql(cnt1, k7);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   534
            masm.notq(cnt1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   535
            masm.bsfq(cnt2, cnt1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   536
            // if (ae != StrIntrinsicNode::LL) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   537
            if (kind1 != JavaKind.Byte && kind2 != JavaKind.Byte) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   538
                // Divide diff by 2 to get number of chars
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   539
                masm.sarl(cnt2, 1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   540
            }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   541
            masm.addq(result, cnt2);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   542
            // if (ae == StrIntrinsicNode::LL) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   543
            if (kind1 == JavaKind.Byte && kind2 == JavaKind.Byte) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   544
                masm.movzbl(cnt1, new AMD64Address(str2, result, Scale.Times1));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   545
                masm.movzbl(result, new AMD64Address(str1, result, Scale.Times1));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   546
            } else if (kind1 == JavaKind.Char && kind2 == JavaKind.Char) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   547
                masm.movzwl(cnt1, new AMD64Address(str2, result, scale));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   548
                masm.movzwl(result, new AMD64Address(str1, result, scale));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   549
            } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   550
                masm.movzwl(cnt1, new AMD64Address(str2, result, scale2));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   551
                masm.movzbl(result, new AMD64Address(str1, result, scale1));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   552
            }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   553
            masm.subl(result, cnt1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   554
            masm.jmpb(POP_LABEL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   555
        }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   556
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   557
        // Discard the stored length difference
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   558
        masm.bind(POP_LABEL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   559
        masm.pop(cnt1);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   560
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   561
        // That's it
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   562
        masm.bind(DONE_LABEL);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   563
        // if (ae == StrIntrinsicNode::UL) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   564
        if (kind1 == JavaKind.Char && kind2 == JavaKind.Byte) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   565
            masm.negl(result);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   566
        }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   567
    }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   568
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   569
    private void loadNextElements(AMD64MacroAssembler masm, Register elem1, Register elem2, Register str1, Register str2,
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   570
                    AMD64Address.Scale scale, AMD64Address.Scale scale1,
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   571
                    AMD64Address.Scale scale2, Register index) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   572
        // if (ae == StrIntrinsicNode::LL) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   573
        if (kind1 == JavaKind.Byte && kind2 == JavaKind.Byte) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   574
            masm.movzbl(elem1, new AMD64Address(str1, index, scale, 0));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   575
            masm.movzbl(elem2, new AMD64Address(str2, index, scale, 0));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   576
            // } else if (ae == StrIntrinsicNode::UU) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   577
        } else if (kind1 == JavaKind.Char && kind2 == JavaKind.Char) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   578
            masm.movzwl(elem1, new AMD64Address(str1, index, scale, 0));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   579
            masm.movzwl(elem2, new AMD64Address(str2, index, scale, 0));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   580
        } else {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   581
            masm.movzbl(elem1, new AMD64Address(str1, index, scale1, 0));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   582
            masm.movzwl(elem2, new AMD64Address(str2, index, scale2, 0));
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   583
        }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   584
    }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   585
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   586
    private static final Unsafe UNSAFE = initUnsafe();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   587
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   588
    private static Unsafe initUnsafe() {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   589
        try {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   590
            return Unsafe.getUnsafe();
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   591
        } catch (SecurityException se) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   592
            try {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   593
                Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   594
                theUnsafe.setAccessible(true);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   595
                return (Unsafe) theUnsafe.get(Unsafe.class);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   596
            } catch (Exception e) {
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   597
                throw new RuntimeException("exception while trying to get Unsafe", e);
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   598
            }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   599
        }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   600
    }
e06f9607f370 8198969: Update Graal
iveresov
parents:
diff changeset
   601
}